Ejemplo n.º 1
0
        internal bool Load(bool wait, Func <Texture2D> load)
        {
            if (LoadImmediately)
            {
                Texture_Unsafe?.Dispose();
                Texture_Unsafe = load();
                FreeFastTextureLoad();
                return(true);
            }

            // Let's queue a reload onto the main thread and call it a day.
            // Make sure to read the texture size immediately though!
            object queuedLoadLock;

            lock (queuedLoadLock = new object()) {
                _Texture_QueuedLoadLock = queuedLoadLock;

                Func <Texture2D> _load = load;
                load = () => {
                    Texture2D tex;
                    lock (queuedLoadLock) {
                        if (_Texture_QueuedLoadLock != queuedLoadLock)
                        {
                            _load = null;
                            FreeFastTextureLoad();
                            return(Texture_Unsafe);
                        }
                        // NOTE: If something dares to change texture info on the fly, GOOD LUCK.
                        Texture_Unsafe?.Dispose();
                        Texture_Unsafe = tex = _load();
                        FreeFastTextureLoad();
                        _Texture_QueuedLoadLock = null;
                    }
                    if (_Texture_UnloadAfterReload)
                    {
                        tex?.Dispose();
                        tex = Texture_Unsafe;
                        // ... can anything even swap the texture here?
                        Texture_Unsafe = null;
                        tex?.Dispose();
                        _Texture_UnloadAfterReload = false;
                    }
                    return(tex);
                };

                _Texture_QueuedLoad = !_Texture_FTLLoading?
                                      MainThreadHelper.GetForceQueue(load) :
                                          MainThreadHelper.Get(load);
            }

            if (wait || _Texture_Requesting)
            {
                _Texture_QueuedLoad.GetResult();
            }

            return(false);
        }
Ejemplo n.º 2
0
        private bool ResetVertexBuffer()
        {
            // Checking for IsDisposed on other threads should be fine...
            if (Vertices != null && !Vertices.IsDisposed && !Vertices.GraphicsDevice.IsDisposed)
            {
                return(false);
            }

            // Handle already queued loads appropriately.
            object queuedLoadLock = _Vertices_QueuedLoadLock;

            if (queuedLoadLock != null)
            {
                lock (queuedLoadLock) {
                    // Queued task finished just in time.
                    if (_Vertices_QueuedLoadLock == null)
                    {
                        return(true);
                    }

                    // If we still can, cancel the queued load, then proceed with lazy-loading.
                    if (MainThreadHelper.IsMainThread)
                    {
                        _Vertices_QueuedLoadLock = null;
                    }
                }

                if (!MainThreadHelper.IsMainThread)
                {
                    // Otherwise wait for it to get loaded, don't reload twice. (Don't wait locked!)
                    while (!_Vertices_QueuedLoad.IsValid)
                    {
                        Thread.Yield();
                    }
                    _Vertices_QueuedLoad.GetResult();
                    return(true);
                }
            }

            if (!(CoreModule.Settings.ThreadedGL ?? Everest.Flags.PreferThreadedGL) && !MainThreadHelper.IsMainThread && queuedLoadLock == null)
            {
                // Let's queue a reload onto the main thread and call it a day.
                lock (queuedLoadLock = new object()) {
                    _Vertices_QueuedLoadLock = queuedLoadLock;
                    _Vertices_QueuedLoad     = MainThreadHelper.Get(() => {
                        lock (queuedLoadLock) {
                            if (_Vertices_QueuedLoadLock == null)
                            {
                                return(Vertices);
                            }
                            // Force-reload as we already returned true on the other thread.
                            Vertices?.Dispose();
                            // NOTE: If something dares to change verts on the fly, make it wait on any existing tasks, then make it force-reload.
                            Vertices = new VertexBuffer(Engine.Graphics.GraphicsDevice, typeof(VertexPositionTexture), verts.Length, BufferUsage.None);
                            Vertices.SetData(verts);
                            _Vertices_QueuedLoadLock = null;
                            return(Vertices);
                        }
                    });
                }
                return(true);
            }

            return(orig_ResetVertexBuffer());
        }
