コード例 #1
0
ファイル: TextureView.cs プロジェクト: ianuub/Ryujinxxx
        public ITexture CreateView(TextureCreateInfo info, int firstLayer, int firstLevel)
        {
            firstLayer += FirstLayer;
            firstLevel += FirstLevel;

            return(_parent.CreateView(info, firstLayer, firstLevel));
        }
コード例 #2
0
ファイル: TextureBase.cs プロジェクト: zh010zh/Ryujinx
        public TextureBase(TextureCreateInfo info, float scaleFactor = 1f)
        {
            Info        = info;
            ScaleFactor = scaleFactor;

            Handle = GL.GenTexture();
        }
コード例 #3
0
        public ITexture CreateView(TextureCreateInfo info, int firstLayer, int firstLevel)
        {
            if (Info.IsCompressed == info.IsCompressed)
            {
                firstLayer += FirstLayer;
                firstLevel += FirstLevel;

                return(_parent.CreateView(info, firstLayer, firstLevel));
            }
            else
            {
                // TODO: Most graphics APIs doesn't support creating a texture view from a compressed format
                // with a non-compressed format (or vice-versa), however NVN seems to support it.
                // So we emulate that here with a texture copy (see the first CopyTo overload).
                // However right now it only does a single copy right after the view is created,
                // so it doesn't work for all cases.
                TextureView emulatedView = (TextureView)_renderer.CreateTexture(info);

                emulatedView._emulatedViewParent = this;

                emulatedView.FirstLayer = firstLayer;
                emulatedView.FirstLevel = firstLevel;

                return(emulatedView);
            }
        }
コード例 #4
0
        /// <summary>
        /// Constructs a new instance of the cached GPU texture.
        /// </summary>
        /// <param name="context">GPU context that the texture belongs to</param>
        /// <param name="info">Texture information</param>
        /// <param name="sizeInfo">Size information of the texture</param>
        public Texture(GpuContext context, TextureInfo info, SizeInfo sizeInfo)
        {
            InitializeTexture(context, info, sizeInfo);

            TextureCreateInfo createInfo = TextureManager.GetCreateInfo(info, context.Capabilities);

            HostTexture = _context.Renderer.CreateTexture(createInfo);
        }
コード例 #5
0
 public void Set(TableRef <ThreadedTexture> texture, TableRef <ThreadedTexture> destination, TextureCreateInfo info, int firstLayer, int firstLevel)
 {
     _texture     = texture;
     _destination = destination;
     _info        = info;
     _firstLayer  = firstLayer;
     _firstLevel  = firstLevel;
 }
コード例 #6
0
        public ITexture CreateView(TextureCreateInfo info, int firstLayer, int firstLevel)
        {
            ThreadedTexture newTex = new ThreadedTexture(_renderer, info, ScaleFactor);

            _renderer.New <TextureCreateViewCommand>().Set(Ref(this), Ref(newTex), info, firstLayer, firstLevel);
            _renderer.QueueCommand();

            return(newTex);
        }
コード例 #7
0
        public TextureStorage(Renderer renderer, TextureCreateInfo info)
        {
            _renderer = renderer;
            Info      = info;

            Handle = GL.GenTexture();

            CreateImmutableStorage();
        }
コード例 #8
0
        public TextureBase(TextureCreateInfo info, float scaleFactor = 1f)
        {
            Info        = info;
            Width       = (int)Math.Ceiling(Info.Width * scaleFactor);
            Height      = (int)Math.Ceiling(Info.Height * scaleFactor);
            ScaleFactor = scaleFactor;

            Handle = GL.GenTexture();
        }
コード例 #9
0
ファイル: TextureBuffer.cs プロジェクト: Ryujinx/Ryujinx
        public TextureBuffer(VulkanRenderer gd, TextureCreateInfo info, float scale)
        {
            _gd = gd;
            Width = info.Width;
            Height = info.Height;
            VkFormat = FormatTable.GetFormat(info.Format);
            ScaleFactor = scale;

            gd.Textures.Add(this);
        }
