Example #1
0
        void CopyBufferToImage(CommandBuffer cmdBuffer, ImageData imageData, Buffer imageBuffer)
        {
            var subresource = new ImageSubresourceLayers(ImageAspectFlags.Color, 0, 0, 1);
            var imageCopy   = new BufferImageCopy(0, 0, 0, subresource, new Offset3D(0, 0, 0), new Extent3D(imageData.Width, imageData.Height, 1));

            cmdBuffer.CopyBufferToImage(imageBuffer, imageData.Image, ImageLayout.TransferDstOptimal, new BufferImageCopy[] { imageCopy });
        }
Example #2
0
        void CopyImageToBuffer(CommandBuffer cmdBuffer, ImageData imageData, Buffer imageBuffer, uint width, uint height)
        {
            var subresource = new ImageSubresourceLayers(ImageAspectFlags.Color, 0, 0, 1);
            var imageCopy   = new BufferImageCopy(0, width, height, subresource, new Offset3D(0, 0, 0), new Extent3D(width, height, 0));

            cmdBuffer.CopyImageToBuffer(imageData.Image, ImageLayout.TransferSrcOptimal, imageBuffer, new[] { imageCopy });
        }
Example #3
0
        private void CopyFromOrToBuffer(
            CommandBuffer commandBuffer,
            VkBuffer buffer,
            Image image,
            int size,
            bool to,
            int x,
            int y,
            int width,
            int height)
        {
            var aspectFlags = Info.Format.ConvertAspectFlags();

            if (aspectFlags == (ImageAspectFlags.ImageAspectDepthBit | ImageAspectFlags.ImageAspectStencilBit))
            {
                aspectFlags = ImageAspectFlags.ImageAspectDepthBit;
            }

            var sl = new ImageSubresourceLayers(aspectFlags, (uint)FirstLevel, (uint)FirstLayer, 1);

            var extent = new Extent3D((uint)width, (uint)height, 1);

            var region = new BufferImageCopy(0, (uint)width, (uint)height, sl, new Offset3D(x, y, 0), extent);

            if (to)
            {
                _gd.Api.CmdCopyImageToBuffer(commandBuffer, image, ImageLayout.General, buffer, 1, region);
            }
            else
            {
                _gd.Api.CmdCopyBufferToImage(commandBuffer, buffer, image, ImageLayout.General, 1, region);
            }
        }
Example #4
0
        void CopyBufferToImage(Queue queue, CommandPool cmdPool, ImageData imageData, Buffer imageBuffer)
        {
            var cmdBuffers = AllocateCommandBuffers(cmdPool, 1);
            var cmdBuffer  = cmdBuffers[0];

            var beginInfo = new CommandBufferBeginInfo();

            cmdBuffer.Begin(beginInfo);

            PipelineBarrierSetLayout(cmdBuffer, imageData.Image, ImageLayout.Preinitialized, ImageLayout.TransferDstOptimal, AccessFlags.HostWrite, AccessFlags.TransferWrite);

            var subresource = new ImageSubresourceLayers(ImageAspectFlags.Color, 0, 0, 1);
            var imageCopy   = new BufferImageCopy(0, 0, 0, subresource, new Offset3D(0, 0, 0), new Extent3D(imageData.Width, imageData.Height, 1));

            cmdBuffer.CopyBufferToImage(imageBuffer, imageData.Image, ImageLayout.TransferDstOptimal, new BufferImageCopy[] { imageCopy });

            PipelineBarrierSetLayout(cmdBuffer, imageData.Image, ImageLayout.TransferDstOptimal, ImageLayout.ColorAttachmentOptimal, AccessFlags.TransferWrite, AccessFlags.ColorAttachmentWrite);

            cmdBuffer.End();

            var submitInfo = new SubmitInfo(null, null, new[] { cmdBuffer }, null);

            queue.Submit(new[] { submitInfo });
            submitInfo.Dispose();
            queue.WaitIdle();

            device.FreeCommandBuffers(cmdPool, new[] { cmdBuffer });
        }
Example #5
0
 public void CmdCopyBufferToImage(VulkanBuffer srcBuffer, Image dstImage, ImageLayout dstImageLayout, BufferImageCopy?pRegion)
 {
     unsafe {
         BufferImageCopy  valpRegion = pRegion ?? default(BufferImageCopy);
         BufferImageCopy *ptrpRegion = pRegion != null ? &valpRegion : (BufferImageCopy *)IntPtr.Zero;
         Interop.NativeMethods.vkCmdCopyBufferToImage(this.m, srcBuffer != null ? srcBuffer.m : default(UInt64), dstImage != null ? dstImage.m : default(UInt64), dstImageLayout, (UInt32)(pRegion != null ? 1 : 0), ptrpRegion);
     }
 }
