You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
63 lines
2.6 KiB
63 lines
2.6 KiB
2 years ago
|
using System;
|
||
|
using System.Runtime.CompilerServices;
|
||
|
using Silk.NET.OpenGL;
|
||
|
|
||
|
namespace gaemstone.Client;
|
||
|
|
||
|
public static class GLExtensions
|
||
|
{
|
||
|
public static uint CreateAndCompileShader(this GL GL, ShaderType type, string label, string source)
|
||
|
{
|
||
|
var shader = GL.CreateShader(type);
|
||
|
GL.ObjectLabel(ObjectIdentifier.Shader, shader, (uint)label.Length, label);
|
||
|
GL.ShaderSource(shader, source);
|
||
|
GL.CompileShader(shader);
|
||
|
GL.GetShader(shader, ShaderParameterName.CompileStatus, out var result);
|
||
|
if (result != (int)GLEnum.True) throw new Exception(
|
||
|
$"Failed compiling shader \"{label}\" ({shader}):\n{GL.GetShaderInfoLog(shader)}");
|
||
|
return shader;
|
||
|
}
|
||
|
|
||
|
public static uint CreateAndLinkProgram(this GL GL, string label, params uint[] shaders)
|
||
|
{
|
||
|
var program = GL.CreateProgram();
|
||
|
GL.ObjectLabel(ObjectIdentifier.Program, program, (uint)label.Length, label);
|
||
|
foreach (var shader in shaders) GL.AttachShader(program, shader);
|
||
|
GL.LinkProgram(program);
|
||
|
foreach (var shader in shaders) GL.DetachShader(program, shader);
|
||
|
foreach (var shader in shaders) GL.DeleteShader(shader);
|
||
|
GL.GetProgram(program, ProgramPropertyARB.LinkStatus, out var result);
|
||
|
if (result != (int)GLEnum.True) throw new Exception(
|
||
|
$"Failed linking Program \"{label}\" ({program}):\n{GL.GetProgramInfoLog(program)}");
|
||
|
return program;
|
||
|
}
|
||
|
|
||
|
// These overloads are available because without them, the implicit casting
|
||
|
// (say from T[] to ReadOnlySpan<T>) causes the generic type resolving to break.
|
||
|
public static uint CreateBufferFromData<T>(this GL GL, T[] data,
|
||
|
BufferTargetARB target = BufferTargetARB.ArrayBuffer,
|
||
|
BufferUsageARB usage = BufferUsageARB.StaticDraw)
|
||
|
where T : unmanaged
|
||
|
=> GL.CreateBufferFromData((ReadOnlySpan<T>)data, target, usage);
|
||
|
public static uint CreateBufferFromData<T>(this GL GL, ArraySegment<T> data,
|
||
|
BufferTargetARB target = BufferTargetARB.ArrayBuffer,
|
||
|
BufferUsageARB usage = BufferUsageARB.StaticDraw)
|
||
|
where T : unmanaged
|
||
|
=> GL.CreateBufferFromData((ReadOnlySpan<T>)data, target, usage);
|
||
|
public static uint CreateBufferFromData<T>(this GL GL, Span<T> data,
|
||
|
BufferTargetARB target = BufferTargetARB.ArrayBuffer,
|
||
|
BufferUsageARB usage = BufferUsageARB.StaticDraw)
|
||
|
where T : unmanaged
|
||
|
=> GL.CreateBufferFromData((ReadOnlySpan<T>)data, target, usage);
|
||
|
public static uint CreateBufferFromData<T>(this GL GL, ReadOnlySpan<T> data,
|
||
|
BufferTargetARB target = BufferTargetARB.ArrayBuffer,
|
||
|
BufferUsageARB usage = BufferUsageARB.StaticDraw)
|
||
|
where T : unmanaged
|
||
|
{
|
||
|
var buffer = GL.GenBuffer();
|
||
|
GL.BindBuffer(target, buffer);
|
||
|
GL.BufferData(target, (nuint)(data.Length * Unsafe.SizeOf<T>()), data, usage);
|
||
|
return buffer;
|
||
|
}
|
||
|
}
|