コード例 #10
0
        public TextureStorage(Renderer renderer, TextureCreateInfo info, float scaleFactor)
        {
            _renderer = renderer;
            Info      = info;

            Handle      = GL.GenTexture();
            ScaleFactor = scaleFactor;

            CreateImmutableStorage();
        }
コード例 #11
0
        public ITexture CreateTexture(TextureCreateInfo info, float scale)
        {
            if (info.Target == Target.TextureBuffer)
            {
                return(new TextureBuffer(this, info, scale));
            }

            // This should be disposed when all views are destroyed.
            using var storage = CreateTextureStorage(info, scale);
            return(storage.CreateView(info, 0, 0));
        }
コード例 #12
0
ファイル: Renderer.cs プロジェクト: ProFireDev/Ryujinx
 public ITexture CreateTexture(TextureCreateInfo info, float scaleFactor)
 {
     if (info.Target == Target.TextureBuffer)
     {
         return(new TextureBuffer(this, info));
     }
     else
     {
         return(ResourcePool.GetTextureOrNull(info, scaleFactor) ?? new TextureStorage(this, info, scaleFactor).CreateDefaultView());
     }
 }
コード例 #13
0
        /// <summary>
        /// Copy the host texture to a scaled one. If a texture is not provided, create it with the given scale.
        /// </summary>
        /// <param name="scale">Scale factor</param>
        /// <param name="storage">Texture to use instead of creating one</param>
        /// <returns>A host texture containing a scaled version of this texture</returns>
        private ITexture GetScaledHostTexture(float scale, ITexture storage = null)
        {
            if (storage == null)
            {
                TextureCreateInfo createInfo = TextureManager.GetCreateInfo(Info, _context.Capabilities, scale);
                storage = _context.Renderer.CreateTexture(createInfo, scale);
            }

            HostTexture.CopyTo(storage, new Extents2D(0, 0, HostTexture.Width, HostTexture.Height), new Extents2D(0, 0, storage.Width, storage.Height), true);

            return(storage);
        }
コード例 #14
0
ファイル: Texture.cs プロジェクト: yunfile123/Ryujinx
        /// <summary>
        /// Sets the Scale Factor on this texture, and immediately recreates it at the correct size.
        /// When a texture is resized, a scaled copy is performed from the old texture to the new one, to ensure no data is lost.
        /// If scale is equivalent, this only propagates the blacklisted/scaled mode.
        /// If called on a view, its storage is resized instead.
        /// When resizing storage, all texture views are recreated.
        /// </summary>
        /// <param name="scale">The new scale factor for this texture</param>
        public void SetScale(float scale)
        {
            TextureScaleMode newScaleMode = ScaleMode == TextureScaleMode.Blacklisted ? ScaleMode : TextureScaleMode.Scaled;

            if (_viewStorage != this)
            {
                _viewStorage.ScaleMode = newScaleMode;
                _viewStorage.SetScale(scale);
                return;
            }

            if (ScaleFactor != scale)
            {
                Logger.Debug?.Print(LogClass.Gpu, $"Rescaling {Info.Width}x{Info.Height} {Info.FormatInfo.Format.ToString()} to ({ScaleFactor} to {scale}). ");

                ScaleFactor = scale;

                ITexture newStorage = GetScaledHostTexture(ScaleFactor);

                Logger.Debug?.Print(LogClass.Gpu, $"  Copy performed: {HostTexture.Width}x{HostTexture.Height} to {newStorage.Width}x{newStorage.Height}");

                ReplaceStorage(newStorage);

                // All views must be recreated against the new storage.

                foreach (var view in _views)
                {
                    Logger.Debug?.Print(LogClass.Gpu, $"  Recreating view {Info.Width}x{Info.Height} {Info.FormatInfo.Format.ToString()}.");
                    view.ScaleFactor = scale;

                    TextureCreateInfo viewCreateInfo = TextureManager.GetCreateInfo(view.Info, _context.Capabilities);

                    ITexture newView = HostTexture.CreateView(viewCreateInfo, view._firstLayer - _firstLayer, view._firstLevel - _firstLevel);

                    view.ReplaceStorage(newView);

                    view.ScaleMode = newScaleMode;
                }
            }

            if (ScaleMode != newScaleMode)
            {
                ScaleMode = newScaleMode;

                foreach (var view in _views)
                {
                    view.ScaleMode = newScaleMode;
                }
            }
        }