Example #6
0
 public void CmdCopyImageToBuffer(Image srcImage, ImageLayout srcImageLayout, VulkanBuffer dstBuffer, BufferImageCopy?pRegion)
 {
     unsafe {
         BufferImageCopy  valpRegion = pRegion ?? default(BufferImageCopy);
         BufferImageCopy *ptrpRegion = pRegion != null ? &valpRegion : (BufferImageCopy *)IntPtr.Zero;
         Interop.NativeMethods.vkCmdCopyImageToBuffer(this.m, srcImage != null ? srcImage.m : default(UInt64), srcImageLayout, dstBuffer != null ? dstBuffer.m : default(UInt64), (UInt32)(pRegion != null ? 1 : 0), ptrpRegion);
     }
 }
Example #7
0
        private void CopyFromOrToBuffer(
            CommandBuffer commandBuffer,
            VkBuffer buffer,
            Image image,
            int size,
            bool to,
            int dstLayer,
            int dstLevel,
            int x,
            int y,
            int width,
            int height)
        {
            var aspectFlags = Info.Format.ConvertAspectFlags();

            if (aspectFlags == (ImageAspectFlags.ImageAspectDepthBit | ImageAspectFlags.ImageAspectStencilBit))
            {
                aspectFlags = ImageAspectFlags.ImageAspectDepthBit;
            }

            var sl = new ImageSubresourceLayers(aspectFlags, (uint)(FirstLevel + dstLevel), (uint)(FirstLayer + dstLayer), 1);

            var extent = new Extent3D((uint)width, (uint)height, 1);

            int rowLengthAlignment = Info.BlockWidth;

            // We expect all data being written into the texture to have a stride aligned by 4.
            if (!to && Info.BytesPerPixel < 4)
            {
                rowLengthAlignment = 4 / Info.BytesPerPixel;
            }

            var region = new BufferImageCopy(
                0,
                (uint)AlignUpNpot(width, rowLengthAlignment),
                (uint)AlignUpNpot(height, Info.BlockHeight),
                sl,
                new Offset3D(x, y, 0),
                extent);

            if (to)
            {
                _gd.Api.CmdCopyImageToBuffer(commandBuffer, image, ImageLayout.General, buffer, 1, region);
            }
            else
            {
                _gd.Api.CmdCopyBufferToImage(commandBuffer, buffer, image, ImageLayout.General, 1, region);
            }
        }
Example #8
0
        void IInternalTexture.Upload(
            HostBuffer stagingBuffer,
            TransientExecutor executor,
            Image image,
            ImageAspects aspects)
        {
            if (stagingBuffer == null)
            {
                throw new ArgumentNullException(nameof(stagingBuffer));
            }
            if (executor == null)
            {
                throw new ArgumentNullException(nameof(executor));
            }

            //Write all the faces to the staging buffer and create copy commands
            long offset = 0;

            BufferImageCopy[] copyRegions = new BufferImageCopy[faces.Length];
            for (int i = 0; i < faces.Length; i++)
            {
                copyRegions[i] = new BufferImageCopy
                {
                    BufferOffset      = offset,
                    BufferRowLength   = 0,
                    BufferImageHeight = 0,
                    ImageSubresource  = new ImageSubresourceLayers(
                        aspectMask: aspects, mipLevel: 0, baseArrayLayer: i, layerCount: 1),
                    ImageOffset = new Offset3D(x: 0, y: 0, z: 0),
                    ImageExtent = new Extent3D(
                        width: size.X,
                        height: size.Y,
                        depth: 1)
                };
                offset += faces[i].Write(stagingBuffer, offset);
            }

            //Copy our staging buffer to the image
            executor.ExecuteBlocking(commandBuffer =>
            {
                commandBuffer.CmdCopyBufferToImage(
                    srcBuffer: stagingBuffer.VulkanBuffer,
                    dstImage: image,
                    dstImageLayout: ImageLayout.TransferDstOptimal,
                    regions: copyRegions);
            });
        }
        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)
            {
                // 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.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 + 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, 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),
            };

            lock (GraphicsDevice.QueueLock)
            {
                GraphicsDevice.NativeCommandQueue.Submit(1, &submitInfo, Fence.Null);
                GraphicsDevice.NativeCommandQueue.WaitIdle();
                commandBuffer.Reset(CommandBufferResetFlags.None);
            }
        }
