Files
stgsharp/test/StgSharp.GenerateGL/Docs/SourceGenerator.md
T

7.1 KiB
Raw Blame History

StgSharp.GenerateGL 源生成器技术文档

目标与范围

  • 输入:Khronos OpenGL Registry gl.xml(Core Profile 为主,版本 3.3→4.6,可选扩展)。
  • 输出:合并的 partial OpenglContext(delegate* 字段)、分版本 OpenGLFunction 薄包装方法,以及按版本生成的 Uniform 语义重载。生成结果最终对应 src\StgSharp.Graphics\OpenGL\Generated\,评审时可以通过命令行参数输出到独立目录。
  • 风格:保持现有函数指针字段 + 薄封装方法模式;兼容现有命名和类型定义(如 GlHandle)。

阶段 1:输入解析(XML 读取与过滤)

  • 将 gl.xml 作为 AdditionalFile 或 EmbeddedResource,使用 XmlReader 流式解析。
  • 解析节点:
    • <commands><command>:函数名、返回类型、参数。
    • <enums>:常量。
    • <feature profile="core">:按 version 收录命令/常量。
    • <extensions>:可选扩展(ARB/KHR/EXT/NV)。
  • 过滤策略:仅 Core Profile 且版本 ≥ 3.3(3.3→4.6 递进);扩展按启用列表追加。

阶段 2:类型映射与句柄规则

  • 整数:GLenum/GLbitfield→uint;GLint/GLsizei/GLfixed→int;GLuint→uint;GLboolean→byte(包装层可 bool→byte)。
  • 浮点:GLfloat→float;GLdouble→double。
  • 指针与尺寸:void*/const void*→void*;GLintptr、GLsizeiptr→nint;GLsync→现有 glSync 包装。GLint64/GLuint64 分别映射为 long/ulong。回调类型 GLDEBUGPROC 暂以指针大小的 IntPtr 表示。
  • 未知 C 类型直接终止生成,不再静默回退为 IntPtr。这可以防止 typedef 漏映射后生成 ABI 不兼容的函数指针。
  • 字符串:函数表中的 GLchar* 保持 byte* ABI;包装层的 const 单指针使用 UTF-8 ReadOnlySpan<byte>,后续可另行提供 string 重载。
  • 参数长度:解析并保留 registry <param len="...">。包装层以该表达式判断数组方向、固定长度和关联的 count/bufSize 参数;底层函数表不使用这些托管规则。
  • 调用约定:OpenGL APIENTRY 通常 stdcall(Windows);保持与现有 glContext 字段一致(delegate* unmanaged[Stdcall] 或 unmanaged[Cdecl],需与 loader 对齐)。
  • 句柄识别:包含 program/shader/buffer/texture/framebuffer/renderbuffer/vertexarray/query/sampler/transformfeedback 等对象名的 GLuint 参数 → 包装层使用 GlHandle,内部传 handle.Value。glCreateProgram、glCreateShader 等明确返回 object name 的命令返回 GlHandle。
  • GLenum 不再仅凭参数名 type 推断为 ShaderType;低层包装保持 uint,避免把像素类型、索引类型等无关参数错误分类。
  • glGet* 输出:保留指针签名,或另行生成 unsafe Span/stackalloc 适配器;核心先生成指针版。

阶段 3:版本分组与文件组织

  • 目标目录:src\StgSharp.Graphics\OpenGL\Generated\
  • Context 生成一个合并文件:
    • OpenglContext.g.cs:所有目标 Core 版本需要的 delegate* 字段。
  • Raw 包装按版本生成独立 partial:
    • OpenGLFunction.Raw.v3_3.g.cs, …:包装方法 public void Foo(...) => Context.glFoo(...);
  • Uniform 重载按首次引入版本生成:
    • OpenGLFunction.Uniform.v3_3.g.cs、v4_0、v4_1。
  • 不再同时生成分版本 Context 与合并 Context,避免同一字段被 partial struct 重复定义。
  • 常量/枚举:glConst.generated.cs(或分版本补丁),避免与现有重复,先查已有定义再生成。
  • 命名空间:StgSharp.Graphics.OpenGL;类声明:partial struct/partial class glContext(按现有定义),partial class OpenGLFunction。

