diff --git a/osu.Framework.Font/Graphics/MultiShaderBufferedDrawNode.cs b/osu.Framework.Font/Graphics/MultiShaderBufferedDrawNode.cs index c03a794d..03be370f 100644 --- a/osu.Framework.Font/Graphics/MultiShaderBufferedDrawNode.cs +++ b/osu.Framework.Font/Graphics/MultiShaderBufferedDrawNode.cs @@ -3,7 +3,6 @@ using System; using System.Collections.Generic; -using System.IO; using System.Linq; using System.Reflection; using osu.Framework.Graphics.Colour; @@ -92,6 +91,10 @@ protected override void DrawContents() { foreach (var frameBuffer in drawFrameBuffers) { + // got no idea why happened. + if (frameBuffer.Texture == null) + break; + DrawFrameBuffer(frameBuffer, DrawRectangle, Color4.White); } } @@ -111,8 +114,8 @@ private void drawFrameBuffer() foreach (var shader in shaders) { - var current = getSourceFrameBuffer(shader); - var target = SharedData.ShaderBuffers[shader]; + var current = SharedData.GetSourceFrameBuffer(shader); + var target = SharedData.GetTargetFrameBuffer(shader); if (shader is IStepShader stepShader) { @@ -149,22 +152,6 @@ void renderShader(IShader shader, FrameBuffer current, FrameBuffer target) shader.Unbind(); } } - - FrameBuffer getSourceFrameBuffer(IShader targetShader) - { - if (!(targetShader is IStepShader stepShader)) - return SharedData.CurrentEffectBuffer; - - var fromShader = stepShader.FromShader; - if (fromShader == null) - return SharedData.CurrentEffectBuffer; - - var shaderBuffers = SharedData.ShaderBuffers; - if (!shaderBuffers.ContainsKey(fromShader)) - throw new DirectoryNotFoundException("Frame buffer does not found in target shader."); - - return shaderBuffers[fromShader]; - } } } } diff --git a/osu.Framework.Font/Graphics/MultiShaderBufferedDrawNodeSharedData.cs b/osu.Framework.Font/Graphics/MultiShaderBufferedDrawNodeSharedData.cs index 3207e9a6..a75db32f 100644 --- a/osu.Framework.Font/Graphics/MultiShaderBufferedDrawNodeSharedData.cs +++ b/osu.Framework.Font/Graphics/MultiShaderBufferedDrawNodeSharedData.cs @@ -3,7 +3,10 @@ using System; using System.Collections.Generic; +using System.IO; using System.Linq; +using System.Reflection; +using osu.Framework.Graphics.OpenGL; using osu.Framework.Graphics.OpenGL.Buffers; using osu.Framework.Graphics.Shaders; using osuTK.Graphics.ES30; @@ -14,8 +17,6 @@ public class MultiShaderBufferedDrawNodeSharedData : BufferedDrawNodeSharedData { private readonly Dictionary shaderBuffers = new Dictionary(); - public IReadOnlyDictionary ShaderBuffers => shaderBuffers; - private readonly RenderbufferInternalFormat[] formats; public MultiShaderBufferedDrawNodeSharedData(RenderbufferInternalFormat[] formats = null, bool pixelSnapping = false) @@ -26,14 +27,56 @@ public MultiShaderBufferedDrawNodeSharedData(RenderbufferInternalFormat[] format public void CreateDefaultFrameBuffers(IShader[] shaders) { - clearBuffers(); + if (shaderBuffers.Keys.SequenceEqual(shaders)) + return; - var filterMode = PixelSnapping ? All.Nearest : All.Linear; + var disposedFrameBuffer = shaderBuffers.Values.ToArray(); + shaderBuffers.Clear(); foreach (var shader in shaders) { + var filterMode = PixelSnapping ? All.Nearest : All.Linear; shaderBuffers.Add(shader, new FrameBuffer(formats, filterMode)); } + + clearBuffersWithSchedule(() => + { + clearBuffers(disposedFrameBuffer); + }); + + static void clearBuffersWithSchedule(Action action) + { + // should call GLWrapper.ScheduleDisposal(() => Dispose(true)); + Delegate act = new Action(() => action?.Invoke()); + var prop = typeof(GLWrapper).GetRuntimeMethods().FirstOrDefault(x => x.Name == "ScheduleDisposal"); + if (prop == null) + throw new NullReferenceException(); + + prop.Invoke(prop, new object[] { act }); + } + } + + public FrameBuffer GetSourceFrameBuffer(IShader shader) + { + if (!(shader is IStepShader stepShader)) + return CurrentEffectBuffer; + + var fromShader = stepShader.FromShader; + if (fromShader == null) + return CurrentEffectBuffer; + + if (!shaderBuffers.ContainsKey(fromShader)) + throw new DirectoryNotFoundException(); + + return shaderBuffers[fromShader]; + } + + public FrameBuffer GetTargetFrameBuffer(IShader shader) + { + if (!shaderBuffers.ContainsKey(shader)) + throw new DirectoryNotFoundException(); + + return shaderBuffers[shader]; } public void UpdateBuffer(IShader shader, FrameBuffer frameBuffer) @@ -45,7 +88,7 @@ public void UpdateBuffer(IShader shader, FrameBuffer frameBuffer) } public FrameBuffer[] GetDrawFrameBuffers() - => ShaderBuffers.Where(x => + => shaderBuffers.Where(x => { var shader = x.Key; if (shader is IStepShader stepShader) @@ -57,18 +100,16 @@ public FrameBuffer[] GetDrawFrameBuffers() protected override void Dispose(bool isDisposing) { base.Dispose(isDisposing); - clearBuffers(); + clearBuffers(shaderBuffers.Values.ToArray()); } - private void clearBuffers() + private void clearBuffers(FrameBuffer[] effectBuffers) { - // clear all frame in the dictionary. - foreach (var shaderBuffer in shaderBuffers) + // dispose all frame buffer in array. + foreach (var shaderBuffer in effectBuffers) { - shaderBuffer.Value.Dispose(); + shaderBuffer.Dispose(); } - - shaderBuffers.Clear(); } } }