Exemplo n.º 1
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 });
        }
Exemplo n.º 2
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);
            }
        }
Exemplo n.º 3
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 });
        }
Exemplo n.º 4
0
        internal void Copy(Image sourceImage, Image destinationImage, uint width, uint height)
        {
            var transferBuffers = this.BeginSingleTimeCommand(this.transferCommandPool);

            ImageSubresourceLayers subresource = new ImageSubresourceLayers
            {
                AspectMask     = ImageAspectFlags.Color,
                BaseArrayLayer = 0,
                LayerCount     = 1,
                MipLevel       = 0
            };

            ImageCopy region = new ImageCopy
            {
                DestinationSubresource = subresource,
                SourceSubresource      = subresource,
                SourceOffset           = new Offset3D(),
                DestinationOffset      = new Offset3D(),
                Extent = new Extent3D
                {
                    Width  = width,
                    Height = height,
                    Depth  = 1
                }
            };

            transferBuffers[0].CopyImage(sourceImage, ImageLayout.TransferSourceOptimal, destinationImage, ImageLayout.TransferDestinationOptimal, region);

            this.EndSingleTimeCommand(transferBuffers, this.transferCommandPool, this.transferQueue);
        }
Exemplo n.º 5
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 });
        }
Exemplo n.º 6
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);
            }
        }
Exemplo n.º 7
0
        public unsafe void Update(Rectangle <uint> bounds, ReadOnlySpan <byte> data)
        {
            Vk vk = _renderer.Vk;

            Buffer <byte> stagingBuffer = new(BufferUsageFlags.BufferUsageTransferSrcBit,
                                              MemoryPropertyFlags.MemoryPropertyHostVisibleBit | MemoryPropertyFlags.MemoryPropertyHostCoherentBit, _renderer);

            stagingBuffer.Update(data);

            TransitionImageLayout(ImageLayout.ShaderReadOnlyOptimal, ImageLayout.TransferDstOptimal);

            CommandBuffer commandBuffer = BeginImageCommandBuffer();

            BufferImageCopy bufferImageCopy = new()
            {
                BufferOffset      = 0,
                BufferRowLength   = 0,
                BufferImageHeight = 0,

                ImageSubresource = new ImageSubresourceLayers()
                {
                    AspectMask     = ImageAspectFlags.ImageAspectColorBit,
                    MipLevel       = 0,
                    BaseArrayLayer = 0,
                    LayerCount     = 1
                },

                ImageOffset = new Offset3D()
                {
                    X = 0,
                    Y = 0,
                    Z = 0
                },
                ImageExtent = new Extent3D()
                {
                    Width  = Size.X,
                    Height = Size.Y,
                    Depth  = 1
                }
            };

            vk.CmdCopyBufferToImage(commandBuffer, stagingBuffer.Handle, _image, ImageLayout.TransferDstOptimal, 1, bufferImageCopy);

            EndImageCommandBuffer(commandBuffer);
            TransitionImageLayout(ImageLayout.TransferDstOptimal, ImageLayout.ShaderReadOnlyOptimal);

            stagingBuffer.Dispose();
        }
Exemplo n.º 8
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);
                }
            }
        }
