예제 #1
0
        private void CopyToImpl(CommandBufferScoped cbs, TextureView dst, Extents2D srcRegion, Extents2D dstRegion, bool linearFilter)
        {
            var src = this;

            var srcFormat = GetCompatibleGalFormat(src.Info.Format);
            var dstFormat = GetCompatibleGalFormat(dst.Info.Format);

            bool srcUsesStorageFormat = src.VkFormat == src.Storage.VkFormat;
            bool dstUsesStorageFormat = dst.VkFormat == dst.Storage.VkFormat;

            int layers = Math.Min(dst.Info.GetDepthOrLayers(), src.Info.GetDepthOrLayers());
            int levels = Math.Min(dst.Info.Levels, src.Info.Levels);

            if (srcUsesStorageFormat && dstUsesStorageFormat)
            {
                if ((srcRegion.X1 | dstRegion.X1) == 0 &&
                    (srcRegion.Y1 | dstRegion.Y1) == 0 &&
                    srcRegion.X2 == src.Width &&
                    srcRegion.Y2 == src.Height &&
                    dstRegion.X2 == dst.Width &&
                    dstRegion.Y2 == dst.Height &&
                    src.Width == dst.Width &&
                    src.Height == dst.Height &&
                    src.VkFormat == dst.VkFormat)
                {
                    TextureCopy.Copy(
                        _gd.Api,
                        cbs.CommandBuffer,
                        src.GetImage().Get(cbs).Value,
                        dst.GetImage().Get(cbs).Value,
                        src.Info,
                        dst.Info,
                        src.FirstLayer,
                        dst.FirstLayer,
                        src.FirstLevel,
                        dst.FirstLevel,
                        0,
                        0,
                        0,
                        0,
                        layers,
                        levels);

                    return;
                }
                else if (_gd.FormatCapabilities.FormatSupports(srcFormat, FormatFeatureFlags.FormatFeatureBlitSrcBit) &&
                         _gd.FormatCapabilities.FormatSupports(dstFormat, FormatFeatureFlags.FormatFeatureBlitDstBit))
                {
                    TextureCopy.Blit(
                        _gd.Api,
                        cbs.CommandBuffer,
                        src.GetImage().Get(cbs).Value,
                        dst.GetImage().Get(cbs).Value,
                        src.Info,
                        dst.Info,
                        srcRegion,
                        dstRegion,
                        src.FirstLayer,
                        dst.FirstLayer,
                        src.FirstLevel,
                        dst.FirstLevel,
                        layers,
                        levels,
                        linearFilter);

                    return;
                }
                else if (srcFormat == GAL.Format.D32FloatS8Uint && srcFormat == dstFormat && SupportsBlitFromD32FS8ToD32FAndS8())
                {
                    var d32StorageInfo = TextureStorage.NewCreateInfoWith(src.Info, GAL.Format.D32Float, 4);
                    var s8StorageInfo  = TextureStorage.NewCreateInfoWith(dst.Info, GAL.Format.S8Uint, 1);

                    using var d32Storage = _gd.CreateTextureStorage(d32StorageInfo, dst.Storage.ScaleFactor);
                    using var s8Storage  = _gd.CreateTextureStorage(s8StorageInfo, dst.Storage.ScaleFactor);

                    void BlitAndCopy(ref TextureCreateInfo info, TextureStorage storage, ImageAspectFlags aspectFlags)
                    {
                        TextureCopy.Blit(
                            _gd.Api,
                            cbs.CommandBuffer,
                            src.GetImage().Get(cbs).Value,
                            storage.GetImage().Get(cbs).Value,
                            src.Info,
                            info,
                            srcRegion,
                            dstRegion,
                            src.FirstLayer,
                            0,
                            src.FirstLevel,
                            0,
                            layers,
                            levels,
                            false,
                            aspectFlags,
                            aspectFlags);

                        TextureCopy.Copy(
                            _gd.Api,
                            cbs.CommandBuffer,
                            storage.GetImage().Get(cbs).Value,
                            dst.GetImage().Get(cbs).Value,
                            info,
                            dst.Info,
                            0,
                            dst.FirstLayer,
                            0,
                            dst.FirstLevel,
                            0,
                            0,
                            0,
                            0,
                            layers,
                            levels);
                    }

                    BlitAndCopy(ref d32StorageInfo, d32Storage, ImageAspectFlags.ImageAspectDepthBit);
                    BlitAndCopy(ref s8StorageInfo, s8Storage, ImageAspectFlags.ImageAspectStencilBit);

                    return;
                }
            }

            if (VulkanConfiguration.UseSlowSafeBlitOnAmd &&
                _gd.Vendor == Vendor.Amd &&
                src.Info.Target == Target.Texture2D &&
                dst.Info.Target == Target.Texture2D &&
                !dst.Info.Format.IsDepthOrStencil())
            {
                _gd.HelperShader.Blit(
                    _gd,
                    src,
                    dst.GetIdentityImageView(),
                    dst.Width,
                    dst.Height,
                    dst.VkFormat,
                    srcRegion,
                    dstRegion,
                    linearFilter);

                return;
            }

            Auto <DisposableImage> srcImage;
            Auto <DisposableImage> dstImage;

            if (dst.Info.Format.IsDepthOrStencil())
            {
                srcImage = src.Storage.CreateAliasedColorForDepthStorageUnsafe(srcFormat).GetImage();
                dstImage = dst.Storage.CreateAliasedColorForDepthStorageUnsafe(dstFormat).GetImage();
            }
            else
            {
                srcImage = src.Storage.CreateAliasedStorageUnsafe(srcFormat).GetImage();
                dstImage = dst.Storage.CreateAliasedStorageUnsafe(dstFormat).GetImage();
            }

            TextureCopy.Blit(
                _gd.Api,
                cbs.CommandBuffer,
                srcImage.Get(cbs).Value,
                dstImage.Get(cbs).Value,
                src.Info,
                dst.Info,
                srcRegion,
                dstRegion,
                src.FirstLevel,
                dst.FirstLevel,
                src.FirstLayer,
                dst.FirstLayer,
                layers,
                levels,
                linearFilter,
                ImageAspectFlags.ImageAspectColorBit,
                ImageAspectFlags.ImageAspectColorBit);
        }
