# 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` 流式解析。 - 解析节点: - ``:函数名、返回类型、参数。 - ``:常量。 - ``:按 `version` 收录命令/常量。 - ``:可选扩展(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`,后续可另行提供 `string` 重载。 - 参数长度:解析并保留 registry ``。包装层以该表达式判断数组方向、固定长度和关联的 `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* glFoo;` - `OpenGLFunction` 包装:薄封装直接转发;句柄参数用 `GlHandle`,内部传 `handle.Value`;`bool` 参数按底层 `GLboolean` 需要转换为 `byte/uint`。 - 指针包装:带长度的 `const T*` 生成 `ReadOnlySpan`,输出 `T*` 生成 `Span`,`len="1"` 的输出生成 `out T`。可由单个 Span 唯一决定的 `count`/`n`/`bufSize` 从 `Span.Length` 推导;共享同一长度的输入 Span 会检查长度一致。简单常量、乘法和除法长度表达式会生成下限检查。 - registry 中省略 `len` 的零结尾 const 字符指针仍生成 `ReadOnlySpan`;省略 `len` 的 `glGet*` 数值单指针按未知长度输出生成 `Span`。`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.id.SignedValue` 取得;数组版本接受 `ReadOnlySpan` 并自动计算 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),保持可配置启用列表。 ## 本地评审输出 可把首个命令行参数作为输出目录: ```powershell dotnet run --project test\StgSharp.GenerateGL\GenerateGL.csproj -- test\StgSharp.GenerateGL\Generated ```