make some changes to opengl api gen, discussing on rewrite of all opengl binding, making it neat and structral
This commit is contained in:
@@ -0,0 +1,219 @@
|
||||
//-----------------------------------------------------------------------
|
||||
// -----------------------------------------------------------------------
|
||||
// file="UniformOverloadEmitter"
|
||||
// Project: StgSharp
|
||||
// Copyright (c) Nitload.
|
||||
// SPDX-License-Identifier: MIT
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
#pragma warning disable CA1305
|
||||
|
||||
namespace GenerateGL.CodeGen
|
||||
{
|
||||
internal static partial class UniformOverloadEmitter
|
||||
{
|
||||
|
||||
public static bool IsValueCommand(
|
||||
GlCommand command
|
||||
)
|
||||
{
|
||||
return ValueCommandRegex().IsMatch(command.Name);
|
||||
}
|
||||
|
||||
public static bool IsSetterCommand(
|
||||
GlCommand command
|
||||
)
|
||||
{
|
||||
return IsValueCommand(command) || MatrixCommandRegex().IsMatch(command.Name);
|
||||
}
|
||||
|
||||
public static void Write(
|
||||
string outputRoot,
|
||||
string version,
|
||||
IReadOnlyList<GlCommand> commands
|
||||
)
|
||||
{
|
||||
List<GlCommand> valueCommands = commands.Where(IsValueCommand)
|
||||
.OrderBy(c => c.Name, StringComparer.Ordinal)
|
||||
.ToList();
|
||||
List<GlCommand> matrixConvenienceCommands = commands
|
||||
.Where(c => Matrix4FloatCommandRegex().IsMatch(c.Name))
|
||||
.OrderBy(c => c.Name, StringComparer.Ordinal)
|
||||
.ToList();
|
||||
|
||||
if (valueCommands.Count == 0 && matrixConvenienceCommands.Count == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
StringBuilder sb = new();
|
||||
sb.AppendLine("// <auto-generated>");
|
||||
sb.AppendLine($"// Generated by StgSharp.GenerateGL on {DateTime.UtcNow.ToString("u", CultureInfo.InvariantCulture)}");
|
||||
sb.AppendLine($"// Uniform overloads introduced in OpenGL {version}");
|
||||
sb.AppendLine("// </auto-generated>");
|
||||
sb.AppendLine("using System;");
|
||||
sb.AppendLine("using System.Runtime.CompilerServices;");
|
||||
sb.AppendLine("using StgSharp.Mathematics.Graphics;");
|
||||
sb.AppendLine();
|
||||
sb.AppendLine("namespace StgSharp.Graphics.OpenGL");
|
||||
sb.AppendLine("{");
|
||||
sb.AppendLine(" public unsafe partial class OpenGLFunction");
|
||||
sb.AppendLine(" {");
|
||||
|
||||
foreach (GlCommand command in valueCommands) {
|
||||
EmitValueOverload(sb, command);
|
||||
}
|
||||
foreach (GlCommand command in valueCommands.Where(IsFloatVectorCommand)) {
|
||||
EmitVectorConvenienceOverload(sb, command);
|
||||
}
|
||||
foreach (GlCommand command in matrixConvenienceCommands) {
|
||||
EmitMatrixConvenienceOverload(sb, command);
|
||||
}
|
||||
|
||||
sb.AppendLine(" }");
|
||||
sb.AppendLine("}");
|
||||
|
||||
string fileName = Path.Combine(
|
||||
outputRoot,
|
||||
$"OpenGLFunction.Uniform.v{version.Replace('.', '_')}.g.cs");
|
||||
File.WriteAllText(fileName, sb.ToString(), Encoding.UTF8);
|
||||
}
|
||||
|
||||
private static void EmitValueOverload(
|
||||
StringBuilder sb,
|
||||
GlCommand command
|
||||
)
|
||||
{
|
||||
Match match = ValueCommandRegex().Match(command.Name);
|
||||
bool hasProgram = match.Groups[1].Success;
|
||||
int dimension = int.Parse(match.Groups[2].Value, CultureInfo.InvariantCulture);
|
||||
string scalarType = MapScalarType(match.Groups[3].Value);
|
||||
bool isVector = match.Groups[4].Success;
|
||||
string uniformType = $"Uniform<{string.Join(", ", Enumerable.Repeat(scalarType, dimension))}>";
|
||||
|
||||
sb.AppendLine(" [MethodImpl(MethodImplOptions.AggressiveInlining)]");
|
||||
if (isVector)
|
||||
{
|
||||
string programParameter = hasProgram ? "GlHandle program, " : string.Empty;
|
||||
sb.AppendLine($" public void SetUniformValue({programParameter}{uniformType} uniform, ReadOnlySpan<{scalarType}> values)");
|
||||
sb.AppendLine(" {");
|
||||
sb.AppendLine(" ArgumentNullException.ThrowIfNull(uniform);");
|
||||
if (dimension > 1)
|
||||
{
|
||||
sb.AppendLine($" if ((values.Length % {dimension}) != 0) {{");
|
||||
sb.AppendLine($" throw new ArgumentException(\"Uniform data length must be divisible by {dimension}.\", nameof(values));");
|
||||
sb.AppendLine(" }");
|
||||
}
|
||||
sb.AppendLine($" fixed ({scalarType}* valuesPtr = values) {{");
|
||||
string count = dimension == 1 ? "values.Length" : $"values.Length / {dimension}";
|
||||
sb.AppendLine($" Context.{command.Name}({BuildPrefixArguments(hasProgram)}{count}, valuesPtr);");
|
||||
sb.AppendLine(" }");
|
||||
sb.AppendLine(" }");
|
||||
} else
|
||||
{
|
||||
string programParameter = hasProgram ? "GlHandle program, " : string.Empty;
|
||||
string values = string.Join(", ", Enumerable.Range(0, dimension)
|
||||
.Select(i => $"{scalarType} v{i}"));
|
||||
string valueArguments = string.Join(", ", Enumerable.Range(0, dimension)
|
||||
.Select(i => $"v{i}"));
|
||||
sb.AppendLine($" public void SetUniformValue({programParameter}{uniformType} uniform, {values})");
|
||||
sb.AppendLine(" {");
|
||||
sb.AppendLine(" ArgumentNullException.ThrowIfNull(uniform);");
|
||||
sb.AppendLine($" Context.{command.Name}({BuildPrefixArguments(hasProgram)}{valueArguments});");
|
||||
sb.AppendLine(" }");
|
||||
}
|
||||
sb.AppendLine();
|
||||
}
|
||||
|
||||
private static void EmitVectorConvenienceOverload(
|
||||
StringBuilder sb,
|
||||
GlCommand command
|
||||
)
|
||||
{
|
||||
Match match = ValueCommandRegex().Match(command.Name);
|
||||
bool hasProgram = match.Groups[1].Success;
|
||||
int dimension = int.Parse(match.Groups[2].Value, CultureInfo.InvariantCulture);
|
||||
if (dimension < 2) {
|
||||
return;
|
||||
}
|
||||
|
||||
string vectorType = $"Vec{dimension}";
|
||||
string programParameter = hasProgram ? "GlHandle program, " : string.Empty;
|
||||
sb.AppendLine(" [MethodImpl(MethodImplOptions.AggressiveInlining)]");
|
||||
sb.AppendLine($" public void SetUniformValue({programParameter}Uniform<{vectorType}> uniform, {vectorType} value)");
|
||||
sb.AppendLine(" {");
|
||||
sb.AppendLine(" ArgumentNullException.ThrowIfNull(uniform);");
|
||||
sb.AppendLine($" Context.{command.Name}({BuildPrefixArguments(hasProgram)}1, (float*)&value);");
|
||||
sb.AppendLine(" }");
|
||||
sb.AppendLine();
|
||||
}
|
||||
|
||||
private static void EmitMatrixConvenienceOverload(
|
||||
StringBuilder sb,
|
||||
GlCommand command
|
||||
)
|
||||
{
|
||||
bool hasProgram = command.Name.StartsWith("glProgram", StringComparison.Ordinal);
|
||||
string programParameter = hasProgram ? "GlHandle program, " : string.Empty;
|
||||
sb.AppendLine(" [MethodImpl(MethodImplOptions.AggressiveInlining)]");
|
||||
sb.AppendLine($" public void SetUniformValue({programParameter}Uniform<GraphicsMatrix> uniform, GraphicsMatrix value, bool transpose = false)");
|
||||
sb.AppendLine(" {");
|
||||
sb.AppendLine(" ArgumentNullException.ThrowIfNull(uniform);");
|
||||
sb.AppendLine($" Context.{command.Name}({BuildPrefixArguments(hasProgram)}1, transpose ? (byte)1 : (byte)0, (float*)&value);");
|
||||
sb.AppendLine(" }");
|
||||
sb.AppendLine();
|
||||
}
|
||||
|
||||
private static string BuildPrefixArguments(
|
||||
bool hasProgram
|
||||
)
|
||||
{
|
||||
return hasProgram
|
||||
? "program.Value, uniform.id.SignedValue, "
|
||||
: "uniform.id.SignedValue, ";
|
||||
}
|
||||
|
||||
private static bool IsFloatVectorCommand(
|
||||
GlCommand command
|
||||
)
|
||||
{
|
||||
Match match = ValueCommandRegex().Match(command.Name);
|
||||
return match.Success && match.Groups[3].Value == "f" && match.Groups[4].Success;
|
||||
}
|
||||
|
||||
private static string MapScalarType(
|
||||
string suffix
|
||||
)
|
||||
{
|
||||
return suffix switch
|
||||
{
|
||||
"f" => "float",
|
||||
"d" => "double",
|
||||
"i" => "int",
|
||||
"ui" => "uint",
|
||||
_ => throw new InvalidOperationException($"Unsupported uniform suffix: {suffix}")
|
||||
};
|
||||
}
|
||||
|
||||
[GeneratedRegex("^gl(Program)?Uniform([1-4])(ui|[fdi])(v)?$",
|
||||
RegexOptions.CultureInvariant)]
|
||||
private static partial Regex ValueCommandRegex();
|
||||
|
||||
[GeneratedRegex("^gl(?:Program)?UniformMatrix4fv$", RegexOptions.CultureInvariant)]
|
||||
private static partial Regex Matrix4FloatCommandRegex();
|
||||
|
||||
[GeneratedRegex("^gl(?:Program)?UniformMatrix[234](?:x[234])?[fd]v$",
|
||||
RegexOptions.CultureInvariant)]
|
||||
private static partial Regex MatrixCommandRegex();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#pragma warning restore CA1305
|
||||
Reference in New Issue
Block a user