public void CopyTo(ITexture destination, int srcLayer, int dstLayer, int srcLevel, int dstLevel) { _gd.FlushAllCommands(); var src = this; var dst = (TextureView)destination; if (!Valid || !dst.Valid) { return; } using var cbs = _gd.CommandBufferPool.Rent(); var srcImage = src.GetImage().Get(cbs).Value; var dstImage = dst.GetImage().Get(cbs).Value; TextureCopy.Copy( _gd.Api, cbs.CommandBuffer, srcImage, dstImage, src.Info, dst.Info, src.FirstLayer, dst.FirstLayer, src.FirstLevel, dst.FirstLevel, srcLayer, dstLayer, srcLevel, dstLevel, 1, 1); }
public void CopyTo(ITexture destination, int firstLayer, int firstLevel) { var src = this; var dst = (TextureView)destination; if (!Valid || !dst.Valid) { return; } _gd.PipelineInternal.EndRenderPass(); var cbs = _gd.PipelineInternal.CurrentCommandBuffer; var srcImage = src.GetImage().Get(cbs).Value; var dstImage = dst.GetImage().Get(cbs).Value; if (src.Info.Target.IsMultisample()) { int depth = Math.Min(src.Info.Depth, dst.Info.Depth - firstLayer); int levels = Math.Min(src.Info.Levels, dst.Info.Levels - firstLevel); CopyMSToNonMS(_gd, cbs, src, dst, srcImage, dstImage, 0, firstLayer, 0, firstLevel, depth, levels); } else { TextureCopy.Copy( _gd.Api, cbs.CommandBuffer, srcImage, dstImage, src.Info, dst.Info, src.FirstLayer, dst.FirstLayer, src.FirstLevel, dst.FirstLevel, 0, firstLayer, 0, firstLevel); } }
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); }
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); }
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); }