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));
        }
Beispiel #2
0
        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));
        }
Beispiel #3
0
        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);
        }
Beispiel #4
0
 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));
 }
Beispiel #5
0
        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;
        }
Beispiel #6
0
        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));
        }
Beispiel #7
0
        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);
        }
Beispiel #8
0
        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);
        }
Beispiel #9
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);
        }
Beispiel #10
0
        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));
        }
Beispiel #11
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);
        }
Beispiel #12
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);
        }
Beispiel #13
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);
        }