Exemplo n.º 1
0
        private void SplitHandle(int handleIndex, int splitIndex)
        {
            RegionHandle handle  = _handles[handleIndex];
            ulong        address = _address + HandlesToBytes(handleIndex);
            ulong        size    = HandlesToBytes(splitIndex - handleIndex);

            // First, the target handle must be removed. Its data can still be used to determine the new handles.
            RegionSignal signal = handle.PreAction;

            handle.Dispose();

            RegionHandle splitLow = _tracking.BeginTracking(address, size);

            splitLow.Parent = this;
            if (signal != null)
            {
                splitLow.RegisterAction(signal);
            }
            _handles[handleIndex] = splitLow;

            RegionHandle splitHigh = _tracking.BeginTracking(address + size, handle.Size - size);

            splitHigh.Parent = this;
            if (signal != null)
            {
                splitHigh.RegisterAction(signal);
            }
            _handles[splitIndex] = splitHigh;
        }
Exemplo n.º 2
0
 /// <summary>
 /// Register an action to perform when the tracked region is read or written.
 /// The action is automatically removed after it runs.
 /// </summary>
 /// <param name="action">Action to call on read or write</param>
 public void RegisterAction(RegionSignal action)
 {
     foreach (var regionHandle in _cpuRegionHandles)
     {
         regionHandle.RegisterAction(action);
     }
 }
Exemplo n.º 3
0
        /// <summary>
        /// Creates a new instance of the buffer.
        /// </summary>
        /// <param name="context">GPU context that the buffer belongs to</param>
        /// <param name="physicalMemory">Physical memory where the buffer is mapped</param>
        /// <param name="address">Start address of the buffer</param>
        /// <param name="size">Size of the buffer in bytes</param>
        /// <param name="baseBuffers">Buffers which this buffer contains, and will inherit tracking handles from</param>
        public Buffer(GpuContext context, PhysicalMemory physicalMemory, ulong address, ulong size, IEnumerable <Buffer> baseBuffers = null)
        {
            _context        = context;
            _physicalMemory = physicalMemory;
            Address         = address;
            Size            = size;

            Handle = context.Renderer.CreateBuffer((int)size);

            _useGranular = size > GranularBufferThreshold;

            IEnumerable <IRegionHandle> baseHandles = null;

            if (baseBuffers != null)
            {
                baseHandles = baseBuffers.SelectMany(buffer =>
                {
                    if (buffer._useGranular)
                    {
                        return(buffer._memoryTrackingGranular.GetHandles());
                    }
                    else
                    {
                        return(Enumerable.Repeat(buffer._memoryTracking.GetHandle(), 1));
                    }
                });
            }

            if (_useGranular)
            {
                _memoryTrackingGranular = physicalMemory.BeginGranularTracking(address, size, baseHandles);

                _memoryTrackingGranular.RegisterPreciseAction(address, size, PreciseAction);
            }
            else
            {
                _memoryTracking = physicalMemory.BeginTracking(address, size);

                if (baseHandles != null)
                {
                    _memoryTracking.Reprotect(false);

                    foreach (IRegionHandle handle in baseHandles)
                    {
                        if (handle.Dirty)
                        {
                            _memoryTracking.Reprotect(true);
                        }

                        handle.Dispose();
                    }
                }

                _memoryTracking.RegisterPreciseAction(PreciseAction);
            }

            _externalFlushDelegate = new RegionSignal(ExternalFlush);
            _loadDelegate          = new Action <ulong, ulong>(LoadRegion);
            _modifiedDelegate      = new Action <ulong, ulong>(RegionModified);
        }
Exemplo n.º 4
0
 public void RegisterAction(RegionSignal action)
 {
     foreach (var handle in _handles)
     {
         if (handle != null)
         {
             handle?.RegisterAction((address, size) => action(handle.Address, handle.Size));
         }
     }
 }
Exemplo n.º 5
0
        public void RegisterAction(ulong address, ulong size, RegionSignal action)
        {
            int startHandle = (int)((address - Address) / Granularity);
            int lastHandle  = (int)((address + (size - 1) - Address) / Granularity);

            for (int i = startHandle; i <= lastHandle; i++)
            {
                _handles[i].RegisterAction(action);
            }
        }
Exemplo n.º 6
0
        /// <summary>
        /// Signal that a memory action occurred within this handle's virtual regions.
        /// </summary>
        /// <param name="write">Whether the region was written to or read</param>
        internal void Signal(ulong address, ulong size, bool write)
        {
            RegionSignal action = Interlocked.Exchange(ref _preAction, null);

            action?.Invoke(address, size);

            if (write)
            {
                Dirty = true;
                Parent?.SignalWrite();
            }
        }
Exemplo n.º 7
0
        /// <summary>
        /// Register an action to perform when the tracked region is read or written.
        /// The action is automatically removed after it runs.
        /// </summary>
        /// <param name="action">Action to call on read or write</param>
        public void RegisterAction(RegionSignal action)
        {
            RegionSignal lastAction = Interlocked.Exchange(ref _preAction, action);

            if (lastAction == null && action != lastAction)
            {
                lock (_tracking.TrackingLock)
                {
                    foreach (VirtualRegion region in _regions)
                    {
                        region.UpdateProtection();
                    }
                }
            }
        }
