Skip to content

Commit b906dd7

Browse files
authored
Fix bugs with premature usage of OpenGL and Vulkan functions (#484)
1 parent d5cd6b4 commit b906dd7

File tree

5 files changed

+102
-30
lines changed

5 files changed

+102
-30
lines changed

src/Lab/InputTest/Program.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -197,7 +197,7 @@ public static unsafe void DoConnect(IInputDevice device, bool isConnected)
197197
mouse.MouseMove -= MouseOnMouseMove;
198198
}
199199

200-
mouse.Cursor.IsConfined = true;
200+
// mouse.Cursor.IsConfined = true;
201201

202202
Console.Write(" Buttons: ");
203203
Console.WriteLine(string.Join(", ", mouse.SupportedButtons.Select(x => x)));

src/Lab/Triangle/Program.cs

Lines changed: 25 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
#define MINIMAL
1+
#define REOPEN_EXPERIMENT
22

33
using System;
44
using System.Drawing;
@@ -24,39 +24,50 @@ public static class Program
2424
private static uint _vertexBufferObject;
2525
private static uint _vertexArrayObject;
2626
private static GL _gl;
27-
#if MINIMAL
2827
private static IView _window;
29-
#else
30-
private static IWindow _window;
31-
#endif
3228
private static Shader _shader;
3329

3430
public static GraphicsAPI API { get; set; } = GraphicsAPI.Default;
3531

3632
public static void Main(string[] args)
3733
{
34+
//Silk.NET.Windowing.Sdl.SdlWindowing.Use();
3835
//SdlProvider.SetMainReady = true;
39-
#if MINIMAL
4036
var opts = ViewOptions.Default;
4137
opts.FramesPerSecond = 90;
4238
opts.UpdatesPerSecond = 90;
4339
opts.API = API;
4440
opts.VSync = false;
45-
_window = Window.GetView(opts);
46-
#else
47-
var opts = WindowOptions.Default;
48-
opts.FramesPerSecond = 90;
49-
opts.API = API;
50-
opts.UpdatesPerSecond = 90;
51-
_window = Window.Create(opts);
52-
#endif
41+
if (Window.IsViewOnly)
42+
{
43+
_window = Window.GetView(opts);
44+
}
45+
else
46+
{
47+
_window = Window.Create(new(opts));
48+
}
49+
5350
_window.Load += Load;
5451
_window.Load += InputTest.Program.OnLoad(_window);
5552
_window.Render += RenderFrame;
5653
_window.Update += UpdateFrame;
5754
_window.FramebufferResize += Resize;
5855
_window.Closing += End;
5956
_window.Run();
57+
#if REOPEN_EXPERIMENT
58+
// Experiment notes:
59+
// - This is something we're meant to support, but we've never tested it!
60+
// - GLFW worked fine, bar input which for some reason didn't work when the window reloaded.
61+
// - SDL worked flawlessly.
62+
// - Right now the Closing event can actually cancel window closure using IsClosing.
63+
// - We need to test this too.
64+
// - We need to add an Unload event that is only called once the window is guaranteed to be terminated.
65+
// - TODO for 3.0 (to add the Unload event, by all means fix bugs before then)
66+
if (_window is IWindow)
67+
{
68+
_window.Run();
69+
}
70+
#endif
6071
}
6172

6273
private static unsafe void Load()

src/Windowing/Silk.NET.Windowing.Common/Internals/ViewImplementationBase.cs

Lines changed: 48 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,14 +55,14 @@ protected ViewImplementationBase(ViewOptions opts)
5555
protected abstract Vector2D<int> CoreSize { get; }
5656
protected abstract nint CoreHandle { get; }
5757
protected abstract bool CoreIsClosing { get; }
58+
protected abstract IGLContext? CoreGLContext { get; }
59+
protected abstract IVkSurface? CoreVkSurface { get; }
5860

5961
// Function bases - again extra functionality on top
6062
protected abstract void CoreInitialize(ViewOptions opts);
6163
protected abstract void CoreReset();
6264

6365
// Other APIs implemented abstractly
64-
public abstract IGLContext? GLContext { get; }
65-
public abstract IVkSurface? VkSurface { get; }
6666
public abstract VideoMode VideoMode { get; }
6767
public abstract bool IsEventDriven { get; set; }
6868
public abstract Vector2D<int> FramebufferSize { get; }
@@ -213,6 +213,52 @@ public bool VSync
213213
}
214214
}
215215