예제 #2
0
        private static void CopyMSToNonMS(
            VulkanRenderer gd,
            CommandBufferScoped cbs,
            TextureView src,
            TextureView dst,
            Image srcImage,
            Image dstImage,
            int srcLayer,
            int dstLayer,
            int srcLevel,
            int dstLevel,
            int layers,
            int levels)
        {
            bool differentFormats = src.Info.Format != dst.Info.Format;

            var target = src.Info.Target switch
            {
                Target.Texture2D => Target.Texture2DMultisample,
                Target.Texture2DArray => Target.Texture2DMultisampleArray,
                Target.Texture2DMultisampleArray => Target.Texture2DArray,
                _ => Target.Texture2D
            };

            var intermmediateTarget = differentFormats ? dst.Info.Target : target;

            using var intermmediate = CreateIntermmediateTexture(gd, src, ref dst._info, intermmediateTarget, layers, levels);
            var intermmediateImage = intermmediate.GetImage().Get(cbs).Value;

            if (differentFormats)
            {
                // If the formats are different, the resolve would perform format conversion.
                // So we need yet another intermmediate texture and do a copy to reinterpret the
                // data into the correct (destination) format, without doing any sort of conversion.
                using var intermmediate2 = CreateIntermmediateTexture(gd, src, ref src._info, target, layers, levels);
                var intermmediate2Image = intermmediate2.GetImage().Get(cbs).Value;

                TextureCopy.Copy(
                    gd.Api,
                    cbs.CommandBuffer,
                    srcImage,
                    intermmediate2Image,
                    src.Info,
                    intermmediate2.Info,
                    src.FirstLayer,
                    0,
                    src.FirstLevel,
                    0,
                    srcLayer,
                    0,
                    srcLevel,
                    0,
                    layers,
                    levels);

                TextureCopy.Copy(
                    gd.Api,
                    cbs.CommandBuffer,
                    intermmediate2Image,
                    intermmediateImage,
                    intermmediate2.Info,
                    intermmediate.Info,
                    0,
                    0,
                    0,
                    0,
                    0,
                    0,
                    0,
                    0,
                    layers,
                    levels);
            }
            else
            {
                TextureCopy.Copy(
                    gd.Api,
                    cbs.CommandBuffer,
                    srcImage,
                    intermmediateImage,
                    src.Info,
                    intermmediate.Info,
                    src.FirstLayer,
                    0,
                    src.FirstLevel,
                    0,
                    srcLayer,
                    0,
                    srcLevel,
                    0,
                    layers,
                    levels);
            }

            var srcRegion = new Extents2D(0, 0, src.Width, src.Height);
            var dstRegion = new Extents2D(0, 0, dst.Width, dst.Height);

            TextureCopy.Blit(
                gd.Api,
                cbs.CommandBuffer,
                intermmediateImage,
                dstImage,
                intermmediate.Info,
                dst.Info,
                srcRegion,
                dstRegion,
                0,
                dst.FirstLevel + dstLevel,
                0,
                dst.FirstLayer + dstLayer,
                layers,
                levels,
                true,
                ImageAspectFlags.ImageAspectColorBit,
                ImageAspectFlags.ImageAspectColorBit);
        }
