Skip to content

Commit

Permalink
Update
Browse files Browse the repository at this point in the history
  • Loading branch information
Tornado-Technology committed Sep 6, 2024
1 parent 09ee904 commit ab73fd3
Show file tree
Hide file tree
Showing 13 changed files with 182 additions and 99 deletions.
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System.Runtime.CompilerServices;
using Hypercube.Graphics.Monitors;
using Hypercube.Mathematics.Vectors;
using Hypercube.OpenGL.Utilities.Helpers;
using JetBrains.Annotations;
using GlfwVideoMode = OpenTK.Windowing.GraphicsLibraryFramework.VideoMode;
using Monitor = OpenTK.Windowing.GraphicsLibraryFramework.Monitor;
using VideoMode = Hypercube.Graphics.Monitors.VideoMode;
Expand All @@ -9,10 +10,10 @@ namespace Hypercube.Client.Graphics.Windows.Realisation.GLFW;

public sealed unsafe partial class GlfwWindowing
{
private readonly Dictionary<int, GlfwMonitorRegistration> _monitors = new();
private readonly Dictionary<int, MonitorHandle> _monitors = new();

private int _primaryMonitorId;
private int _nextMonitorId = 1;
private MonitorId _primaryMonitorId;
private MonitorId _nextMonitorId = MonitorId.Zero;

private void InitMonitors()
{
Expand All @@ -25,71 +26,35 @@ private void InitMonitors()

var primary = OpenTK.Windowing.GraphicsLibraryFramework.GLFW.GetPrimaryMonitor();
var up = OpenTK.Windowing.GraphicsLibraryFramework.GLFW.GetMonitorUserPointer(primary);
_primaryMonitorId = (int)up;
_primaryMonitorId = (int) up;

_logger.EngineInfo($"Initialize monitors, count: {_monitors.Count}");
}

[MethodImpl(MethodImplOptions.NoInlining)]
private void ThreadSetupMonitor(Monitor* monitor)
{
var id = _nextMonitorId++;
// Create a new monitor index by simply increasing the counter by 1
var monitorId = new MonitorId(_nextMonitorId++);

var name = OpenTK.Windowing.GraphicsLibraryFramework.GLFW.GetMonitorName(monitor);
var videoMode = OpenTK.Windowing.GraphicsLibraryFramework.GLFW.GetVideoMode(monitor);
// Set our monitor identifier as a pointer
// to be able to get information from glfw events without problems
GLFWHelper.SetMonitorUserPointer(monitor, monitorId);

var modesPointer = OpenTK.Windowing.GraphicsLibraryFramework.GLFW.GetVideoModesRaw(monitor, out var modeCount);
var modes = new VideoMode[modeCount];

for (var i = 0; i < modes.Length; i++)
{
modes[i] = ConvertVideoMode(modesPointer[i]);
}

OpenTK.Windowing.GraphicsLibraryFramework.GLFW.SetMonitorUserPointer(monitor, (void*)id);

var currentVideoMode = ConvertVideoMode(*videoMode);
// Block for obtaining basic monitor information for further registration
var name = OpenTK.Windowing.GraphicsLibraryFramework.GLFW.GetMonitorName(monitor);
var videoMode = GLFWHelper.GetVideoMode(monitor);
var videoModes = GLFWHelper.GetVideoModes(monitor);

var registration = new GlfwMonitorRegistration(
id,
var registration = new MonitorHandle(
(nint) monitor,
monitorId,
name,
currentVideoMode.Width,
currentVideoMode.Height,
currentVideoMode.RefreshRate,
modes,
monitor
videoMode,
videoModes
);

_monitors[id] = registration;
_monitors[monitorId] = registration;
_renderer.AddMonitor(registration);
}

private static VideoMode ConvertVideoMode(in GlfwVideoMode mode)
{
return new()
{
Width = (ushort)mode.Width,
Height = (ushort)mode.Height,
RedBits = (byte)mode.RedBits,
RefreshRate = (ushort)mode.RefreshRate,
GreenBits = (byte)mode.GreenBits,
BlueBits = (byte)mode.BlueBits,
};
}

public sealed class GlfwMonitorRegistration : MonitorHandle
{
public readonly Monitor* Pointer;


public GlfwMonitorRegistration(MonitorId id, string name, Vector2i size, int refreshRate, VideoMode[] videoModes, Monitor* pointer) : base(id, name, size, refreshRate, videoModes)
{
Pointer = pointer;
}

public GlfwMonitorRegistration(MonitorId id, string name, int width, int height, int refreshRate, VideoMode[] videoModes, Monitor* pointer) : base(id, name, width, height, refreshRate, videoModes)
{
Pointer = pointer;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ public WindowCreateResult WindowCreate(IContextInfo? context, WindowCreateSettin
}
else
{
monitor = threadMonitorRegistration.Pointer;
monitor = (Monitor*) threadMonitorRegistration.Pointer;
var modePointer = OpenTK.Windowing.GraphicsLibraryFramework.GLFW.GetVideoMode(monitor);

OpenTK.Windowing.GraphicsLibraryFramework.GLFW.WindowHint(WindowHintInt.RedBits, settings.RedBits ?? modePointer->RedBits);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
using Hypercube.Graphics.Windowing;
using Hypercube.Logging;
using Hypercube.Mathematics.Vectors;
using Monitor = OpenTK.Windowing.GraphicsLibraryFramework.Monitor;

namespace Hypercube.Client.Graphics.Windows.Realisation.GLFW;

Expand Down Expand Up @@ -97,15 +98,12 @@ public nint GetProcAddress(string procName)

public void WindowSetMonitor(WindowHandle window, MonitorHandle monitor, Vector2i vector)
{
if (monitor is not GlfwMonitorRegistration glfwMonitor)
return;

if (window is not GlfwWindowHandle glfwWindow)
return;

OpenTK.Windowing.GraphicsLibraryFramework.GLFW.SetWindowMonitor(
glfwWindow,
glfwMonitor.Pointer,
(Monitor*) monitor.Pointer,
vector.X,
vector.Y,
monitor.Size.X,
Expand Down
24 changes: 9 additions & 15 deletions Hypercube.Graphics/Monitors/MonitorHandle.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,32 +6,26 @@ namespace Hypercube.Graphics.Monitors;
[PublicAPI]
public class MonitorHandle
{
public nint Pointer { get; }
public MonitorId Id { get; }
public string Name { get; }
public Vector2i Size { get; }
public int RefreshRate { get; }
public VideoMode VideoMode { get; }
public VideoMode[] VideoModes { get; }

public MonitorHandle(MonitorId id, string name, Vector2i size, int refreshRate, VideoMode[] videoModes)
public Vector2i Size => new(VideoMode.Width, VideoMode.Height);
public int RefreshRate => VideoMode.RefreshRate;

public MonitorHandle(nint pointer, MonitorId id, string name, VideoMode videoMode, VideoMode[] videoModes)
{
Pointer = pointer;
Id = id;
Name = name;
Size = size;
RefreshRate = refreshRate;
VideoModes = videoModes;
}

public MonitorHandle(MonitorId id, string name, int width, int height, int refreshRate, VideoMode[] videoModes)
{
Id = id;
Name = name;
Size = new Vector2i(width, height);
RefreshRate = refreshRate;
VideoMode = videoMode;
VideoModes = videoModes;
}

public override string ToString()
{
return $"MonitorHandle {Id.Value}, name: {Name}, size: {Size}, rate: {RefreshRate}, mode: ({VideoModes.Length})";
return $"{Name} [{Id.Value}]({Pointer}) mode: ({VideoMode}), count: {VideoModes.Length}";
}
}
56 changes: 40 additions & 16 deletions Hypercube.Graphics/Monitors/MonitorId.cs
Original file line number Diff line number Diff line change
@@ -1,13 +1,37 @@
namespace Hypercube.Graphics.Monitors;
using JetBrains.Annotations;

[Serializable]
public readonly struct MonitorId(int value) : IEquatable<MonitorId>
namespace Hypercube.Graphics.Monitors;

/// <summary>
/// Registered monitor index. Wrapper over <see cref="int"/>,
/// to simplify typing and work with indexing.
/// </summary>
[PublicAPI, Serializable]
public readonly struct MonitorId : IEquatable<MonitorId>
{
public static readonly MonitorId Invalid = default;
public static readonly MonitorId Zero = new(0);
/// <summary>
/// Incorrect monitor index.
/// </summary>
/// <value>
/// MonitorId (-1)
/// </value>
public static readonly MonitorId Invalid = new(-1);

public readonly int Value = value;
/// <summary>
/// Index from which monitors indexing start.
/// </summary>
/// <value>
/// MonitorId (0)
/// </value>
public static readonly MonitorId Zero = new(0);

public readonly int Value;

public MonitorId(int value)
{
Value = value;
}

public bool Equals(MonitorId other)
{
return Value == other.Value;
Expand All @@ -18,6 +42,16 @@ public override bool Equals(object? obj)
return obj is MonitorId id && Equals(id);
}

public override int GetHashCode()
{
return Value;
}

public override string ToString()
{
return $"monitor({Value})";
}

public static bool operator ==(MonitorId a, MonitorId b)
{
return a.Equals(b);
Expand All @@ -37,14 +71,4 @@ public static implicit operator MonitorId(int id)
{
return new MonitorId(id);
}

public override int GetHashCode()
{
return Value;
}

public override string ToString()
{
return $"monitor({Value})";
}
}
18 changes: 16 additions & 2 deletions Hypercube.Graphics/Monitors/VideoMode.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,22 @@
namespace Hypercube.Graphics.Monitors;
using System.Diagnostics;
using JetBrains.Annotations;

namespace Hypercube.Graphics.Monitors;

/// <summary>
/// Monitor mode information obtained through the graphics API.
/// </summary>
[PublicAPI, DebuggerDisplay("{ToString()}")]
public readonly struct VideoMode
{
/// <summary>
/// Width in screen coordinates.
/// </summary>
public ushort Width { get; init; }

/// <summary>
/// Height in screen coordinates.
/// </summary>
public ushort Height { get; init; }

public byte RedBits { get; init; }
Expand All @@ -13,6 +27,6 @@ public readonly struct VideoMode

public override string ToString()
{
return $"mode(size: {Width}, {Height}, RGB bits: {RedBits}, {BlueBits}, {GreenBits}, rate: {RefreshRate})";
return $"size: {Width}, {Height}; RGB bits: {RedBits}, {BlueBits}, {GreenBits}; rate: {RefreshRate}";
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
using JetBrains.Annotations;

namespace Hypercube.Graphics.Shaders.Exceptions;

[PublicAPI]
public class ShaderCompilationException : Exception
{
public ShaderCompilationException(int handle, string infoLog) : base($"Error occurred whilst compiling shader: {handle}.\n\n{infoLog}")
{
}
}
3 changes: 2 additions & 1 deletion Hypercube.Graphics/Windowing/WindowCreateResult.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,10 @@ namespace Hypercube.Graphics.Windowing;
[PublicAPI]
public readonly struct WindowCreateResult
{
public bool Failed => Registration is null;
public readonly WindowHandle? Registration;
public readonly string? Error;

public bool Failed => Registration is null;

public WindowCreateResult(WindowHandle registration)
{
Expand Down
2 changes: 1 addition & 1 deletion Hypercube.Graphics/Windowing/WindowCreateSettings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
namespace Hypercube.Graphics.Windowing;

[PublicAPI]
public sealed class WindowCreateSettings
public class WindowCreateSettings
{
public int Width => Size.X;
public int Height => Size.Y;
Expand Down
3 changes: 2 additions & 1 deletion Hypercube.OpenGL/Shaders/Shader.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using Hypercube.Graphics.Shaders;
using Hypercube.Graphics.Shaders.Exceptions;
using JetBrains.Annotations;
using OpenToolkit.Graphics.OpenGL4;

Expand Down Expand Up @@ -32,6 +33,6 @@ private void Compile()
return;

var infoLog = GL.GetShaderInfoLog(Handle);
throw new Exception($"Error occurred whilst compiling Shader({Handle}).\n\n{infoLog}");
throw new ShaderCompilationException(Handle, infoLog);
}
}
37 changes: 35 additions & 2 deletions Hypercube.OpenGL/Shaders/ShaderProgram.cs
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,39 @@ public ShaderProgram(string vertSource, string fragSource)
_uniformLocations = GetUniformLocations();
}

public ShaderProgram(IEnumerable<KeyValuePair<ShaderType, string>> sources)
{
var shaders = new HashSet<IShader>();
foreach (var (type, shader) in sources)
{
shaders.Add(CreateShader(shader, type));
}

Handle = GL.CreateProgram();

foreach (var shader in shaders)
{
Attach(shader);
}

LinkProgram();

// When the shader program is linked, it no longer needs the individual shaders attached to it; the compiled code is copied into the shader program.
// Detach them, and then delete them.
foreach (var shader in shaders)
{
Detach(shader);
}

_uniformLocations = GetUniformLocations();
}

public ShaderProgram(HashSet<IShader> shaders)
{

_uniformLocations = GetUniformLocations();
}

public void Use()
{
GL.UseProgram(Handle);
Expand Down Expand Up @@ -153,8 +186,8 @@ private void LinkProgram()

throw new Exception($"Error occurred whilst linking Program({Handle})");
}
private IShader CreateShader(string source, ShaderType type)

public static IShader CreateShader(string source, ShaderType type)
{
return new Shader(source, type);
}
Expand Down
Loading

0 comments on commit ab73fd3

Please sign in to comment.