Exemplo n.º 9
0
        public unsafe void Mipmaps()
        {
            PhysicalDevice physicalDevice = _renderer.Params.PhysicalDevice;
            Vk             vk             = _renderer.Vk;

            vk.GetPhysicalDeviceFormatProperties(physicalDevice, _format, out FormatProperties formatProperties);
            if (!formatProperties.OptimalTilingFeatures.HasFlag(FormatFeatureFlags.FormatFeatureSampledImageFilterLinearBit)) // bitting not supported.
            {
                return;
            }

            CommandBuffer commandBuffer = BeginImageCommandBuffer();

            uint mipWidth  = Size.X;
            uint mipHeight = Size.Y;

            ImageMemoryBarrier barrier = new()
            {
                SType = StructureType.ImageMemoryBarrier,

                Image = _image,
                SrcQueueFamilyIndex = Vk.QueueFamilyIgnored,
                DstQueueFamilyIndex = Vk.QueueFamilyIgnored,
                SubresourceRange    = new ImageSubresourceRange()
                {
                    AspectMask     = ImageAspectFlags.ImageAspectColorBit,
                    BaseArrayLayer = 0,
                    LayerCount     = 1,
                    BaseMipLevel   = 0,
                    LevelCount     = 1
                }
            };

            for (uint i = 1; i < _mipLevelCount; i++)
            {
                barrier.SubresourceRange.BaseMipLevel = i - 1;
                barrier.OldLayout     = ImageLayout.TransferDstOptimal;
                barrier.NewLayout     = ImageLayout.TransferSrcOptimal;
                barrier.SrcAccessMask = AccessFlags.AccessTransferWriteBit;
                barrier.DstAccessMask = AccessFlags.AccessTransferReadBit;

                vk.CmdPipelineBarrier(commandBuffer, PipelineStageFlags.PipelineStageTransferBit, PipelineStageFlags.PipelineStageTransferBit, 0, 0, null, 0, null, 1, barrier);

                ImageBlit blit = new()
                {
                    SrcOffsets = new ImageBlit.SrcOffsetsBuffer()
                    {
                        Element0 = new Offset3D()
                        {
                            X = 0,
                            Y = 0,
                            Z = 0,
                        },
                        Element1 = new Offset3D()
                        {
                            X = (int)mipWidth,
                            Y = (int)mipHeight,
                            Z = 1
                        }
                    },
                    SrcSubresource = new ImageSubresourceLayers()
                    {
                        AspectMask     = ImageAspectFlags.ImageAspectColorBit,
                        MipLevel       = i - 1,
                        BaseArrayLayer = 0,
                        LayerCount     = 1
                    },
                    DstOffsets = new ImageBlit.DstOffsetsBuffer()
                    {
                        Element0 = new Offset3D()
                        {
                            X = 0,
                            Y = 0,
                            Z = 0
                        },
                        Element1 = new Offset3D()
                        {
                            X = (int)((mipWidth > 1) ? mipWidth / 2 : 1),
                            Y = (int)((mipHeight > 1) ? mipHeight / 2 : 1),
                            Z = 1
                        }
                    },
                    DstSubresource = new ImageSubresourceLayers()
                    {
                        AspectMask     = ImageAspectFlags.ImageAspectColorBit,
                        MipLevel       = i,
                        BaseArrayLayer = 0,
                        LayerCount     = 1
                    }
                };

                vk.CmdBlitImage(commandBuffer, _image, ImageLayout.TransferSrcOptimal,
                                _image, ImageLayout.TransferDstOptimal, 1, blit, HasFlag(ImageFlags.Nearest) ? Filter.Nearest : Filter.Linear);

                barrier.OldLayout     = ImageLayout.TransferSrcOptimal;
                barrier.NewLayout     = ImageLayout.ShaderReadOnlyOptimal;
                barrier.SrcAccessMask = AccessFlags.AccessTransferReadBit;
                barrier.DstAccessMask = AccessFlags.AccessShaderReadBit;

                vk.CmdPipelineBarrier(commandBuffer, PipelineStageFlags.PipelineStageTransferBit, PipelineStageFlags.PipelineStageFragmentShaderBit, 0, 0, null, 0, null, 1, barrier);

                mipWidth  /= 2;
                mipHeight /= 2;
            }

            barrier.SubresourceRange.BaseMipLevel = _mipLevelCount - 1;
            barrier.OldLayout     = ImageLayout.TransferDstOptimal;
            barrier.NewLayout     = ImageLayout.ShaderReadOnlyOptimal;
            barrier.SrcAccessMask = AccessFlags.AccessTransferWriteBit;
            barrier.DstAccessMask = AccessFlags.AccessShaderReadBit;

            vk.CmdPipelineBarrier(commandBuffer, PipelineStageFlags.PipelineStageTransferBit, PipelineStageFlags.PipelineStageFragmentShaderBit, 0, 0, null, 0, null, 1, barrier);

            EndImageCommandBuffer(commandBuffer);
        }