Ejemplo n.º 3
0
        internal override void Unload()
        {
            Texture2D tex = Texture_Unsafe;

            // Handle already queued loads appropriately.
            object queuedLoadLock = _Texture_QueuedLoadLock;

            if (queuedLoadLock != null)
            {
                bool gotLock = false;
                try {
                    Monitor.TryEnter(queuedLoadLock, ref gotLock);
                    if (gotLock)
                    {
                        if (_Texture_QueuedLoadLock != null)
                        {
                            // If we still can, cancel the queued load.
                            _Texture_QueuedLoadLock = null;
                        }
                    }
                    else
                    {
                        // Welp.
                        _Texture_UnloadAfterReload = true;
                        Monitor.TryEnter(queuedLoadLock, ref gotLock);
                        if (gotLock)
                        {
                            // It might be too late - let's unload ourselves.
                            _Texture_UnloadAfterReload = false;
                        }
                        else
                        {
                            // The loader will still handle the request.
                            return;
                        }
                    }
                } finally {
                    if (gotLock)
                    {
                        Monitor.Exit(queuedLoadLock);
                    }
                }

                if (!MainThreadHelper.IsMainThread)
                {
                    // Otherwise wait for it to get loaded. (Don't wait locked!)
                    while (!_Texture_QueuedLoad.IsValid)
                    {
                        Thread.Yield();
                    }
                    tex = _Texture_QueuedLoad.GetResult();
                }
            }

            Texture_Unsafe = null;
            if (tex == null || tex.IsDisposed)
            {
                return;
            }

            if (!(CoreModule.Settings.ThreadedGL ?? Everest.Flags.PreferThreadedGL) && !MainThreadHelper.IsMainThread)
            {
                MainThreadHelper.Do(() => tex.Dispose());
            }
            else
            {
                tex.Dispose();
            }
        }
Ejemplo n.º 4
0
        public new void ResetBillboardBuffers()
        {
            // Checking for IsDisposed on other threads should be fine...
            if (billboardVertices != null && !billboardIndices.IsDisposed && !billboardIndices.GraphicsDevice.IsDisposed &&
                billboardVertices != null && !billboardVertices.IsDisposed && !billboardVertices.GraphicsDevice.IsDisposed &&
                billboardInfo.Length <= billboardVertices.VertexCount)
            {
                return;
            }

            // Handle already queued loads appropriately.
            object queuedLoadLock = _Billboard_QueuedLoadLock;

            if (queuedLoadLock != null)
            {
                lock (queuedLoadLock) {
                    // Queued task finished just in time.
                    if (_Billboard_QueuedLoadLock == null)
                    {
                        return;
                    }

                    // If we still can, cancel the queued load, then proceed with lazy-loading.
                    if (MainThreadHelper.IsMainThread)
                    {
                        _Billboard_QueuedLoadLock = null;
                    }
                }

                if (!MainThreadHelper.IsMainThread)
                {
                    // Otherwise wait for it to get loaded, don't reload twice. (Don't wait locked!)
                    while (!_Billboard_QueuedLoad.IsValid)
                    {
                        Thread.Yield();
                    }
                    _Billboard_QueuedLoad.GetResult();
                    return;
                }
            }

            if (!(CoreModule.Settings.ThreadedGL ?? Everest.Flags.PreferThreadedGL) && !MainThreadHelper.IsMainThread && queuedLoadLock == null)
            {
                // Let's queue a reload onto the main thread and call it a day.
                lock (queuedLoadLock = new object()) {
                    _Billboard_QueuedLoadLock = queuedLoadLock;
                    _Billboard_QueuedLoad     = MainThreadHelper.Get(() => {
                        lock (queuedLoadLock) {
                            if (_Billboard_QueuedLoadLock == null)
                            {
                                return(billboardVertices);
                            }
                            // Force-reload as we already returned true on the other thread.
                            if (billboardVertices != null && !billboardVertices.IsDisposed)
                            {
                                billboardVertices.Dispose();
                            }
                            if (billboardIndices != null && !billboardIndices.IsDisposed)
                            {
                                billboardIndices.Dispose();
                            }
                            // NOTE: If something dares to change verts on the fly, make it wait on any existing tasks, then make it force-reload.
                            // Let's rely on the original code for now.
                            orig_ResetBillboardBuffers();
                            _Billboard_QueuedLoadLock = null;
                            return(billboardVertices);
                        }
                    });
                }
                return;
            }

            orig_ResetBillboardBuffers();
        }