Example #10
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);
        }
Example #11
0
 public unsafe void CopyBufferToImage(Buffer sourceBuffer, Image destinationImage, ImageLayout destinationImageLayout, uint regionCount, BufferImageCopy* regions)
 {
     vkCmdCopyBufferToImage(this, sourceBuffer, destinationImage, destinationImageLayout, regionCount, regions);
 }
Example #12
0
 public unsafe void CopyImageToBuffer(Image sourceImage, ImageLayout sourceImageLayout, Buffer destinationBuffer, uint regionCount, BufferImageCopy* regions)
 {
     vkCmdCopyImageToBuffer(this, sourceImage, sourceImageLayout, destinationBuffer, regionCount, regions);
 }
Example #13
0
        public Texture2D(
            string name, Graphics graphics, TextureData2D data, bool premultiply = true
            )
        {
            Name     = name;
            Graphics = graphics;

            // Create image
            var image = Graphics.Device.CreateImage(new ImageCreateInfo
            {
                ImageType     = ImageType.Image2D,
                Format        = data.Format,
                MipLevels     = data.MipMaps.Length,
                ArrayLayers   = 1,
                Samples       = SampleCounts.Count1,
                Tiling        = ImageTiling.Optimal,
                SharingMode   = SharingMode.Exclusive,
                InitialLayout = ImageLayout.Undefined,
                Extent        = new Extent3D(data.MipMaps[0].Extent.Width, data.MipMaps[0].Extent.Height, 1),
                Usage         = ImageUsages.Sampled | ImageUsages.TransferDst
            });

            Image = new VKImage(
                image, data.Format, data.MipMaps[0].Extent,
                new ImageSubresourceRange(ImageAspects.Color, 0, data.MipMaps.Length, 0, 1
                                          ));
            var memReq = Image.Image.GetMemoryRequirements();

            DeviceMemory = Graphics.Device.AllocateMemory(new MemoryAllocateInfo(
                                                              allocationSize: memReq.Size,
                                                              memoryTypeIndex: Graphics.GetMemoryTypeIndex(memReq.MemoryTypeBits, MemoryProperties.DeviceLocal)
                                                              ));
            Image.Image.BindMemory(DeviceMemory);

            // Copy data to staging buffer
            var staging = VKBuffer <byte> .StagingBuffer($"{nameof(Texture2D)} staging buffer", Graphics, data.Size);

            unsafe
            {
                var dest = staging.Map(0, data.Size);
                foreach (var mip in data.MipMaps)
                {
                    fixed(byte *src = mip.Data)
                    {
                        if (premultiply)
                        {
                            switch (data.Format)
                            {
                            default:
                                throw new NotImplementedException(
                                          $"Premultiplying is not implemented for format: {data.Format}"
                                          );

                            case Format.B8G8R8A8UNorm:
                                for (var i = 0; i < mip.Size; i += 4)
                                {
                                    var b = src[i];
                                    var g = src[i + 1];
                                    var r = src[i + 2];
                                    var a = src[i + 3];
                                    b           = (byte)(b * (a / 255f));
                                    g           = (byte)(g * (a / 255f));
                                    r           = (byte)(r * (a / 255f));
                                    dest[i]     = b;
                                    dest[i + 1] = g;
                                    dest[i + 2] = r;
                                    dest[i + 3] = a;
                                }
                                break;
                            }
                        }
                        else
                        {
                            System.Buffer.MemoryCopy(src, dest, mip.Size, mip.Size);
                        }
                        dest += mip.Size;
                    }
                }
                staging.Unmap();
            }

            // Create copy regions
            var regions = new BufferImageCopy[data.MipMaps.Length];
            var offset  = 0L;

            for (var i = 0; i < regions.Length; i++)
            {
                regions[i] = new BufferImageCopy
                {
                    ImageSubresource = new ImageSubresourceLayers(ImageAspects.Color, i, 0, 1),
                    ImageExtent      = new Extent3D(data.MipMaps[0].Extent.Width, data.MipMaps[0].Extent.Height, 1),
                    BufferOffset     = offset
                };
                offset += data.MipMaps[i].Size;
            }

            // Create command buffer
            var range  = new ImageSubresourceRange(ImageAspects.Color, 0, data.MipMaps.Length, 0, 1);
            var buffer = Graphics.TransferQueueFamily.CreateCommandBuffers(CommandBufferLevel.Primary, 1)[0];

            buffer.Begin(new CommandBufferBeginInfo(CommandBufferUsages.OneTimeSubmit));
            buffer.CmdPipelineBarrier(
                PipelineStages.TopOfPipe, PipelineStages.Transfer,
                imageMemoryBarriers: new ImageMemoryBarrier[]
            {
                new ImageMemoryBarrier(
                    Image.Image, range,
                    Accesses.None, Accesses.TransferWrite,
                    ImageLayout.Undefined, ImageLayout.TransferDstOptimal
                    )
            }
                );
            buffer.CmdCopyBufferToImage(staging.Buffer, Image.Image, ImageLayout.TransferDstOptimal, regions);
            buffer.CmdPipelineBarrier(
                PipelineStages.Transfer, PipelineStages.FragmentShader,
                imageMemoryBarriers: new ImageMemoryBarrier[]
            {
                new ImageMemoryBarrier(
                    Image.Image, range,
                    Accesses.TransferWrite, Accesses.ShaderRead,
                    ImageLayout.TransferDstOptimal, ImageLayout.ShaderReadOnlyOptimal
                    )
            }
                );
            buffer.End();

            // Submit the buffer
            var fence = Graphics.Device.CreateFence(new FenceCreateInfo());

            Graphics.GraphicsQueueFamily.HighestPriority.Submit(
                new SubmitInfo(
                    commandBuffers: new CommandBuffer[] { buffer }
                    ),
                fence
                );
            fence.Wait();

            // Clean up
            fence.Dispose();
            staging.Dispose();
        }
