public DescriptorSetUpdater(VulkanGraphicsDevice gd, PipelineBase pipeline) { _gd = gd; _pipeline = pipeline; _uniformBuffers = Array.Empty <DescriptorBufferInfo>(); _storageBuffers = Array.Empty <DescriptorBufferInfo>(); _textures = new DescriptorImageInfo[32 * 5]; _textureRefs = new Auto <DisposableImageView> [32 * 5]; _samplerRefs = new Auto <DisposableSampler> [32 * 5]; _images = Array.Empty <DescriptorImageInfo>(); _bufferTextures = Array.Empty <BufferView>(); _bufferImages = Array.Empty <BufferView>(); _dummyTexture = (TextureView)gd.CreateTexture(new GAL.TextureCreateInfo( 1, 1, 1, 1, 1, 1, 1, 4, GAL.Format.R8G8B8A8Unorm, DepthStencilMode.Depth, Target.Texture2D, SwizzleComponent.Red, SwizzleComponent.Green, SwizzleComponent.Blue, SwizzleComponent.Alpha), 1f); _dummySampler = (SamplerHolder)gd.CreateSampler(new GAL.SamplerCreateInfo( MinFilter.Nearest, MagFilter.Nearest, false, AddressMode.Repeat, AddressMode.Repeat, AddressMode.Repeat, CompareMode.None, GAL.CompareOp.Always, new ColorF(0, 0, 0, 0), 0, 0, 0, 1f)); }
public Span <byte> GetTextureData(CommandBufferPool cbp, TextureView view, int size) { GAL.TextureCreateInfo info = view.Info; var flushStorage = ResizeIfNeeded(size); using (var cbs = cbp.Rent()) { var buffer = flushStorage.GetBuffer(cbs.CommandBuffer).Get(cbs).Value; var image = view.GetImage().Get(cbs).Value; view.CopyFromOrToBuffer(cbs.CommandBuffer, buffer, image, size, true, 0, 0, info.GetLayers(), info.Levels, singleSlice: false); } flushStorage.WaitForFences(); return(flushStorage.GetDataStorage(0, size)); }
public void Blit( VulkanRenderer gd, TextureView src, Auto <DisposableImageView> dst, int dstWidth, int dstHeight, VkFormat dstFormat, Extents2D srcRegion, Extents2D dstRegion, bool linearFilter, bool clearAlpha = false) { gd.FlushAllCommands(); using var cbs = gd.CommandBufferPool.Rent(); Blit(gd, cbs, src, dst, dstWidth, dstHeight, dstFormat, srcRegion, dstRegion, linearFilter, clearAlpha); }
private static TextureView CreateIntermmediateTexture(VulkanRenderer gd, TextureView src, ref TextureCreateInfo formatInfo, Target target, int depth, int levels) { return(gd.CreateTextureView(new GAL.TextureCreateInfo( src.Width, src.Height, depth, levels, 1, formatInfo.BlockWidth, formatInfo.BlockHeight, formatInfo.BytesPerPixel, formatInfo.Format, DepthStencilMode.Depth, target, SwizzleComponent.Red, SwizzleComponent.Green, SwizzleComponent.Blue, SwizzleComponent.Alpha), 1f)); }
public FramebufferParams(Device device, ITexture[] colors, ITexture depthStencil) { _device = device; int colorsCount = colors.Count(IsValidTextureView); int count = colorsCount + (IsValidTextureView(depthStencil) ? 1 : 0); _attachments = new Auto <DisposableImageView> [count]; _colors = new TextureView[colorsCount]; AttachmentSamples = new uint[count]; AttachmentFormats = new VkFormat[count]; AttachmentIndices = new int[count]; MaxColorAttachmentIndex = colors.Length - 1; uint width = uint.MaxValue; uint height = uint.MaxValue; uint layers = uint.MaxValue; int index = 0; int bindIndex = 0; foreach (ITexture color in colors) { if (IsValidTextureView(color)) { var texture = (TextureView)color; _attachments[index] = texture.GetImageViewForAttachment(); _colors[index] = texture; _validColorAttachments |= 1u << bindIndex; AttachmentSamples[index] = (uint)texture.Info.Samples; AttachmentFormats[index] = texture.VkFormat; AttachmentIndices[index] = bindIndex; width = Math.Min(width, (uint)texture.Width); height = Math.Min(height, (uint)texture.Height); layers = Math.Min(layers, (uint)texture.Layers); if (++index >= colorsCount) { break; } } bindIndex++; } if (depthStencil is TextureView dsTexture && dsTexture.Valid) { _attachments[count - 1] = dsTexture.GetImageViewForAttachment(); _depthStencil = dsTexture; AttachmentSamples[count - 1] = (uint)dsTexture.Info.Samples; AttachmentFormats[count - 1] = dsTexture.VkFormat; width = Math.Min(width, (uint)dsTexture.Width); height = Math.Min(height, (uint)dsTexture.Height); layers = Math.Min(layers, (uint)dsTexture.Layers); HasDepthStencil = true; } if (count == 0) { width = height = layers = 1; } Width = width; Height = height; Layers = layers; AttachmentsCount = count; }
private void CaptureFrame(TextureView texture, int x, int y, int width, int height, bool isBgra, bool flipX, bool flipY) { byte[] bitmap = texture.GetData(x, y, width, height); _gd.OnScreenCaptured(new ScreenCaptureImageInfo(width, height, isBgra, bitmap, flipX, flipY)); }
public void Blit( VulkanRenderer gd, CommandBufferScoped cbs, TextureView src, Auto <DisposableImageView> dst, int dstWidth, int dstHeight, VkFormat dstFormat, Extents2D srcRegion, Extents2D dstRegion, bool linearFilter, bool clearAlpha = false) { _pipeline.SetCommandBuffer(cbs); const int RegionBufferSize = 16; var sampler = linearFilter ? _samplerLinear : _samplerNearest; _pipeline.SetTextureAndSampler(ShaderStage.Fragment, 0, src, sampler); Span <float> region = stackalloc float[RegionBufferSize / sizeof(float)]; region[0] = (float)srcRegion.X1 / src.Width; region[1] = (float)srcRegion.X2 / src.Width; region[2] = (float)srcRegion.Y1 / src.Height; region[3] = (float)srcRegion.Y2 / src.Height; if (dstRegion.X1 > dstRegion.X2) { (region[0], region[1]) = (region[1], region[0]); } if (dstRegion.Y1 > dstRegion.Y2) { (region[2], region[3]) = (region[3], region[2]); } var bufferHandle = gd.BufferManager.CreateWithHandle(gd, RegionBufferSize, false); gd.BufferManager.SetData <float>(bufferHandle, 0, region); Span <BufferRange> bufferRanges = stackalloc BufferRange[1]; bufferRanges[0] = new BufferRange(bufferHandle, 0, RegionBufferSize); _pipeline.SetUniformBuffers(1, bufferRanges); Span <GAL.Viewport> viewports = stackalloc GAL.Viewport[1]; var rect = new Rectangle <float>( MathF.Min(dstRegion.X1, dstRegion.X2), MathF.Min(dstRegion.Y1, dstRegion.Y2), MathF.Abs(dstRegion.X2 - dstRegion.X1), MathF.Abs(dstRegion.Y2 - dstRegion.Y1)); viewports[0] = new GAL.Viewport( rect, ViewportSwizzle.PositiveX, ViewportSwizzle.PositiveY, ViewportSwizzle.PositiveZ, ViewportSwizzle.PositiveW, 0f, 1f); Span <Rectangle <int> > scissors = stackalloc Rectangle <int> [1]; scissors[0] = new Rectangle <int>(0, 0, dstWidth, dstHeight); _pipeline.SetProgram(clearAlpha ? _programColorBlitClearAlpha : _programColorBlit); _pipeline.SetRenderTarget(dst, (uint)dstWidth, (uint)dstHeight, false, dstFormat); _pipeline.SetRenderTargetColorMasks(new uint[] { 0xf }); _pipeline.SetScissors(scissors); if (clearAlpha) { _pipeline.ClearRenderTargetColor(0, 0, 1, new ColorF(0f, 0f, 0f, 1f)); } _pipeline.SetViewports(viewports, false); _pipeline.SetPrimitiveTopology(GAL.PrimitiveTopology.TriangleStrip); _pipeline.Draw(4, 1, 0, 0); _pipeline.Finish(); gd.BufferManager.Delete(bufferHandle); }
public void DrawTexture( VulkanRenderer gd, PipelineBase pipeline, TextureView src, ISampler srcSampler, Extents2DF srcRegion, Extents2DF dstRegion) { const int RegionBufferSize = 16; pipeline.SetTextureAndSampler(ShaderStage.Fragment, 0, src, srcSampler); Span <float> region = stackalloc float[RegionBufferSize / sizeof(float)]; region[0] = srcRegion.X1 / src.Width; region[1] = srcRegion.X2 / src.Width; region[2] = srcRegion.Y1 / src.Height; region[3] = srcRegion.Y2 / src.Height; if (dstRegion.X1 > dstRegion.X2) { (region[0], region[1]) = (region[1], region[0]); } if (dstRegion.Y1 > dstRegion.Y2) { (region[2], region[3]) = (region[3], region[2]); } var bufferHandle = gd.BufferManager.CreateWithHandle(gd, RegionBufferSize, false); gd.BufferManager.SetData <float>(bufferHandle, 0, region); Span <BufferRange> bufferRanges = stackalloc BufferRange[1]; bufferRanges[0] = new BufferRange(bufferHandle, 0, RegionBufferSize); pipeline.SetUniformBuffers(1, bufferRanges); Span <GAL.Viewport> viewports = stackalloc GAL.Viewport[1]; var rect = new Rectangle <float>( MathF.Min(dstRegion.X1, dstRegion.X2), MathF.Min(dstRegion.Y1, dstRegion.Y2), MathF.Abs(dstRegion.X2 - dstRegion.X1), MathF.Abs(dstRegion.Y2 - dstRegion.Y1)); viewports[0] = new GAL.Viewport( rect, ViewportSwizzle.PositiveX, ViewportSwizzle.PositiveY, ViewportSwizzle.PositiveZ, ViewportSwizzle.PositiveW, 0f, 1f); Span <Rectangle <int> > scissors = stackalloc Rectangle <int> [1]; pipeline.SetProgram(_programColorBlit); pipeline.SetViewports(viewports, false); pipeline.SetPrimitiveTopology(GAL.PrimitiveTopology.TriangleStrip); pipeline.Draw(4, 1, 0, 0); gd.BufferManager.Delete(bufferHandle); }
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); }
public DescriptorSetUpdater(VulkanRenderer gd, PipelineBase pipeline) { _gd = gd; _pipeline = pipeline; // Some of the bindings counts needs to be multiplied by 2 because we have buffer and // regular textures/images interleaved on the same descriptor set. _uniformBufferRefs = new Auto <DisposableBuffer> [Constants.MaxUniformBufferBindings]; _storageBufferRefs = new Auto <DisposableBuffer> [Constants.MaxStorageBufferBindings]; _textureRefs = new Auto <DisposableImageView> [Constants.MaxTextureBindings * 2]; _samplerRefs = new Auto <DisposableSampler> [Constants.MaxTextureBindings * 2]; _imageRefs = new Auto <DisposableImageView> [Constants.MaxImageBindings * 2]; _bufferTextureRefs = new TextureBuffer[Constants.MaxTextureBindings * 2]; _bufferImageRefs = new TextureBuffer[Constants.MaxImageBindings * 2]; _bufferImageFormats = new GAL.Format[Constants.MaxImageBindings * 2]; _uniformBuffers = new DescriptorBufferInfo[Constants.MaxUniformBufferBindings]; _storageBuffers = new DescriptorBufferInfo[Constants.MaxStorageBufferBindings]; _textures = new DescriptorImageInfo[Constants.MaxTexturesPerStage]; _images = new DescriptorImageInfo[Constants.MaxImagesPerStage]; _bufferTextures = new BufferView[Constants.MaxTexturesPerStage]; _bufferImages = new BufferView[Constants.MaxImagesPerStage]; var initialImageInfo = new DescriptorImageInfo() { ImageLayout = ImageLayout.General }; _textures.AsSpan().Fill(initialImageInfo); _images.AsSpan().Fill(initialImageInfo); _uniformSet = new bool[Constants.MaxUniformBufferBindings]; _storageSet = new bool[Constants.MaxStorageBufferBindings]; if (gd.Capabilities.SupportsNullDescriptors) { // If null descriptors are supported, we can pass null as the handle. _dummyBuffer = null; } else { // If null descriptors are not supported, we need to pass the handle of a dummy buffer on unused bindings. _dummyBuffer = gd.BufferManager.Create(gd, 0x10000, forConditionalRendering: false, deviceLocal: true); } _dummyTexture = gd.CreateTextureView(new GAL.TextureCreateInfo( 1, 1, 1, 1, 1, 1, 1, 4, GAL.Format.R8G8B8A8Unorm, DepthStencilMode.Depth, Target.Texture2D, SwizzleComponent.Red, SwizzleComponent.Green, SwizzleComponent.Blue, SwizzleComponent.Alpha), 1f); _dummySampler = (SamplerHolder)gd.CreateSampler(new GAL.SamplerCreateInfo( MinFilter.Nearest, MagFilter.Nearest, false, AddressMode.Repeat, AddressMode.Repeat, AddressMode.Repeat, CompareMode.None, GAL.CompareOp.Always, new ColorF(0, 0, 0, 0), 0, 0, 0, 1f)); }
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); }
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); }