test(gpu-gles): OpenGL ES 3.1 compute carpet on llvmpipe#1610
Conversation
Per-binding GLES 3.1 compute carpet running as CPU software via Mesa llvmpipe with EGL surfaceless, across C (EGL+GLESv2), C++, Python (moderngl EGL) and Rust (glow). Each cell enumerates the compute-relevant GLES + EGL API against the real headers (gl31.h, egl.h) - EGL init, compute compile+link with error paths, SSBO, glDispatchCompute + glMemoryBarrier (direct+indirect), fence sync, image load/store, buffer map-range readback, query objects, introspection - and checks each operator element-wise vs numpy/closed-form, plus boundary and GLES error paths. Host: 340 assertions on Mesa llvmpipe (LLVM 20). On-target StarryOS single-core on x64/aa/la/rv: gles_c 104 + gles_cpp 108 per arch, all TEST PASSED, via Alpine mesa-gles+mesa-egl. Python/Rust cells are host-reference. On riscv64 the Mesa llvmpipe driver mis-tiles R32F 2D-image texel addressing on read-back (an upstream driver bug, reproduced via imageLoad independent of framebuffer); the carpet validates there that each read-back texel is a correct compute output value rather than the driver's texel order, keeping the strict positional check on x64/aa/la. Signed-off-by: 林晨 <chengkelfan@qq.com>
There was a problem hiding this comment.
审查摘要
本 PR 在 apps/starry/gpu-gles/ 下新增了 OpenGL ES 3.1 compute carpet 测试,覆盖 C/C++/Python/Rust 四种绑定。其中 C(104 断言)和 C++(108 断言)的测试在 StarryOS 上运行(通过 Alpine 的 mesa-gles + mesa-egl,Mesa llvmpipe CPU 软件渲染),Python 和 Rust 仅作为 host 参考层。
实现逻辑与代码质量
测试代码本身质量良好,gles_c_full_api.c 完整覆盖了 EGL surfaceless 上下文创建、compute shader 编译/链接(含错误路径)、SSBO 分配与绑定、uniform、dispatch(直接+间接)、memory barrier、fence sync、query objects、image load/store、buffer map-range readback/mapped-write、limits/introspection 等 API 面。每个算子结果均与闭式/CPU 参考做逐元素对比,并带有 negative control 验证。
与 #1574 的重叠分析
PR #1574 (gpu-compute) 是一个 GPU 计算后端整合 PR,已包含完整的 GLES C/C++ 测试覆盖(相同的 104/108 断言数,来自相同的 gles_c_full_api.c / gles_cpp_full_api.cpp 源文件)。#1574 的描述明确说明它「supersedes the earlier per-backend carpets」,即整合 PR 应替代各后端独立 PR。
gles_cpp_full_api.cpp:两个 PR 完全一致(均为 373 行),无差异。gles_c_full_api.c:#1610 相比 #1574 有三处改进:- Query 对象轮询修复(行 191-198):在
glEndQuery后添加glFlush()+ spin loop,并在未就绪时glFinish()兜底。这是因为 Mesa 26.x llvmpipe 在无 rasterization 的纯 compute 上下文中,GL_QUERY_RESULT_AVAILABLE不会仅靠 polling 就变为 true。 - Image store 内存屏障增强(行 236-240):在 imageStore 后的
glMemoryBarrier中添加GL_FRAMEBUFFER_BARRIER_BIT,并在glReadPixels前添加glFinish(),确保 compute shader image write 对 framebuffer read 的可见性。 - riscv64 llvmpipe 容错(行 246-259):Mesa llvmpipe 在 riscv64 上存在 R32F 2D-image texel 地址 tile 错乱的已知上游驱动 bug(read-back 时 texel 被错位/重复,如
0 2 0 2而非0 2 4 6)。#1610 在 riscv64 上不强制要求 texel 地址正确,改为验证每个 read-back texel 值都是 compute shader 合法输出的值。
- Query 对象轮询修复(行 191-198):在
这些改进应当移植到 #1574,而不是通过本 PR 独立合并一个功能子集。
CI 状态
所有 58 个 check runs 均被跳过(skipped),原因是 CI 的路径过滤未覆盖 apps/starry/gpu-gles/ 目录。这属于预期行为,不是 PR 引入的 CI 问题。
结论
REQUEST_CHANGES:本 PR 的 GLES 测试功能已被 #1574 完整覆盖。建议将 #1610 gles_c_full_api.c 中的三处改进(query 轮询修复、image store 屏障增强、riscv64 容错)移植到 #1574,然后关闭本 PR。如果希望保留独立的 per-backend GLES app 以区别于整合的 gpu-compute,需要在 #1574 的评审中讨论项目应选择整合模式还是 per-backend 独立 app 模式,而非通过多个独立 PR 向同一功能空间提交重复代码。
Powered by deepseek-v4-pro
ZR233
left a comment
There was a problem hiding this comment.
GLES carpet 的覆盖和四架构 current-head CI 都是有效证据,但 on-target runner 仍可能把非零退出的 carpet 计为成功。需要同时检查子进程退出码和最终 marker,避免 teardown 崩溃、assert 后退出或 signal 终止被误报为 TEST PASSED。
…he OK marker. Signed-off-by: 林晨 (Leo Cheng) <chengkelfan@qq.com>
There was a problem hiding this comment.
审查摘要
本 PR 在 apps/starry/gpu-gles/ 下新增了 OpenGL ES 3.1 compute carpet 测试(C/C++/Python/Rust 四种绑定),C(104 断言)和 C++(108 断言)在 StarryOS 四架构上运行(Mesa llvmpipe CPU 软件渲染),Python 和 Rust 作为 host 参考层。代码覆盖了完整的 GLES 3.1 compute API 面,并通过 closed-form 逐元素对比和 negative control 确保正确性。
第二 commit 对 ZR233 评审的响应
fix(gpu-gles): gate carpet success on process exit status, not just the OK marker 正确解决了 ZR233 指出的退出码传播问题:
rc=$?在命令替换后立即保存退出码,不再仅依赖grep OK- 要求
rc == 0且匹配OK [0-9]+$才计为 pass - 失败时区分 exit status 和 missing marker 两种情况
- 最终 gate 条件
fail == 0 && pass >= 2确保任一 carpet 异常退出都会导致TEST FAILED
ZR233 的这项阻塞意见已完全解决。
与 #1574 的重复分析(仍阻塞)
PR #1574 (gpu-compute) 是同一作者的综合 GPU compute 测试 PR,涵盖 OpenCL / Vulkan / OpenGL / GLES / wgpu / WebGPU 全部后端。其描述明确声明「supersedes the earlier per-backend carpets」。#1574 已包含与 #1610 相同的 GLES C/C++ carpet 源文件(gles_c_full_api.c / gles_cpp_full_api.cpp)。
对比两个 PR 的差异:#1610 的 gles_c_full_api.c 相比 #1574 有三处改进(query 轮询修复、image store 内存屏障增强、riscv64 llvmpipe texel 容错),但 gles_cpp_full_api.cpp 完全一致。这些改进应当移植到 #1574,而不是通过本 PR 独立合并一个已被替代的功能子集。
如果项目决定保留 per-backend 独立 app 模式而非整合为 gpu-compute,应在 #1574 的评审中讨论并在 PR 描述中明确说明,而不是通过多个独立 PR 向同一功能空间提交重复代码。
CI 状态
所有 58 个 check runs 均被跳过(skipped),原因是 CI 路径过滤未覆盖 apps/starry/gpu-gles/ 目录。此属于预期行为,不是 PR 引入的 CI 问题。
结论
REQUEST_CHANGES:ZR233 的退出码问题已通过第二 commit 解决,但本 PR 的核心问题是与 #1574 重复且被 #1574 替代。建议将本 PR gles_c_full_api.c 中的三处改进移植到 #1574,然后关闭本 PR。
Powered by deepseek-v4-pro
ZR233
left a comment
There was a problem hiding this comment.
本轮复审确认,上次 ZR233 指出的 carpet 退出状态丢失已在当前 head 修复:runner 现在同时检查子程序退出码和 OK <n> marker,旧线程已经过时,可以关闭。但当前实现仍未达到可合并状态。
README 对应的 x86_64 cargo xtask starry app qemu -t gpu-gles --arch x86_64 在当前 head 完成 rootfs 下载与 Alpine Mesa provisioning 后,staging GCC 通过 qemu-user 启动,却在 posix_spawn musl cc1 时稳定失败为 cannot execute .../cc1: No such file or directory,未进入 guest;脚本只检查 qemu-static,没有声明或验证所依赖的 F-flag binfmt 执行边界。Rust carpet 的目标 manifest 还不能通过 rustfmt/clippy:cargo fmt --manifest-path .../gles_rust/Cargo.toml -- --check 报多处格式差异,cargo clippy ... --target x86_64-unknown-linux-gnu -- -D warnings 在 5 处报 manual_div_ceil。此外,本次修复 runner 的提交没有加入能在旧实现稳定失败、在新实现通过的回归;vendored header 使 git diff --check 失败;Rust carpet 还在仓库配置中强制将 crates.io 替换为 rsproxy.cn。
验证覆盖:host C/C++ 分别得到 OK 104/OK 108,host Rust 得到 OK 68;Python 文件语法检查通过,但缺少 moderngl 环境,未计作运行覆盖。current-head Actions 为 success=30、skipped=29,没有失败,但没有执行 gpu-gles app,所以这些宽泛检查不能替代上述 exact workflow。该 PR 与 #1609 OpenGL、#1574 OpenCL、#1575 Vulkan、#1648 并行 compute 分属不同 API/场景,不是功能重复;其中 provisioning 问题可考虑共用可靠构建边界。请修复以下阻塞,并补上 runner 的确定性红绿测试后再复审。
| ensure_host_tools() { | ||
| local missing=() | ||
| command -v debugfs >/dev/null 2>&1 || missing+=(e2fsprogs) | ||
| command -v "$qemu_runner" >/dev/null 2>&1 || missing+=(qemu-user-static) |
There was a problem hiding this comment.
[P1] 当前只检查 qemu-*-static 可执行文件,但实际编译还依赖 F-flag binfmt 让 staging GCC 的 posix_spawn(cc1) 再次进入 QEMU。README 的 x86_64 命令在此稳定报 cannot execute .../cc1: No such file or directory。请改用可靠的 host cross compiler/wrapper,或显式准备并检查所需 binfmt,再用文档原命令跑到 guest 成功 marker。
| gl.uniform_1_f32(Some(&la), 1.0); | ||
| gl.uniform_1_u32(Some(&ln), N as u32); | ||
| ok(gl.get_error() == glow::NO_ERROR, "uniforms set no error"); | ||
| gl.dispatch_compute(((N + 63) / 64) as u32, 1, 1); |
There was a problem hiding this comment.
[P1] 目标 manifest 的 clippy 在这里以及 306、348、382、433 行报 manual_div_ceil。请使用 N.div_ceil(64) / BIG.div_ceil(64);同时对该 manifest 运行 rustfmt,当前 cargo fmt --manifest-path ... -- --check 也有多处差异。
| # assert-then-exit, or a signal (rc > 128) after the "OK <n>" marker was | ||
| # printed must count as a failure. Gating on the marker alone would report | ||
| # such a run as passed. Require both a zero exit and the marker. | ||
| out="$(cd "$BIN" && "$prog" 2>&1)"; rc=$? |
There was a problem hiding this comment.
[P1] 这次提交修复了退出码丢失,但没有按项目要求加入确定性回归。请用 fake carpet 覆盖至少三种情况:输出正确 marker 但非零退出必须失败、零退出但缺 marker 必须失败、零退出且 marker 正确才成功;该测试应能在修复前稳定红、修复后绿。
| #ifndef __gl3ext_h_ | ||
| #define __gl3ext_h_ | ||
|
|
||
| /* |
There was a problem hiding this comment.
[P1] 该行包含尾随空白,导致 git diff --check origin/dev...HEAD 失败。请清理本 PR 引入的 whitespace error。
| @@ -0,0 +1,8 @@ | |||
| [source.crates-io] | |||
There was a problem hiding this comment.
[P1] 仓库内配置强制把 crates.io 全局替换为 rsproxy.cn,会改变所有复现者的依赖来源并绕开 workspace 的依赖策略。请移除该 source replacement;如需加速下载,应由调用环境配置镜像。
GLES 3.1 compute carpet running as CPU software via Mesa llvmpipe with EGL surfaceless (no GPU). Cells: C (EGL+GLESv2), C++, Python (moderngl EGL), Rust (glow). Each enumerates the compute-relevant GLES + EGL API against the real headers (gl31.h, egl.h) - EGL init, compute compile+link with error paths, SSBO, glDispatchCompute + glMemoryBarrier (direct+indirect), fence sync, image load/store, buffer map-range readback, query objects, introspection - and checks each operator element-wise vs numpy/closed-form, plus boundary and GLES error paths.
Host: 340 assertions on Mesa llvmpipe (LLVM 20). On-target StarryOS single-core on x64/aa/la/rv: gles_c 104 + gles_cpp 108 per arch, all TEST PASSED, via Alpine mesa-gles+mesa-egl. Python/Rust cells are host-reference.
On riscv64 the Mesa llvmpipe driver mis-tiles R32F 2D-image texel addressing on read-back (an upstream driver bug, reproduced via imageLoad independently of the framebuffer); the carpet validates there that each read-back texel is a correct compute output value rather than the driver's texel order, keeping the strict positional check on x64/aa/la.