private static void BlitImage(
            ImageAspects aspectMask,
            Image fromImage,
            IntRect fromRegion,
            int fromMipLevel,
            int fromLayerCount,
            Image toImage,
            IntRect toRegion,
            int toMipLevel,
            int toLayerCount,
            TransientExecutor executor)
        {
            ImageBlit blit = new ImageBlit
            {
                SrcSubresource = new ImageSubresourceLayers(
                    aspectMask,
                    fromMipLevel,
                    baseArrayLayer: 0,
                    fromLayerCount),
                SrcOffset1     = new Offset3D(fromRegion.Min.X, fromRegion.Min.Y, 0),
                SrcOffset2     = new Offset3D(fromRegion.Max.X, fromRegion.Max.Y, 1),
                DstSubresource = new ImageSubresourceLayers(
                    aspectMask,
                    toMipLevel,
                    baseArrayLayer: 0,
                    toLayerCount),
                DstOffset1 = new Offset3D(toRegion.Min.X, toRegion.Min.Y, 0),
                DstOffset2 = new Offset3D(toRegion.Max.X, toRegion.Max.Y, 1)
            };

            //Execute the blit
            executor.ExecuteBlocking(commandBuffer =>
            {
                commandBuffer.CmdBlitImage(
                    srcImage: fromImage,
                    srcImageLayout: ImageLayout.TransferSrcOptimal,
                    dstImage: toImage,
                    dstImageLayout: ImageLayout.TransferDstOptimal,
                    regions:  new [] { blit },
                    filter: Filter.Linear);
            });
        }
        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 });
            });
        }