perf(glsm): fix per-draw client-array re-uploads collapsing GUI/F3 frame rate - #116
Merged
Conversation
…ne consumes them IrisGLSMBridge registers its GLSM hook listeners unconditionally at startup, so VANILLA_BLEND_CHANGE/PROGRAM_CHANGE always had listeners and the per-call snapshot+compare work introduced in 2f54db7 ran on every tryBlendFunc/glUseProgram even with no shader pack loaded, while every listener is a no-op without a DeferredWorldRenderingPipeline. GUI-heavy frames (notably the F3 debug overlay, ~100 drawString + ~55 drawRect per frame) multiply this fixed per-call cost into a sharp FPS drop. Add a cheap GLSMHooks.consumersActive gate maintained by PipelineManager (true only while a DeferredWorldRenderingPipeline is active) and consult it before the snapshot/compare/post work. With a deferred pipeline the gate is always true and behavior is unchanged. Escape hatch: -Dactinium.glsmHooksAlwaysActive=true.
… renders MissingModelCompat.isMissingModel walked a four-deep getter chain (Minecraft -> BlockRendererDispatcher -> BlockModelShapes -> ModelManager) for every block render during chunk mesh building. The reference only changes on resource reload, so cache it (volatile, worker-thread safe) and clear the cache from a reload listener registered in Actinium.onInit. The one-argument isMissingModel signature is kept so the compat-bridge renderer bytecode contract is untouched.
… reads Root cause of the F3/GUI FPS collapse (140+ -> 15 fps with the debug overlay open, sluggish inventory/video-settings screens): 2f54db7 widened captured client pointers to the whole underlying allocation to stay correct when HBM-CE mutates the BufferBuilder limit after setting a pointer. uploadClientArraysToVBO then re-uploaded that entire allocation (>4MB observed, ~1.1ms per upload on PCIe) on EVERY draw issued while a mod leaves client-state attribs enabled. Text/rect-heavy GUI frames issue hundreds of draws, multiplying this into ~57ms/frame. glDrawArrays (and the QUADS path through QuadConverter, whose shared EBO references exactly [first, first+count)) knows the drawn vertex range, so per-attrib uploads are now clamped to the bytes that range can read via VertexAttribState.computeUploadLength; indexed draws with an unknown max index keep the full-allocation upload. Escape hatch: -Dactinium.glsmFullClientArrayUpload=true. Also adds clientArray.stackSample caller attribution to the periodic GLSM perf report to identify which mod drives large uploads.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
问题
0.0.5 → 0.0.7 之间的性能回归:打开 F3 调试界面帧率从 140+ 暴跌至 15(帧时间 +60ms),背包、视频设置等 GUI 界面也明显卡顿。无光影同样复现。
根因
perfDebug 日志定位(
gl.clientArrayUpload[count=708-750/s, avgUs≈1150µs],F3 下约 50 次/帧 ≈ 57ms/帧):2f54db7为修 HBM-CE 兼容,将VertexAttribState捕获的 client 指针扩到整个底层分配(HBM 复用 BufferBuilder 分配、set pointer 后改 limit)——正确性修复,语义必须保留;GLStateManager.uploadClientArraysToVBO()在每次 draw(只要存在启用的 client-side 顶点属性,HBM-CE 的 client-state 泄漏使其常态启用)都把捕获的整个分配(实测 4.2MB,bufferDataorphan +bufferSubData,约 1.1ms/次,与 PCIe 上传耗时吻合)重新上传;改动(3 个提交)
bcd0c67perf(glsm):client-array 上传按 draw 顶点区间裁剪(主修复)。glDrawArrays(含 QUADS 经 QuadConverter 转换的路径,其共享 EBO 恰好引用[first, first+count))的读取区间已知,逐属性将上传裁剪到该区间实际读取的字节(4.2MB → 几十~几百字节);最大索引未知的裸glDrawElements系列保守保持全量上传。新增VertexAttribState.computeUploadLength纯函数 + 10 个单元测试;GLSM perf 周期日志新增clientArray.stackSample调用方归因。逃逸通道:-Dactinium.glsmFullClientArrayUpload=true。20e6e73perf(glsm):无 deferred pipeline 时跳过 blend/program 快照与事件 post。IrisGLSMBridge启动时无条件注册监听器导致hasListeners()恒真,2f54db7引入的每次tryBlendFunc/glUseProgram快照+比较在无光影时全部空转。新增GLSMHooks.consumersActive门禁,由PipelineManager在 pipeline 生命周期维护(仅DeferredWorldRenderingPipeline活跃时为 true);有光影时行为逐字节不变。逃逸通道:-Dactinium.glsmHooksAlwaysActive=true。f499c63perf(terrain):缓存 vanilla missing-model 引用,消除 chunk 构建期每方块的 4 级 getter 链(MissingModelCompat,资源重载时经监听器失效;桥 renderer 的第三方 Mixin 绑定契约未触碰)。验证
./gradlew build --no-daemon全绿:根项目 140 个测试套件 0 失败,含CeleritasCompatBridgeJarTest7/7(桥契约)、新增VertexAttribUploadLengthTest10/10、GLSMHooksConsumersGateTest。备注
glDrawElements路径仍是全量上传;若后续日志显示该路径也热,可再加索引扫描求上界的优化。a3ad50d的 BiomeColorNoise 存在最多 60 倍的平面噪声冗余计算(仅 worker 线程构建期、与本次症状无关),将另行评估处理,不在本 PR 范围。