コード例 #15
0
        public TextureView(
            Renderer renderer,
            TextureStorage parent,
            TextureCreateInfo info,
            int firstLayer,
            int firstLevel) : base(info, parent.ScaleFactor)
        {
            _renderer = renderer;
            _parent   = parent;

            FirstLayer = firstLayer;
            FirstLevel = firstLevel;

            CreateView();
        }
コード例 #16
0
ファイル: TextureCopy.cs プロジェクト: scese250/Ryujinx
 public static void Blit(
     Vk api,
     CommandBuffer commandBuffer,
     Image srcImage,
     Image dstImage,
     TextureCreateInfo srcInfo,
     TextureCreateInfo dstInfo,
     Extents2D srcRegion,
     Extents2D dstRegion,
     int srcLayer,
     int dstLayer,
     int srcLevel,
     int dstLevel,
     bool linearFilter,
     bool forceColorAspect = false)
 {
コード例 #17
0
        /// <summary>
        /// Create a texture view from this texture.
        /// A texture view is defined as a child texture, from a sub-range of their parent texture.
        /// For example, the initial layer and mipmap level of the view can be defined, so the texture
        /// will start at the given layer/level of the parent texture.
        /// </summary>
        /// <param name="info">Child texture information</param>
        /// <param name="sizeInfo">Child texture size information</param>
        /// <param name="firstLayer">Start layer of the child texture on the parent texture</param>
        /// <param name="firstLevel">Start mipmap level of the child texture on the parent texture</param>
        /// <returns>The child texture</returns>
        public Texture CreateView(TextureInfo info, SizeInfo sizeInfo, int firstLayer, int firstLevel)
        {
            Texture texture = new Texture(
                _context,
                info,
                sizeInfo,
                _firstLayer + firstLayer,
                _firstLevel + firstLevel);

            TextureCreateInfo createInfo = TextureManager.GetCreateInfo(info, _context.Capabilities);

            texture.HostTexture = HostTexture.CreateView(createInfo, firstLayer, firstLevel);

            _viewStorage.AddView(texture);

            return(texture);
        }
コード例 #18
0
ファイル: TextureView.cs プロジェクト: yomifrogs/Ryujinx
        public TextureView(
            Renderer renderer,
            TextureStorage parent,
            TextureCreateInfo info,
            int firstLayer,
            int firstLevel)
        {
            _renderer = renderer;
            _parent   = parent;
            _info     = info;

            _firstLayer = firstLayer;
            _firstLevel = firstLevel;

            Handle = GL.GenTexture();

            CreateView();
        }
コード例 #19
0
 public static void Blit(
     Vk api,
     CommandBuffer commandBuffer,
     Image srcImage,
     Image dstImage,
     TextureCreateInfo srcInfo,
     TextureCreateInfo dstInfo,
     Extents2D srcRegion,
     Extents2D dstRegion,
     int srcLayer,
     int dstLayer,
     int srcLevel,
     int dstLevel,
     int layers,
     int levels,
     bool linearFilter,
     ImageAspectFlags srcAspectFlags = 0,
     ImageAspectFlags dstAspectFlags = 0)
 {
コード例 #20
0
ファイル: Texture.cs プロジェクト: yunfile123/Ryujinx
        /// <summary>
        /// Copy the host texture to a scaled one. If a texture is not provided, create it with the given scale.
        /// </summary>
        /// <param name="scale">Scale factor</param>
        /// <param name="storage">Texture to use instead of creating one</param>
        /// <returns>A host texture containing a scaled version of this texture</returns>
        private ITexture GetScaledHostTexture(float scale, ITexture storage = null)
        {
            if (storage == null)
            {
                TextureCreateInfo createInfo = TextureManager.GetCreateInfo(Info, _context.Capabilities);

                storage = _context.Renderer.CreateTexture(createInfo, scale);
            }

            if (Info.Target == Target.Texture2DArray)
            {
                CopyArrayScaled(storage);
            }
            else
            {
                HostTexture.CopyTo(storage, new Extents2D(0, 0, HostTexture.Width, HostTexture.Height), new Extents2D(0, 0, storage.Width, storage.Height), true);
            }

            return(storage);
        }
コード例 #21
0
        /// <summary>
        /// Create a texture view from this texture.
        /// A texture view is defined as a child texture, from a sub-range of their parent texture.
        /// For example, the initial layer and mipmap level of the view can be defined, so the texture
        /// will start at the given layer/level of the parent texture.
        /// </summary>
        /// <param name="info">Child texture information</param>
        /// <param name="sizeInfo">Child texture size information</param>
        /// <param name="range">Physical memory ranges where the texture data is located</param>
        /// <param name="firstLayer">Start layer of the child texture on the parent texture</param>
        /// <param name="firstLevel">Start mipmap level of the child texture on the parent texture</param>
        /// <returns>The child texture</returns>
        public Texture CreateView(TextureInfo info, SizeInfo sizeInfo, MultiRange range, int firstLayer, int firstLevel)
        {
            Texture texture = new Texture(
                _context,
                info,
                sizeInfo,
                range,
                FirstLayer + firstLayer,
                FirstLevel + firstLevel,
                ScaleFactor,
                ScaleMode);

            TextureCreateInfo createInfo = TextureManager.GetCreateInfo(info, _context.Capabilities, ScaleFactor);

            texture.HostTexture = HostTexture.CreateView(createInfo, firstLayer, firstLevel);

            _viewStorage.AddView(texture);

            return(texture);
        }
コード例 #22
0
        /// <summary>
        /// Recreates the texture storage (or view, in the case of child textures) of this texture.
        /// This allows recreating the texture with a new size.
        /// A copy is automatically performed from the old to the new texture.
        /// </summary>
        /// <param name="width">The new texture width</param>
        /// <param name="height">The new texture height</param>
        /// <param name="depthOrLayers">The new texture depth (for 3D textures) or layers (for layered textures)</param>
        private void RecreateStorageOrView(int width, int height, int depthOrLayers)
        {
            ChangedSize = true;

            SetInfo(new TextureInfo(
                        Info.Address,
                        Info.GpuAddress,
                        width,
                        height,
                        depthOrLayers,
                        Info.Levels,
                        Info.SamplesInX,
                        Info.SamplesInY,
                        Info.Stride,
                        Info.IsLinear,
                        Info.GobBlocksInY,
                        Info.GobBlocksInZ,
                        Info.GobBlocksInTileX,
                        Info.Target,
                        Info.FormatInfo,
                        Info.DepthStencilMode,
                        Info.SwizzleR,
                        Info.SwizzleG,
                        Info.SwizzleB,
                        Info.SwizzleA));

            TextureCreateInfo createInfo = TextureManager.GetCreateInfo(Info, _context.Capabilities, ScaleFactor);

            if (_viewStorage != this)
            {
                ReplaceStorage(_viewStorage.HostTexture.CreateView(createInfo, _firstLayer, _firstLevel));
            }
            else
            {
                ITexture newStorage = _context.Renderer.CreateTexture(createInfo, ScaleFactor);

                HostTexture.CopyTo(newStorage, 0, 0);

                ReplaceStorage(newStorage);
            }
        }
コード例 #23
0
        /// <summary>
        /// Gets a texture of the specified target type from this texture.
        /// This can be used to get an array texture from a non-array texture and vice-versa.
        /// If this texture and the requested targets are equal, then this texture Host texture is returned directly.
        /// </summary>
        /// <param name="target">The desired target type</param>
        /// <returns>A view of this texture with the requested target, or null if the target is invalid for this texture</returns>
        public ITexture GetTargetTexture(Target target)
        {
            if (target == Target)
            {
                return(HostTexture);
            }

            if (_arrayViewTexture == null && IsSameDimensionsTarget(target))
            {
                TextureCreateInfo createInfo = new TextureCreateInfo(
                    Info.Width,
                    Info.Height,
                    target == Target.CubemapArray ? 6 : 1,
                    Info.Levels,
                    Info.Samples,
                    Info.FormatInfo.BlockWidth,
                    Info.FormatInfo.BlockHeight,
                    Info.FormatInfo.BytesPerPixel,
                    Info.FormatInfo.Format,
                    Info.DepthStencilMode,
                    target,
                    Info.SwizzleR,
                    Info.SwizzleG,
                    Info.SwizzleB,
                    Info.SwizzleA);

                ITexture viewTexture = HostTexture.CreateView(createInfo, 0, 0);

                _arrayViewTexture = viewTexture;
                _arrayViewTarget  = target;

                return(viewTexture);
            }
            else if (_arrayViewTarget == target)
            {
                return(_arrayViewTexture);
            }

            return(null);
        }
コード例 #24
0
        /// <summary>
        /// Attempt to obtain a texture from the resource cache with the desired parameters.
        /// </summary>
        /// <param name="info">The creation info for the desired texture</param>
        /// <param name="scaleFactor">The scale factor for the desired texture</param>
        /// <returns>A TextureView with the description specified, or null if one was not found.</returns>
        public TextureView GetTextureOrNull(TextureCreateInfo info, float scaleFactor)
        {
            lock (_lock)
            {
                List <DisposedTexture> list;
                if (!_textures.TryGetValue(info, out list))
                {
                    return(null);
                }

                foreach (DisposedTexture texture in list)
                {
                    if (scaleFactor == texture.ScaleFactor)
                    {
                        list.Remove(texture);
                        return(texture.View);
                    }
                }

                return(null);
            }
        }
コード例 #25
0
        public TextureStorage CreateAliasedStorageUnsafe(GAL.Format format)
        {
            if (_aliasedStorages == null || !_aliasedStorages.TryGetValue(format, out var storage))
            {
                _aliasedStorages ??= new Dictionary <GAL.Format, TextureStorage>();

                var info = new TextureCreateInfo(
                    _info.Width,
                    _info.Height,
                    _info.Depth,
                    _info.Levels,
                    _info.Samples,
                    _info.BlockWidth,
                    _info.BlockHeight,
                    _info.BytesPerPixel,
                    format,
                    _info.DepthStencilMode,
                    _info.Target,
                    _info.SwizzleR,
                    _info.SwizzleG,
                    _info.SwizzleB,
                    _info.SwizzleA);

                storage = new TextureStorage(_gd, default, _device, info, ScaleFactor, _allocationAuto);
コード例 #26
0
        /// <summary>
        /// Attempt to obtain a texture from the resource cache with the desired parameters.
        /// </summary>
        /// <param name="info">The creation info for the desired texture</param>
        /// <param name="scaleFactor">The scale factor for the desired texture</param>
        /// <returns>A TextureView with the description specified, or null if one was not found.</returns>
        public TextureView TryGetTexture(TextureCreateInfo info, float scaleFactor)
        {
            lock (_lock)
            {
                uint key = GetTextureKey(info);

                List <DisposedTexture> list;
                if (!_textures.TryGetValue(key, out list))
                {
                    return(null);
                }

                foreach (DisposedTexture texture in list)
                {
                    if (texture.View.Info.Equals(info) && scaleFactor == texture.ScaleFactor)
                    {
                        list.Remove(texture);
                        return(texture.View);
                    }
                }

                return(null);
            }
        }
コード例 #27
0
        /// <summary>
        /// Initializes the data for a texture. Can optionally initialize the texture with or without data.
        /// If the texture is a view, it will initialize memory tracking to be non-dirty.
        /// </summary>
        /// <param name="isView">True if the texture is a view, false otherwise</param>
        /// <param name="withData">True if the texture is to be initialized with data</param>
        public void InitializeData(bool isView, bool withData = false)
        {
            _memoryTracking = _context.PhysicalMemory.BeginTracking(Address, Size);

            if (withData)
            {
                Debug.Assert(!isView);

                TextureCreateInfo createInfo = TextureManager.GetCreateInfo(Info, _context.Capabilities, ScaleFactor);
                HostTexture = _context.Renderer.CreateTexture(createInfo, ScaleFactor);

                SynchronizeMemory(); // Load the data.
                if (ScaleMode == TextureScaleMode.Scaled)
                {
                    SetScale(GraphicsConfig.ResScale); // Scale the data up.
                }
            }
            else
            {
                // Don't update this texture the next time we synchronize.
                ConsumeModified();
                _hasData = true;

                if (!isView)
                {
                    if (ScaleMode == TextureScaleMode.Scaled)
                    {
                        // Don't need to start at 1x as there is no data to scale, just go straight to the target scale.
                        ScaleFactor = GraphicsConfig.ResScale;
                    }

                    TextureCreateInfo createInfo = TextureManager.GetCreateInfo(Info, _context.Capabilities, ScaleFactor);
                    HostTexture = _context.Renderer.CreateTexture(createInfo, ScaleFactor);
                }
            }
        }
コード例 #28
0
ファイル: Texture.cs プロジェクト: aanntaa/Ryujinx
        /// <summary>
        /// Helper method for copying our Texture2DArray texture to the given target, with scaling.
        /// This creates temporary views for each array layer on both textures, copying each one at a time.
        /// </summary>
        /// <param name="target">The texture array to copy to</param>
        private void CopyArrayScaled(ITexture target)
        {
            TextureInfo viewInfo = new TextureInfo(
                Info.Address,
                Info.Width,
                Info.Height,
                1,
                Info.Levels,
                Info.SamplesInX,
                Info.SamplesInY,
                Info.Stride,
                Info.IsLinear,
                Info.GobBlocksInY,
                Info.GobBlocksInZ,
                Info.GobBlocksInTileX,
                Target.Texture2D,
                Info.FormatInfo,
                Info.DepthStencilMode,
                Info.SwizzleR,
                Info.SwizzleG,
                Info.SwizzleB,
                Info.SwizzleA);

            TextureCreateInfo createInfo = TextureManager.GetCreateInfo(viewInfo, _context.Capabilities, ScaleFactor);

            for (int i = 0; i < Info.DepthOrLayers; i++)
            {
                ITexture from = HostTexture.CreateView(createInfo, i, 0);
                ITexture to   = target.CreateView(createInfo, i, 0);

                from.CopyTo(to, new Extents2D(0, 0, from.Width, from.Height), new Extents2D(0, 0, to.Width, to.Height), true);

                from.Release();
                to.Release();
            }
        }
コード例 #29
0
ファイル: TextureStorage.cs プロジェクト: Ryujinx/Ryujinx
        public unsafe TextureStorage(
            VulkanRenderer gd,
            PhysicalDevice physicalDevice,
            Device device,
            TextureCreateInfo info,
            float scaleFactor,
            Auto <MemoryAllocation> foreignAllocation = null)
        {
            _gd         = gd;
            _device     = device;
            _info       = info;
            ScaleFactor = scaleFactor;

            var format = _gd.FormatCapabilities.ConvertToVkFormat(info.Format);
            var levels = (uint)info.Levels;
            var layers = (uint)info.GetLayers();
            var depth  = (uint)(info.Target == Target.Texture3D ? info.Depth : 1);

            VkFormat = format;

            var type = info.Target.Convert();

            var extent = new Extent3D((uint)info.Width, (uint)info.Height, depth);

            var sampleCountFlags = ConvertToSampleCountFlags((uint)info.Samples);

            var usage = DefaultUsageFlags;

            if (info.Format.IsDepthOrStencil())
            {
                usage |= ImageUsageFlags.ImageUsageDepthStencilAttachmentBit;
            }
            else if (info.Format.IsRtColorCompatible())
            {
                usage |= ImageUsageFlags.ImageUsageColorAttachmentBit;
            }

            if (info.Format.IsImageCompatible())
            {
                usage |= ImageUsageFlags.ImageUsageStorageBit;
            }

            var flags = ImageCreateFlags.ImageCreateMutableFormatBit;

            // This flag causes mipmapped texture arrays to break on AMD GCN, so for that copy dependencies are forced for aliasing as cube.
            bool isCube         = info.Target == Target.Cubemap || info.Target == Target.CubemapArray;
            bool cubeCompatible = gd.IsAmdGcn ? isCube : (info.Width == info.Height && layers >= 6);

            if (type == ImageType.ImageType2D && cubeCompatible)
            {
                flags |= ImageCreateFlags.ImageCreateCubeCompatibleBit;
            }

            if (type == ImageType.ImageType3D)
            {
                flags |= ImageCreateFlags.ImageCreate2DArrayCompatibleBit;
            }

            var imageCreateInfo = new ImageCreateInfo()
            {
                SType         = StructureType.ImageCreateInfo,
                ImageType     = type,
                Format        = format,
                Extent        = extent,
                MipLevels     = levels,
                ArrayLayers   = layers,
                Samples       = sampleCountFlags,
                Tiling        = ImageTiling.Optimal,
                Usage         = usage,
                SharingMode   = SharingMode.Exclusive,
                InitialLayout = ImageLayout.Undefined,
                Flags         = flags
            };

            gd.Api.CreateImage(device, imageCreateInfo, null, out _image).ThrowOnError();

            if (foreignAllocation == null)
            {
                gd.Api.GetImageMemoryRequirements(device, _image, out var requirements);
                var allocation = gd.MemoryAllocator.AllocateDeviceMemory(physicalDevice, requirements, DefaultImageMemoryFlags);

                if (allocation.Memory.Handle == 0UL)
                {
                    gd.Api.DestroyImage(device, _image, null);
                    throw new Exception("Image initialization failed.");
                }

                _size = requirements.Size;

                gd.Api.BindImageMemory(device, _image, allocation.Memory, allocation.Offset).ThrowOnError();

                _allocationAuto = new Auto <MemoryAllocation>(allocation);
                _imageAuto      = new Auto <DisposableImage>(new DisposableImage(_gd.Api, device, _image), null, _allocationAuto);

                InitialTransition(ImageLayout.Undefined, ImageLayout.General);
            }
            else
            {
                _foreignAllocationAuto = foreignAllocation;
                foreignAllocation.IncrementReferenceCount();
                var allocation = foreignAllocation.GetUnsafe();

                gd.Api.BindImageMemory(device, _image, allocation.Memory, allocation.Offset).ThrowOnError();

                _imageAuto = new Auto <DisposableImage>(new DisposableImage(_gd.Api, device, _image));

                InitialTransition(ImageLayout.Preinitialized, ImageLayout.General);
            }
        }
コード例 #30
0
        /// <summary>
        /// Tries to find an existing texture, or create a new one if not found.
        /// </summary>
        /// <param name="info">Texture information of the texture to be found or created</param>
        /// <param name="flags">The texture search flags, defines texture comparison rules</param>
        /// <returns>The texture</returns>
        public Texture FindOrCreateTexture(TextureInfo info, TextureSearchFlags flags = TextureSearchFlags.None)
        {
            bool isSamplerTexture = (flags & TextureSearchFlags.Sampler) != 0;

            // Try to find a perfect texture match, with the same address and parameters.
            int sameAddressOverlapsCount = _textures.FindOverlaps(info.Address, ref _textureOverlaps);

            for (int index = 0; index < sameAddressOverlapsCount; index++)
            {
                Texture overlap = _textureOverlaps[index];

                if (overlap.IsPerfectMatch(info, flags))
                {
                    if (!isSamplerTexture)
                    {
                        // If not a sampler texture, it is managed by the auto delete
                        // cache, ensure that it is on the "top" of the list to avoid
                        // deletion.
                        _cache.Lift(overlap);
                    }
                    else if (!overlap.SizeMatches(info))
                    {
                        // If this is used for sampling, the size must match,
                        // otherwise the shader would sample garbage data.
                        // To fix that, we create a new texture with the correct
                        // size, and copy the data from the old one to the new one.
                        overlap.ChangeSize(info.Width, info.Height, info.DepthOrLayers);
                    }

                    return(overlap);
                }
            }

            // Calculate texture sizes, used to find all overlapping textures.
            SizeInfo sizeInfo;

            if (info.IsLinear)
            {
                sizeInfo = SizeCalculator.GetLinearTextureSize(
                    info.Stride,
                    info.Height,
                    info.FormatInfo.BlockHeight);
            }
            else
            {
                sizeInfo = SizeCalculator.GetBlockLinearTextureSize(
                    info.Width,
                    info.Height,
                    info.GetDepth(),
                    info.Levels,
                    info.GetLayers(),
                    info.FormatInfo.BlockWidth,
                    info.FormatInfo.BlockHeight,
                    info.FormatInfo.BytesPerPixel,
                    info.GobBlocksInY,
                    info.GobBlocksInZ,
                    info.GobBlocksInTileX);
            }

            // Find view compatible matches.
            ulong size = (ulong)sizeInfo.TotalSize;

            int overlapsCount = _textures.FindOverlaps(info.Address, size, ref _textureOverlaps);

            Texture texture = null;

            for (int index = 0; index < overlapsCount; index++)
            {
                Texture overlap = _textureOverlaps[index];

                if (overlap.IsViewCompatible(info, size, out int firstLayer, out int firstLevel))
                {
                    if (!isSamplerTexture)
                    {
                        info = AdjustSizes(overlap, info, firstLevel);
                    }

                    texture = overlap.CreateView(info, sizeInfo, firstLayer, firstLevel);

                    if (IsTextureModified(overlap))
                    {
                        CacheTextureModified(texture);
                    }

                    // The size only matters (and is only really reliable) when the
                    // texture is used on a sampler, because otherwise the size will be
                    // aligned.
                    if (!overlap.SizeMatches(info, firstLevel) && isSamplerTexture)
                    {
                        texture.ChangeSize(info.Width, info.Height, info.DepthOrLayers);
                    }

                    break;
                }
            }

            // No match, create a new texture.
            if (texture == null)
            {
                texture = new Texture(_context, info, sizeInfo);

                // We need to synchronize before copying the old view data to the texture,
                // otherwise the copied data would be overwritten by a future synchronization.
                texture.SynchronizeMemory();

                for (int index = 0; index < overlapsCount; index++)
                {
                    Texture overlap = _textureOverlaps[index];

                    if (texture.IsViewCompatible(overlap.Info, overlap.Size, out int firstLayer, out int firstLevel))
                    {
                        TextureInfo overlapInfo = AdjustSizes(texture, overlap.Info, firstLevel);

                        TextureCreateInfo createInfo = GetCreateInfo(overlapInfo, _context.Capabilities);

                        ITexture newView = texture.HostTexture.CreateView(createInfo, firstLayer, firstLevel);

                        overlap.HostTexture.CopyTo(newView, 0, 0);

                        // Inherit modification from overlapping texture, do that before replacing
                        // the view since the replacement operation removes it from the list.
                        if (IsTextureModified(overlap))
                        {
                            CacheTextureModified(texture);
                        }

                        overlap.ReplaceView(texture, overlapInfo, newView);
                    }
                }

                // If the texture is a 3D texture, we need to additionally copy any slice
                // of the 3D texture to the newly created 3D texture.
                if (info.Target == Target.Texture3D)
                {
                    for (int index = 0; index < overlapsCount; index++)
                    {
                        Texture overlap = _textureOverlaps[index];

                        if (texture.IsViewCompatible(
                                overlap.Info,
                                overlap.Size,
                                isCopy: true,
                                out int firstLayer,
                                out int firstLevel))
                        {
                            overlap.HostTexture.CopyTo(texture.HostTexture, firstLayer, firstLevel);

                            if (IsTextureModified(overlap))
                            {
                                CacheTextureModified(texture);
                            }
                        }
                    }
                }
            }

            // Sampler textures are managed by the texture pool, all other textures
            // are managed by the auto delete cache.
            if (!isSamplerTexture)
            {
                _cache.Add(texture);
                texture.Modified += CacheTextureModified;
                texture.Disposed += CacheTextureDisposed;
            }

            _textures.Add(texture);

            ShrinkOverlapsBufferIfNeeded();

            return(texture);
        }