阶段 4:生成规则(函数表与包装)

  • OpenglContext 字段:internal unsafe delegate*<converted_sig> glFoo;
  • OpenGLFunction 包装:薄封装直接转发;句柄参数用 GlHandle,内部传 handle.Value;bool 参数按底层 GLboolean 需要转换为 byte/uint。
  • 指针包装:带长度的 const T* 生成 ReadOnlySpan<T>,输出 T* 生成 Span<T>,len="1" 的输出生成 out T。可由单个 Span 唯一决定的 count/n/bufSize 从 Span.Length 推导;共享同一长度的输入 Span 会检查长度一致。简单常量、乘法和除法长度表达式会生成下限检查。
  • registry 中省略 len 的零结尾 const 字符指针仍生成 ReadOnlySpan<byte>;省略 len 的 glGet* 数值单指针按未知长度输出生成 Span<T>。void*、二级指针、驱动拥有的返回指针以及表示 Buffer 偏移的指针继续保留原始形式。
  • 可重载的 C 类型尾缀会折叠为同一 C# 方法名,例如 TexParameterf/i/fv/iv → TexParameter(...),BlendEquation/BlendEquationi → BlendEquation(...)。生成器以最终 C# 参数签名检测冲突;无法区分时保留最少的维度或语义尾缀。
  • glUniform1/2/3/4[f|i|ui|d][v] 和 glProgramUniform* 不再作为一组公开的 C 风格方法生成,而是生成 SetUniformValue(...) 重载。location 从 Uniform<T...>.id.SignedValue 取得;数组版本接受 ReadOnlySpan<T> 并自动计算 count。
  • float vector 额外生成 Vec2、Vec3、Vec4 重载,4×4 float matrix 生成 GraphicsMatrix 重载。所有 uniform setter(包括 matrix)都不进入 Raw wrapper;项目暂时没有对应托管类型的其他矩阵形状只保留底层 OpenglContext 函数指针,待类型齐备后再生成公开重载。
  • glVertexAttribN*v 若存在对应的标量命令 glVertexAttribN*,不再生成重复的 Span wrapper;公开 API 使用 VertexAttrib(index, x, y, z, w) 形式的固定分量重载。只有不存在标量等价命令的特殊整数/归一化形式才暂时保留独立入口。
  • FramebufferTexture1D/2D/3D 表示不同 OpenGL API,不参与维度重载归并。
  • 去重:若同名字段/方法已存在,跳过或比对签名避免重复生成。

阶段 5:增量源生成器结构

  • 步骤:
    1. 收集 AdditionalFiles(gl.xml)。
    2. 解析→建模(CommandModel, EnumModel, FeatureModel)。
    3. 按版本/profile 过滤。
    4. Emit:分文件输出(SourceProductionContext.AddSource)。
  • 配置建议:LangVersion=preview(支持 delegate* unmanaged[Stdcall]);仅引用必要的 XML 解析库。

阶段 6:兼容性与发布注意

  • 不改动现有手写文件,仅追加 partial。
  • 常量值需与现有 glConst 保持一致,生成前检查重复。
  • 大 gl.xml 使用流式解析避免内存压力。
  • Loader(wglGetProcAddress/glXGetProcAddress/eglGetProcAddress)不在本轮生成,字段调用约定需与 loader 对齐。

下一步实施建议

  1. 将 gl.xml 添加为 AdditionalFile。
  2. 搭建增量生成器骨架:Parse → Filter → Emit。
  3. 先生成 3.3 子集验证编译,再扩展到 4.6。
  4. 按需追加扩展(ARB/KHR),保持可配置启用列表。

本地评审输出

可把首个命令行参数作为输出目录:

dotnet run --project test\StgSharp.GenerateGL\GenerateGL.csproj -- test\StgSharp.GenerateGL\Generated