216+
public IGLContext? GLContext
217+
{
218+
get
219+
{
220+
if (!IsInitialized && (API.API == ContextAPI.OpenGL || API.API == ContextAPI.OpenGLES))
221+
{
222+
static void Throw() => throw new InvalidOperationException
223+
(
224+
"OpenGL functions can only be used after initialization (just before the Load callback is " +
225+
"executed)"
226+
);
227+
228+
Throw();
229+
}
230+
else if (API.API != ContextAPI.OpenGL && API.API != ContextAPI.OpenGLES)
231+
{
232+
return null;
233+
}
234+
235+
return CoreGLContext;
236+
}
237+
}
238+
239+
public IVkSurface? VkSurface
240+
{
241+
get
242+
{
243+
if (!IsInitialized && API.API == ContextAPI.Vulkan)
244+
{
245+
static void Throw() => throw new InvalidOperationException
246+
(
247+
"Vulkan functions can only be used after initialization (just before the Load callback is " +
248+
"executed)"
249+
);
250+
251+
Throw();
252+
}
253+
else if (API.API != ContextAPI.Vulkan)
254+
{
255+
return null;
256+
}
257+
258+
return CoreVkSurface;
259+
}
260+
}
261+
216262
// Misc implementations
217263
[MethodImpl(MethodImplOptions.AggressiveInlining | (MethodImplOptions) 512)]
218264
public Vector2D<int> PointToFramebuffer(Vector2D<int> point)

src/Windowing/Silk.NET.Windowing.Glfw/GlfwWindow.cs

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -77,21 +77,35 @@ protected override void CoreReset()
7777
{
7878
_glfw.DestroyWindow(_glfwWindow);
7979
GLFW.Glfw.ThrowExceptions();
80-
_glfwWindow = null;
8180
}
8281
catch (GlfwException)
8382
{
8483
// If the window is already destroyed, it throws an exception,
8584
// but we want the window destroyed anyways, so just ignore it
8685
}
86+
finally
87+
{
88+
_glfwWindow = null;
89+
_glContext = null;
90+
}
8791
}
8892

89-
public override IGLContext? GLContext
90-
=> API.API == ContextAPI.OpenGL || API.API == ContextAPI.OpenGLES
91-
? _glContext ??= new(_glfw, _glfwWindow, this)
92-
: null;
93+
protected override IGLContext? CoreGLContext => _glContext ??= new(_glfw, _glfwWindow, this);
9394

94-
public override IVkSurface? VkSurface => API.API == ContextAPI.Vulkan && _glfw.VulkanSupported() ? this : null;
95+
protected override IVkSurface? CoreVkSurface
96+
{
97+
get
98+
{
99+
if (!_glfw.VulkanSupported())
100+
{
101+
static void Throw()
102+
=> throw new PlatformNotSupportedException("GLFW does not support Vulkan on this platform.");
103+
Throw();
104+
}
105+
106+
return this;
107+
}
108+
}
95109

96110
protected override bool CoreIsVisible
97111
{

src/Windowing/Silk.NET.Windowing.Sdl/SdlView.cs

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -53,11 +53,8 @@ public SdlView(void* nativeHandle, IGLContext? ctx, SdlPlatform platform) : base
5353
public override event Action<bool>? FocusChanged;
5454

5555
// Properties
56-
public override IGLContext? GLContext => _ctx ??= API.API == ContextAPI.OpenGL || API.API == ContextAPI.OpenGLES
57-
? new SdlContext(Sdl, SdlWindow, this)
58-
: null;
59-
60-
public override IVkSurface? VkSurface => _vk ??= API.API == ContextAPI.Vulkan ? new SdlVkSurface(this) : null;
56+
protected override IGLContext? CoreGLContext => _ctx ??= new SdlContext(Sdl, SdlWindow, this);
57+
protected override IVkSurface? CoreVkSurface => _vk ??= new SdlVkSurface(this);
6158
protected override nint CoreHandle => (nint) SdlWindow;
6259
internal SDL.Sdl Sdl { get; }
6360
internal SDL.Window* SdlWindow { get; private set; }
@@ -160,7 +157,7 @@ protected void CoreInitialize
160157
}
161158

162159
sharedContext?.MakeCurrent();
163-
(GLContext as SdlContext)?.Create
160+
(CoreGLContext as SdlContext)?.Create
164161
(
165162
(GLattr.GLContextMajorVersion, opts.API.Version.MajorVersion),
166163
(GLattr.GLContextMinorVersion, opts.API.Version.MinorVersion),
@@ -244,8 +241,12 @@ protected override void CoreReset()
244241
return;
245242
}
246243

247-
GLContext?.Dispose();
244+
CoreGLContext?.Dispose();
248245
Sdl.DestroyWindow(SdlWindow);
246+
247+
SdlWindow = null;
248+
_ctx = null;
249+
_vk = null;
249250
}
250251

251252
public override void DoEvents()

0 commit comments

Comments
 (0)