Example #14
0
        private void CopyFromOrToBuffer(
            CommandBuffer commandBuffer,
            VkBuffer buffer,
            Image image,
            int size,
            bool to,
            int dstLayer,
            int dstLevel,
            int dstLayers,
            int dstLevels,
            bool singleSlice)
        {
            bool is3D   = Info.Target == Target.Texture3D;
            int  width  = Info.Width;
            int  height = Info.Height;
            int  depth  = is3D && !singleSlice ? Info.Depth : 1;
            int  layer  = is3D ? 0 : dstLayer;
            int  layers = dstLayers;
            int  levels = dstLevels;

            int offset = 0;

            for (int level = 0; level < levels; level++)
            {
                int mipSize = GetBufferDataLength(Info.GetMipSize(level));

                int endOffset = offset + mipSize;

                if ((uint)endOffset > (uint)size)
                {
                    break;
                }

                int rowLength = (Info.GetMipStride(level) / Info.BytesPerPixel) * Info.BlockWidth;

                var aspectFlags = Info.Format.ConvertAspectFlags();

                if (aspectFlags == (ImageAspectFlags.ImageAspectDepthBit | ImageAspectFlags.ImageAspectStencilBit))
                {
                    aspectFlags = ImageAspectFlags.ImageAspectDepthBit;
                }

                var sl = new ImageSubresourceLayers(
                    aspectFlags,
                    (uint)(FirstLevel + dstLevel + level),
                    (uint)(FirstLayer + layer),
                    (uint)layers);

                var extent = new Extent3D((uint)width, (uint)height, (uint)depth);

                int z = is3D ? dstLayer : 0;

                var region = new BufferImageCopy((ulong)offset, (uint)rowLength, (uint)height, sl, new Offset3D(0, 0, z), extent);

                if (to)
                {
                    _gd.Api.CmdCopyImageToBuffer(commandBuffer, image, ImageLayout.General, buffer, 1, region);
                }
                else
                {
                    _gd.Api.CmdCopyBufferToImage(commandBuffer, buffer, image, ImageLayout.General, 1, region);
                }

                offset += mipSize;

                width  = Math.Max(1, width >> 1);
                height = Math.Max(1, height >> 1);

                if (Info.Target == Target.Texture3D)
                {
                    depth = Math.Max(1, depth >> 1);
                }
            }
        }
Example #15
0
 internal static unsafe extern void vkCmdCopyImageToBuffer(CommandBuffer commandBuffer, Image sourceImage, ImageLayout sourceImageLayout, Buffer destinationBuffer, uint regionCount, BufferImageCopy* regions);
Example #16
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);
            }
        }