예제 #3
0
        private static void BlitDepthStencilWithBuffer(
            VulkanRenderer gd,
            CommandBufferScoped cbs,
            TextureView src,
            TextureView dst,
            Extents2D srcRegion,
            Extents2D dstRegion)
        {
            int drBaseX  = Math.Min(dstRegion.X1, dstRegion.X2);
            int drBaseY  = Math.Min(dstRegion.Y1, dstRegion.Y2);
            int drWidth  = Math.Abs(dstRegion.X2 - dstRegion.X1);
            int drHeight = Math.Abs(dstRegion.Y2 - dstRegion.Y1);

            var drOriginZero = new Extents2D(
                dstRegion.X1 - drBaseX,
                dstRegion.Y1 - drBaseY,
                dstRegion.X2 - drBaseX,
                dstRegion.Y2 - drBaseY);

            var d32SrcStorageInfo = TextureStorage.NewCreateInfoWith(ref src._info, GAL.Format.D32Float, 4);
            var d32DstStorageInfo = TextureStorage.NewCreateInfoWith(ref dst._info, GAL.Format.D32Float, 4, drWidth, drHeight);
            var s8SrcStorageInfo  = TextureStorage.NewCreateInfoWith(ref src._info, GAL.Format.S8Uint, 1);
            var s8DstStorageInfo  = TextureStorage.NewCreateInfoWith(ref dst._info, GAL.Format.S8Uint, 1, drWidth, drHeight);

            using var d32SrcStorage = gd.CreateTextureStorage(d32SrcStorageInfo, src.Storage.ScaleFactor);
            using var d32DstStorage = gd.CreateTextureStorage(d32DstStorageInfo, dst.Storage.ScaleFactor);
            using var s8SrcStorage  = gd.CreateTextureStorage(s8SrcStorageInfo, src.Storage.ScaleFactor);
            using var s8DstStorage  = gd.CreateTextureStorage(s8DstStorageInfo, dst.Storage.ScaleFactor);

            void SlowBlit(TextureStorage srcTemp, TextureStorage dstTemp, ImageAspectFlags aspectFlags)
            {
                int levels = Math.Min(src.Info.Levels, dst.Info.Levels);

                int srcSize = 0;
                int dstSize = 0;

                for (int l = 0; l < levels; l++)
                {
                    srcSize += srcTemp.Info.GetMipSize2D(l);
                    dstSize += dstTemp.Info.GetMipSize2D(l);
                }

                using var srcTempBuffer = gd.BufferManager.Create(gd, srcSize, deviceLocal: true);
                using var dstTempBuffer = gd.BufferManager.Create(gd, dstSize, deviceLocal: true);

                src.Storage.CopyFromOrToBuffer(
                    cbs.CommandBuffer,
                    srcTempBuffer.GetBuffer().Get(cbs, 0, srcSize).Value,
                    src.GetImage().Get(cbs).Value,
                    srcSize,
                    to: true,
                    0,
                    0,
                    src.FirstLayer,
                    src.FirstLevel,
                    1,
                    levels,
                    true,
                    aspectFlags,
                    false);

                BufferHolder.InsertBufferBarrier(
                    gd,
                    cbs.CommandBuffer,
                    srcTempBuffer.GetBuffer().Get(cbs, 0, srcSize).Value,
                    AccessFlags.AccessTransferWriteBit,
                    AccessFlags.AccessTransferReadBit,
                    PipelineStageFlags.PipelineStageTransferBit,
                    PipelineStageFlags.PipelineStageTransferBit,
                    0,
                    srcSize);

                srcTemp.CopyFromOrToBuffer(
                    cbs.CommandBuffer,
                    srcTempBuffer.GetBuffer().Get(cbs, 0, srcSize).Value,
                    srcTemp.GetImage().Get(cbs).Value,
                    srcSize,
                    to: false,
                    0,
                    0,
                    0,
                    0,
                    1,
                    levels,
                    true,
                    aspectFlags,
                    false);

                InsertImageBarrier(
                    gd.Api,
                    cbs.CommandBuffer,
                    srcTemp.GetImage().Get(cbs).Value,
                    AccessFlags.AccessTransferWriteBit,
                    AccessFlags.AccessTransferReadBit,
                    PipelineStageFlags.PipelineStageTransferBit,
                    PipelineStageFlags.PipelineStageTransferBit,
                    aspectFlags,
                    0,
                    0,
                    1,
                    levels);

                TextureCopy.Blit(
                    gd.Api,
                    cbs.CommandBuffer,
                    srcTemp.GetImage().Get(cbs).Value,
                    dstTemp.GetImage().Get(cbs).Value,
                    srcTemp.Info,
                    dstTemp.Info,
                    srcRegion,
                    drOriginZero,
                    0,
                    0,
                    0,
                    0,
                    1,
                    levels,
                    false,
                    aspectFlags,
                    aspectFlags);

                InsertImageBarrier(
                    gd.Api,
                    cbs.CommandBuffer,
                    dstTemp.GetImage().Get(cbs).Value,
                    AccessFlags.AccessTransferWriteBit,
                    AccessFlags.AccessTransferReadBit,
                    PipelineStageFlags.PipelineStageTransferBit,
                    PipelineStageFlags.PipelineStageTransferBit,
                    aspectFlags,
                    0,
                    0,
                    1,
                    levels);

                dstTemp.CopyFromOrToBuffer(
                    cbs.CommandBuffer,
                    dstTempBuffer.GetBuffer().Get(cbs, 0, dstSize).Value,
                    dstTemp.GetImage().Get(cbs).Value,
                    dstSize,
                    to: true,
                    0,
                    0,
                    0,
                    0,
                    1,
                    levels,
                    true,
                    aspectFlags,
                    false);

                BufferHolder.InsertBufferBarrier(
                    gd,
                    cbs.CommandBuffer,
                    dstTempBuffer.GetBuffer().Get(cbs, 0, dstSize).Value,
                    AccessFlags.AccessTransferWriteBit,
                    AccessFlags.AccessTransferReadBit,
                    PipelineStageFlags.PipelineStageTransferBit,
                    PipelineStageFlags.PipelineStageTransferBit,
                    0,
                    dstSize);

                dst.Storage.CopyFromOrToBuffer(
                    cbs.CommandBuffer,
                    dstTempBuffer.GetBuffer().Get(cbs, 0, dstSize).Value,
                    dst.GetImage().Get(cbs).Value,
                    dstSize,
                    to: false,
                    drBaseX,
                    drBaseY,
                    dst.FirstLayer,
                    dst.FirstLevel,
                    1,
                    levels,
                    true,
                    aspectFlags,
                    false);
            }

            SlowBlit(d32SrcStorage, d32DstStorage, ImageAspectFlags.ImageAspectDepthBit);
            SlowBlit(s8SrcStorage, s8DstStorage, ImageAspectFlags.ImageAspectStencilBit);
        }
