2023-06-22 22:11:32 +02:00
|
|
|
using System;
|
|
|
|
using System.Runtime.CompilerServices;
|
|
|
|
using System.Runtime.InteropServices;
|
|
|
|
using System.Text;
|
|
|
|
using static Quik.OpenGL.GLEnum;
|
|
|
|
|
|
|
|
namespace Quik.OpenGL
|
|
|
|
{
|
|
|
|
public unsafe static partial class GL
|
|
|
|
{
|
|
|
|
private delegate int CreateShaderProc(GLEnum type);
|
|
|
|
private delegate void ShaderSourceProc(int shader, int count, byte** strings, int* length);
|
|
|
|
private delegate void CompileShaderProc(int shader);
|
|
|
|
private delegate void GetShaderProc(int shader, GLEnum pname, int* value);
|
|
|
|
private delegate void GetShaderInfoLogProc(int shader, int maxLength, int* length, byte* infoLog);
|
|
|
|
private delegate void DeleteShaderProc(int id);
|
|
|
|
|
2024-06-09 21:54:33 +02:00
|
|
|
private static CreateShaderProc? _createShader;
|
|
|
|
private static ShaderSourceProc? _shaderSource;
|
|
|
|
private static CompileShaderProc? _compileShader;
|
|
|
|
private static GetShaderProc? _getShader;
|
|
|
|
private static GetShaderInfoLogProc? _getShaderInfoLog;
|
|
|
|
private static DeleteShaderProc? _deleteShader;
|
2023-06-22 22:11:32 +02:00
|
|
|
|
|
|
|
private static void LoadShader()
|
|
|
|
{
|
|
|
|
_createShader = GetProcAddress<CreateShaderProc>("glCreateShader");
|
|
|
|
_shaderSource = GetProcAddress<ShaderSourceProc>("glShaderSource");
|
|
|
|
_compileShader = GetProcAddress<CompileShaderProc>("glCompileShader");
|
|
|
|
_getShader = GetProcAddress<GetShaderProc>("glGetShaderiv");
|
|
|
|
_getShaderInfoLog = GetProcAddress<GetShaderInfoLogProc>("glGetShaderInfoLog");
|
|
|
|
_deleteShader = GetProcAddress<DeleteShaderProc>("glDeleteShader");
|
|
|
|
}
|
|
|
|
|
|
|
|
[MethodImpl(AggressiveInlining)]
|
2024-06-09 21:54:33 +02:00
|
|
|
public static int CreateShader(GLEnum type) => _createShader!(type);
|
2023-06-22 22:11:32 +02:00
|
|
|
|
|
|
|
[MethodImpl(AggressiveInlining)]
|
|
|
|
public static void ShaderSource(int shader, string source)
|
|
|
|
{
|
|
|
|
byte[] sourceUTF8 = Encoding.UTF8.GetBytes(source);
|
|
|
|
int length = sourceUTF8.Length;
|
|
|
|
|
|
|
|
fixed (byte* ptr = &sourceUTF8[0])
|
|
|
|
{
|
2024-06-09 21:54:33 +02:00
|
|
|
_shaderSource!(shader, 1, &ptr, &length);
|
2023-06-22 22:11:32 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
[MethodImpl(AggressiveInlining)]
|
|
|
|
public static void ShaderSource(int shader, string[] sources)
|
|
|
|
{
|
|
|
|
int count = sources.Length;
|
|
|
|
byte*[] pointers = new byte*[count];
|
|
|
|
int[] lengths = new int[count];
|
|
|
|
|
|
|
|
for (int i = 0; i < count; i++)
|
|
|
|
{
|
|
|
|
byte[] decoded = Encoding.UTF8.GetBytes(sources[i]);
|
|
|
|
int length = lengths[i] = decoded.Length;
|
|
|
|
IntPtr memory = Marshal.AllocHGlobal(decoded.Length);
|
|
|
|
|
|
|
|
Marshal.Copy(decoded, 0, memory, length);
|
|
|
|
pointers[i] = (byte*)memory;
|
|
|
|
}
|
|
|
|
|
|
|
|
try
|
|
|
|
{
|
|
|
|
fixed (byte** ptr = &pointers[0])
|
|
|
|
fixed (int * len = &lengths[0])
|
|
|
|
{
|
2024-06-09 21:54:33 +02:00
|
|
|
_shaderSource!(shader, count, ptr, len);
|
2023-06-22 22:11:32 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
finally
|
|
|
|
{
|
|
|
|
for (int i = 0; i < count; i++)
|
|
|
|
{
|
|
|
|
Marshal.FreeHGlobal((IntPtr)pointers[i]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
[MethodImpl(AggressiveInlining)]
|
2024-06-09 21:54:33 +02:00
|
|
|
public static void CompileShader(int shader) => _compileShader!(shader);
|
2023-06-22 22:11:32 +02:00
|
|
|
|
|
|
|
[MethodImpl(AggressiveInlining)]
|
|
|
|
public static void GetShader(int shader, GLEnum pname, out int value)
|
|
|
|
{
|
|
|
|
value = default;
|
|
|
|
fixed (int *ptr = &value)
|
2024-06-09 21:54:33 +02:00
|
|
|
_getShader!(shader, pname, ptr);
|
2023-06-22 22:11:32 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
[MethodImpl(AggressiveInlining)]
|
|
|
|
public static string GetShaderInfoLog(int shader)
|
|
|
|
{
|
|
|
|
GetShader(shader, GL_INFO_LOG_LENGTH, out int length);
|
|
|
|
byte[] infoLog = new byte[length];
|
|
|
|
|
|
|
|
fixed (byte *ptr = infoLog)
|
2024-06-09 21:54:33 +02:00
|
|
|
_getShaderInfoLog!(shader, length, &length, ptr);
|
2023-06-22 22:11:32 +02:00
|
|
|
|
|
|
|
return Encoding.UTF8.GetString(infoLog);
|
|
|
|
}
|
|
|
|
|
|
|
|
[MethodImpl(AggressiveInlining)]
|
2024-06-09 21:54:33 +02:00
|
|
|
public static void DeleteShader(int shader) => _deleteShader!(shader);
|
2023-06-22 22:11:32 +02:00
|
|
|
}
|
|
|
|
}
|