예제 #1
0
        /// <summary>
        /// Create a new texture group handle, representing a range of views in a storage texture.
        /// </summary>
        /// <param name="group">The TextureGroup that the handle belongs to</param>
        /// <param name="offset">The byte offset from the start of the storage of the handle</param>
        /// <param name="size">The size in bytes covered by the handle</param>
        /// <param name="views">All views of the storage texture, used to calculate overlaps</param>
        /// <param name="firstLayer">The first layer of this handle in the storage texture</param>
        /// <param name="firstLevel">The first level of this handle in the storage texture</param>
        /// <param name="baseSlice">The base slice index of this handle</param>
        /// <param name="sliceCount">The number of slices this handle covers</param>
        /// <param name="handles">The memory tracking handles that cover this handle</param>
        public TextureGroupHandle(TextureGroup group,
                                  int offset,
                                  ulong size,
                                  List <Texture> views,
                                  int firstLayer,
                                  int firstLevel,
                                  int baseSlice,
                                  int sliceCount,
                                  CpuRegionHandle[] handles)
        {
            _group      = group;
            _firstLayer = firstLayer;
            _firstLevel = firstLevel;

            Offset       = offset;
            Size         = (int)size;
            Overlaps     = new List <Texture>();
            Dependencies = new List <TextureDependency>();

            BaseSlice  = baseSlice;
            SliceCount = sliceCount;

            if (views != null)
            {
                RecalculateOverlaps(group, views);
            }

            Handles = handles;
        }
예제 #2
0
        /// <summary>
        /// Check if this handle has a dependency to a given texture group.
        /// </summary>
        /// <param name="group">The texture group to check for</param>
        /// <returns>True if there is a dependency, false otherwise</returns>
        public bool HasDependencyTo(TextureGroup group)
        {
            foreach (TextureDependency dep in Dependencies)
            {
                if (dep.Other.Handle._group == group)
                {
                    return(true);
                }
            }

            return(false);
        }
예제 #3
0
        /// <summary>
        /// Inherit state from another texture group.
        /// </summary>
        /// <param name="other">The texture group to inherit from</param>
        public void Inherit(TextureGroup other)
        {
            bool layerViews = _hasLayerViews || other._hasLayerViews;
            bool mipViews   = _hasMipViews || other._hasMipViews;

            if (layerViews != _hasLayerViews || mipViews != _hasMipViews)
            {
                _hasLayerViews = layerViews;
                _hasMipViews   = mipViews;

                RecalculateHandleRegions();
            }

            InheritHandles(other._handles, _handles);
        }
예제 #4
0
        /// <summary>
        /// Calculate a list of which views overlap this handle.
        /// </summary>
        /// <param name="group">The parent texture group, used to find a view's base CPU VA offset</param>
        /// <param name="views">The list of views to search for overlaps</param>
        public void RecalculateOverlaps(TextureGroup group, List <Texture> views)
        {
            // Overlaps can be accessed from the memory tracking signal handler, so access must be atomic.
            lock (Overlaps)
            {
                int endOffset = Offset + Size;

                Overlaps.Clear();

                foreach (Texture view in views)
                {
                    int viewOffset = group.FindOffset(view);
                    if (viewOffset < endOffset && Offset < viewOffset + (int)view.Size)
                    {
                        Overlaps.Add(view);
                    }
                }
            }
        }
예제 #5
0
        /// <summary>
        /// Create a copy dependency between this texture group, and a texture at a given layer/level offset.
        /// </summary>
        /// <param name="other">The view compatible texture to create a dependency to</param>
        /// <param name="firstLayer">The base layer of the given texture relative to the storage</param>
        /// <param name="firstLevel">The base level of the given texture relative to the storage</param>
        /// <param name="copyTo">True if this texture is first copied to the given one, false for the opposite direction</param>
        public void CreateCopyDependency(Texture other, int firstLayer, int firstLevel, bool copyTo)
        {
            TextureGroup otherGroup = other.Group;

            EnsureFullSubdivision();
            otherGroup.EnsureFullSubdivision();

            // Get the location of each texture within its storage, so we can find the handles to apply the dependency to.
            // This can consist of multiple disjoint regions, for example if this is a mip slice of an array texture.

            var targetRange = new List <(int BaseHandle, int RegionCount)>();
            var otherRange  = new List <(int BaseHandle, int RegionCount)>();

            EvaluateRelevantHandles(firstLayer, firstLevel, other.Info.GetSlices(), other.Info.Levels, (baseHandle, regionCount, split) => targetRange.Add((baseHandle, regionCount)));
            otherGroup.EvaluateRelevantHandles(other, (baseHandle, regionCount, split) => otherRange.Add((baseHandle, regionCount)));

            int targetIndex = 0;
            int otherIndex  = 0;

            (int Handle, int RegionCount)targetRegion = (0, 0);
            (int Handle, int RegionCount)otherRegion  = (0, 0);

            while (true)
            {
                if (targetRegion.RegionCount == 0)
                {
                    if (targetIndex >= targetRange.Count)
                    {
                        break;
                    }

                    targetRegion = targetRange[targetIndex++];
                }

                if (otherRegion.RegionCount == 0)
                {
                    if (otherIndex >= otherRange.Count)
                    {
                        break;
                    }

                    otherRegion = otherRange[otherIndex++];
                }

                TextureGroupHandle handle      = _handles[targetRegion.Handle++];
                TextureGroupHandle otherHandle = other.Group._handles[otherRegion.Handle++];

                targetRegion.RegionCount--;
                otherRegion.RegionCount--;

                handle.CreateCopyDependency(otherHandle, copyTo);

                // If "copyTo" is true, this texture must copy to the other.
                // Otherwise, it must copy to this texture.

                if (copyTo)
                {
                    otherHandle.Copy(handle);
                }
                else
                {
                    handle.Copy(otherHandle);
                }
            }
        }
예제 #6
0
        /// <summary>
        /// Initialize a new texture group with this texture as storage.
        /// </summary>
        /// <param name="hasLayerViews">True if the texture will have layer views</param>
        /// <param name="hasMipViews">True if the texture will have mip views</param>
        public void InitializeGroup(bool hasLayerViews, bool hasMipViews)
        {
            Group = new TextureGroup(_context, this);

            Group.Initialize(ref _sizeInfo, hasLayerViews, hasMipViews);
        }