Exemplo n.º 10
0
        private unsafe CommandBuffer BeginImageCommandBuffer()
        {
            Device device = _renderer.Params.Device;
            Vk     vk     = _renderer.Vk;

            CommandBufferAllocateInfo commandBufferAllocateInfo = new()
            {
                SType = StructureType.CommandBufferAllocateInfo,

                CommandBufferCount = 1,
                CommandPool        = _renderer.ImageTransitionPool
            };

            _renderer.AssertVulkan(vk.AllocateCommandBuffers(device, commandBufferAllocateInfo, out CommandBuffer commandBuffer));

            CommandBufferBeginInfo commandBufferBeginInfo = new()
            {
                SType = StructureType.CommandBufferBeginInfo,
                Flags = CommandBufferUsageFlags.CommandBufferUsageOneTimeSubmitBit,

                PInheritanceInfo = null
            };

            _renderer.AssertVulkan(vk.BeginCommandBuffer(commandBuffer, commandBufferBeginInfo));

            return(commandBuffer);
        }

        private unsafe void EndImageCommandBuffer(CommandBuffer commandBuffer)
        {
            Device device = _renderer.Params.Device;
            Vk     vk     = _renderer.Vk;

            _renderer.AssertVulkan(vk.EndCommandBuffer(commandBuffer));

            SubmitInfo submitInfo = new()
            {
                SType = StructureType.SubmitInfo,

                CommandBufferCount = 1,
                PCommandBuffers    = &commandBuffer,

                SignalSemaphoreCount = 0,
                PSignalSemaphores    = null,
                WaitSemaphoreCount   = 0,
                PWaitSemaphores      = null,
                PWaitDstStageMask    = null
            };

            _renderer.AssertVulkan(vk.QueueSubmit(_renderer.ImageTransitionQueue, 1, submitInfo, default));
            _renderer.AssertVulkan(vk.QueueWaitIdle(_renderer.ImageTransitionQueue));

            vk.FreeCommandBuffers(device, _renderer.ImageTransitionPool, 1, commandBuffer);
        }

        private unsafe void TransitionImageLayout(ImageLayout oldLayout, ImageLayout newLayout)
        {
            Vk vk = _renderer.Vk;

            CommandBuffer commandBuffer = BeginImageCommandBuffer();

            ImageMemoryBarrier imageMemoryBarrier = new()
            {
                SType = StructureType.ImageMemoryBarrier,

                OldLayout = oldLayout,
                NewLayout = newLayout,

                SrcQueueFamilyIndex = Vk.QueueFamilyIgnored,
                DstQueueFamilyIndex = Vk.QueueFamilyIgnored,

                Image = _image,

                SubresourceRange = new ImageSubresourceRange()
                {
                    AspectMask     = ImageAspectFlags.ImageAspectColorBit,
                    BaseArrayLayer = 0,
                    LayerCount     = 1,
                    BaseMipLevel   = 0,
                    LevelCount     = _mipLevelCount
                },

                SrcAccessMask = 0,
                DstAccessMask = 0
            };

            if ((oldLayout == ImageLayout.Undefined) && (newLayout == ImageLayout.TransferDstOptimal))
            {
                imageMemoryBarrier.SrcAccessMask = 0;
                imageMemoryBarrier.DstAccessMask = AccessFlags.AccessTransferWriteBit;

                vk.CmdPipelineBarrier(commandBuffer, PipelineStageFlags.PipelineStageTopOfPipeBit, PipelineStageFlags.PipelineStageTransferBit, 0, 0, null, 0, null, 1, imageMemoryBarrier);
            }
            else if ((oldLayout == ImageLayout.TransferDstOptimal) && (newLayout == ImageLayout.ShaderReadOnlyOptimal))
            {
                imageMemoryBarrier.SrcAccessMask = AccessFlags.AccessTransferWriteBit;
                imageMemoryBarrier.DstAccessMask = AccessFlags.AccessShaderReadBit;

                vk.CmdPipelineBarrier(commandBuffer, PipelineStageFlags.PipelineStageTransferBit, PipelineStageFlags.PipelineStageFragmentShaderBit, 0, 0, null, 0, null, 1, imageMemoryBarrier);
            }
            else if ((oldLayout == ImageLayout.ShaderReadOnlyOptimal) && (newLayout == ImageLayout.TransferDstOptimal))
            {
                imageMemoryBarrier.SrcAccessMask = AccessFlags.AccessShaderReadBit;
                imageMemoryBarrier.DstAccessMask = AccessFlags.AccessTransferWriteBit;

                vk.CmdPipelineBarrier(commandBuffer, PipelineStageFlags.PipelineStageFragmentShaderBit, PipelineStageFlags.PipelineStageTransferBit, 0, 0, null, 0, null, 1, imageMemoryBarrier);
            }

            EndImageCommandBuffer(commandBuffer);
        }

        private void CopyBufferToImage(Buffer <byte> source)
        {
            Vk vk = _renderer.Vk;

            CommandBuffer commandBuffer = BeginImageCommandBuffer();

            BufferImageCopy bufferImageCopy = new()
            {
                BufferOffset      = 0,
                BufferRowLength   = 0,
                BufferImageHeight = 0,

                ImageSubresource = new ImageSubresourceLayers()
                {
                    AspectMask     = ImageAspectFlags.ImageAspectColorBit,
                    MipLevel       = 0,
                    BaseArrayLayer = 0,
                    LayerCount     = 1
                },

                ImageOffset = new Offset3D()
                {
                    X = 0,
                    Y = 0,
                    Z = 0
                },
                ImageExtent = new Extent3D()
                {
                    Width  = Size.X,
                    Height = Size.Y,
                    Depth  = 1
                }
            };

            vk.CmdCopyBufferToImage(commandBuffer, source.Handle, _image, ImageLayout.TransferDstOptimal, 1, bufferImageCopy);

            EndImageCommandBuffer(commandBuffer);
        }