Beispiel #1
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();
        }
Beispiel #2
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);
        }