예제 #4
0
        private void CopyToImpl(CommandBufferScoped cbs, TextureView dst, Extents2D srcRegion, Extents2D dstRegion, bool linearFilter)
        {
            var src = this;

            var srcFormat = GetCompatibleGalFormat(src.Info.Format);
            var dstFormat = GetCompatibleGalFormat(dst.Info.Format);

            bool srcUsesStorageFormat = src.VkFormat == src.Storage.VkFormat;
            bool dstUsesStorageFormat = dst.VkFormat == dst.Storage.VkFormat;

            if (srcUsesStorageFormat && dstUsesStorageFormat)
            {
                if ((srcRegion.X1 | dstRegion.X1) == 0 &&
                    (srcRegion.Y1 | dstRegion.Y1) == 0 &&
                    srcRegion.X2 == src.Width &&
                    srcRegion.Y2 == src.Height &&
                    dstRegion.X2 == dst.Width &&
                    dstRegion.Y2 == dst.Height &&
                    src.Width == dst.Width &&
                    src.Height == dst.Height &&
                    src.VkFormat == dst.VkFormat)
                {
                    TextureCopy.Copy(
                        _gd.Api,
                        cbs.CommandBuffer,
                        src.GetImage().Get(cbs).Value,
                        dst.GetImage().Get(cbs).Value,
                        src.Info,
                        dst.Info,
                        src.FirstLayer,
                        dst.FirstLayer,
                        src.FirstLevel,
                        dst.FirstLevel,
                        0,
                        0,
                        0,
                        0,
                        1,
                        1);

                    return;
                }
                else if (_gd.FormatCapabilities.FormatSupports(srcFormat, FormatFeatureFlags.FormatFeatureBlitSrcBit) &&
                         _gd.FormatCapabilities.FormatSupports(dstFormat, FormatFeatureFlags.FormatFeatureBlitDstBit))
                {
                    TextureCopy.Blit(
                        _gd.Api,
                        cbs.CommandBuffer,
                        src.GetImage().Get(cbs).Value,
                        dst.GetImage().Get(cbs).Value,
                        src.Info,
                        dst.Info,
                        srcRegion,
                        dstRegion,
                        src.FirstLayer,
                        dst.FirstLayer,
                        src.FirstLevel,
                        dst.FirstLevel,
                        linearFilter);

                    return;
                }
            }

            Auto <DisposableImage> srcImage;
            Auto <DisposableImage> dstImage;

            if (dst.Info.Format.IsDepthOrStencil())
            {
                srcImage = src.Storage.CreateAliasedColorForDepthStorageUnsafe(srcFormat).GetImage();
                dstImage = dst.Storage.CreateAliasedColorForDepthStorageUnsafe(dstFormat).GetImage();
            }
            else
            {
                srcImage = src.Storage.CreateAliasedStorageUnsafe(srcFormat).GetImage();
                dstImage = dst.Storage.CreateAliasedStorageUnsafe(dstFormat).GetImage();
            }

            TextureCopy.Blit(
                _gd.Api,
                cbs.CommandBuffer,
                srcImage.Get(cbs).Value,
                dstImage.Get(cbs).Value,
                src.Info,
                dst.Info,
                srcRegion,
                dstRegion,
                src.FirstLevel,
                dst.FirstLevel,
                src.FirstLayer,
                dst.FirstLayer,
                linearFilter,
                forceColorAspect: true);
        }