Example #17
0
        internal static VulkanImage Texture2D(VulkanContext ctx, TextureData tex2D)
        {
            Buffer stagingBuffer = ctx.Device.CreateBuffer(
                new BufferCreateInfo(tex2D.Mipmaps[0].Size, BufferUsages.TransferSrc));
            MemoryRequirements stagingMemReq = stagingBuffer.GetMemoryRequirements();
            int heapIndex = ctx.MemoryProperties.MemoryTypes.IndexOf(
                stagingMemReq.MemoryTypeBits, MemoryProperties.HostVisible);
            DeviceMemory stagingMemory = ctx.Device.AllocateMemory(
                new MemoryAllocateInfo(stagingMemReq.Size, heapIndex));

            stagingBuffer.BindMemory(stagingMemory);

            IntPtr ptr = stagingMemory.Map(0, stagingMemReq.Size);

            Interop.Write(ptr, tex2D.Mipmaps[0].Data);
            stagingMemory.Unmap();

            // Setup buffer copy regions for each mip level.
            var bufferCopyRegions = new BufferImageCopy[tex2D.Mipmaps.Length];
            int offset            = 0;

            for (int i = 0; i < bufferCopyRegions.Length; i++)
            {
                bufferCopyRegions = new[]
                {
                    new BufferImageCopy
                    {
                        ImageSubresource = new ImageSubresourceLayers(ImageAspects.Color, i, 0, 1),
                        ImageExtent      = tex2D.Mipmaps[0].Extent,
                        BufferOffset     = offset
                    }
                };
                offset += tex2D.Mipmaps[i].Size;
            }

            // Create optimal tiled target image.
            Image image = ctx.Device.CreateImage(new ImageCreateInfo
            {
                ImageType     = ImageType.Image2D,
                Format        = tex2D.Format,
                MipLevels     = tex2D.Mipmaps.Length,
                ArrayLayers   = 1,
                Samples       = SampleCounts.Count1,
                Tiling        = ImageTiling.Optimal,
                SharingMode   = SharingMode.Exclusive,
                InitialLayout = ImageLayout.Undefined,
                Extent        = tex2D.Mipmaps[0].Extent,
                Usage         = ImageUsages.Sampled | ImageUsages.TransferDst
            });
            MemoryRequirements imageMemReq = image.GetMemoryRequirements();
            int imageHeapIndex             = ctx.MemoryProperties.MemoryTypes.IndexOf(
                imageMemReq.MemoryTypeBits, MemoryProperties.DeviceLocal);
            DeviceMemory memory = ctx.Device.AllocateMemory(new MemoryAllocateInfo(imageMemReq.Size, imageHeapIndex));

            image.BindMemory(memory);

            var subresourceRange = new ImageSubresourceRange(ImageAspects.Color, 0, tex2D.Mipmaps.Length, 0, 1);

            // Copy the data from staging buffers to device local buffers.
            CommandBuffer cmdBuffer = ctx.GraphicsCommandPool.AllocateBuffers(new CommandBufferAllocateInfo(CommandBufferLevel.Primary, 1))[0];

            cmdBuffer.Begin(new CommandBufferBeginInfo(CommandBufferUsages.OneTimeSubmit));
            cmdBuffer.CmdPipelineBarrier(PipelineStages.TopOfPipe, PipelineStages.TopOfPipe,
                                         imageMemoryBarriers: new[]
            {
                new ImageMemoryBarrier(
                    image, subresourceRange,
                    0, Accesses.TransferWrite,
                    ImageLayout.Undefined, ImageLayout.TransferDstOptimal)
            });
            cmdBuffer.CmdCopyBufferToImage(stagingBuffer, image, ImageLayout.TransferDstOptimal, bufferCopyRegions);
            cmdBuffer.CmdPipelineBarrier(PipelineStages.TopOfPipe, PipelineStages.TopOfPipe,
                                         imageMemoryBarriers: new[]
            {
                new ImageMemoryBarrier(
                    image, subresourceRange,
                    Accesses.TransferWrite, Accesses.ShaderRead,
                    ImageLayout.TransferDstOptimal, ImageLayout.ShaderReadOnlyOptimal)
            });
            cmdBuffer.End();

            // Submit.
            Fence fence = ctx.Device.CreateFence();

            ctx.GraphicsQueue.Submit(new SubmitInfo(commandBuffers: new[] { cmdBuffer }), fence);
            fence.Wait();

            // Cleanup staging resources.
            fence.Dispose();
            stagingMemory.Dispose();
            stagingBuffer.Dispose();

            // Create image view.
            ImageView view = image.CreateView(new ImageViewCreateInfo(tex2D.Format, subresourceRange));

            return(new VulkanImage(image, memory, view, tex2D.Format));
        }
Example #18
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);
        }
Example #19
0
 internal static unsafe extern void vkCmdCopyBufferToImage(CommandBuffer commandBuffer, Buffer sourceBuffer, Image destinationImage, ImageLayout destinationImageLayout, uint regionCount, BufferImageCopy* regions);