Exemplo n.º 8
0
        /// <summary>
        /// Signal that a memory action occurred within this handle's virtual regions.
        /// </summary>
        /// <param name="address">Address accessed</param>
        /// <param name="size">Size of the region affected in bytes</param>
        /// <param name="write">Whether the region was written to or read</param>
        /// <param name="handleIterable">Reference to the handles being iterated, in case the list needs to be copied</param>
        internal void Signal(ulong address, ulong size, bool write, ref IList <RegionHandle> handleIterable)
        {
            // If this handle was already unmapped (even if just partially),
            // then we have nothing to do until it is mapped again.
            // The pre-action should be still consumed to avoid flushing on remap.
            if (Unmapped)
            {
                Interlocked.Exchange(ref _preAction, null);
                return;
            }

            if (_preAction != null)
            {
                // Copy the handles list in case it changes when we're out of the lock.
                if (handleIterable is List <RegionHandle> )
                {
                    handleIterable = handleIterable.ToArray();
                }

                // Temporarily release the tracking lock while we're running the action.
                Monitor.Exit(_tracking.TrackingLock);

                try
                {
                    lock (_preActionLock)
                    {
                        _preAction?.Invoke(address, size);

                        _preAction = null;
                    }
                }
                finally
                {
                    Monitor.Enter(_tracking.TrackingLock);
                }
            }

            if (write)
            {
                bool oldDirty = Dirty;
                Dirty = true;
                if (!oldDirty)
                {
                    _onDirty?.Invoke();
                }
                Parent?.SignalWrite();
            }
        }
Exemplo n.º 9
0
        /// <summary>
        /// Register an action to perform when the tracked region is read or written.
        /// The action is automatically removed after it runs.
        /// </summary>
        /// <param name="action">Action to call on read or write</param>
        public void RegisterAction(RegionSignal action)
        {
            ClearVolatile();

            lock (_preActionLock)
            {
                RegionSignal lastAction = _preAction;
                _preAction = action;

                if (lastAction == null && action != lastAction)
                {
                    lock (_tracking.TrackingLock)
                    {
                        foreach (VirtualRegion region in _regions)
                        {
                            region.UpdateProtection();
                        }
                    }
                }
            }
        }
Exemplo n.º 10
0
        /// <summary>
        /// Creates a new instance of the buffer.
        /// </summary>
        /// <param name="context">GPU context that the buffer belongs to</param>
        /// <param name="address">Start address of the buffer</param>
        /// <param name="size">Size of the buffer in bytes</param>
        public Buffer(GpuContext context, ulong address, ulong size)
        {
            _context = context;
            Address  = address;
            Size     = size;

            Handle = context.Renderer.CreateBuffer((int)size);

            _useGranular = size > GranularBufferThreshold;

            if (_useGranular)
            {
                _memoryTrackingGranular = context.PhysicalMemory.BeginGranularTracking(address, size);
            }
            else
            {
                _memoryTracking = context.PhysicalMemory.BeginTracking(address, size);
            }

            _externalFlushDelegate = new RegionSignal(ExternalFlush);
            _loadDelegate          = new Action <ulong, ulong>(LoadRegion);
            _modifiedDelegate      = new Action <ulong, ulong>(RegionModified);
        }
Exemplo n.º 11
0
 public void RegisterAction(RegionSignal action) => _impl.RegisterAction(action);
Exemplo n.º 12
0
        internal MultiRegionHandle(MemoryTracking tracking, ulong address, ulong size, IEnumerable <IRegionHandle> handles, ulong granularity)
        {
            _handles    = new RegionHandle[size / granularity];
            Granularity = granularity;

            int i = 0;

            if (handles != null)
            {
                // Inherit from the handles we were given. Any gaps must be filled with new handles,
                // and old handles larger than our granularity must copy their state onto new granular handles and dispose.
                // It is assumed that the provided handles do not overlap, in order, are on page boundaries,
                // and don't extend past the requested range.

                foreach (RegionHandle handle in handles)
                {
                    int startIndex = (int)((handle.Address - address) / granularity);

                    // Fill any gap left before this handle.
                    while (i < startIndex)
                    {
                        RegionHandle fillHandle = tracking.BeginTracking(address + (ulong)i * granularity, granularity);
                        fillHandle.Parent = this;
                        _handles[i++]     = fillHandle;
                    }

                    if (handle.Size == granularity)
                    {
                        handle.Parent = this;
                        _handles[i++] = handle;
                    }
                    else
                    {
                        int endIndex = (int)((handle.EndAddress - address) / granularity);

                        while (i < endIndex)
                        {
                            RegionHandle splitHandle = tracking.BeginTracking(address + (ulong)i * granularity, granularity);
                            splitHandle.Parent = this;

                            splitHandle.Reprotect(handle.Dirty);

                            RegionSignal signal = handle.PreAction;
                            if (signal != null)
                            {
                                splitHandle.RegisterAction(signal);
                            }

                            _handles[i++] = splitHandle;
                        }

                        handle.Dispose();
                    }
                }
            }

            // Fill any remaining space with new handles.
            while (i < _handles.Length)
            {
                RegionHandle handle = tracking.BeginTracking(address + (ulong)i * granularity, granularity);
                handle.Parent = this;
                _handles[i++] = handle;
            }

            Address = address;
            Size    = size;
        }
Exemplo n.º 13
0
 public void RegisterAction(ulong address, ulong size, RegionSignal action) => _impl.RegisterAction(address, size, action);