Skip to content

feat(rendering): add occlusion culling backends and bindless texturing - #95

Open
ZhuRuoLing wants to merge 30 commits into
Anvil-Dev:dev/26.1from
ZhuRuoLing:feat/occusion_culling
Open

feat(rendering): add occlusion culling backends and bindless texturing#95
ZhuRuoLing wants to merge 30 commits into
Anvil-Dev:dev/26.1from
ZhuRuoLing:feat/occusion_culling

Conversation

@ZhuRuoLing

@ZhuRuoLing ZhuRuoLing commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

Summary

This PR extends the Minecraft 26.1 rendering module with an occlusion-culling framework and GPU-side rendering infrastructure. It adds an OpenGL samples-query backend, Hi-Z depth-processing foundations, feature-submit filtering, and compute/texture capability plumbing.

Changes

  • Added OcclusionCuller, OcclusionKey, OcclusionMethod, culling statistics, and wrapped submit-node storage.
  • Added automatic backend selection with Hi-Z, GPU Query, and no-op implementations.
  • Added pooled OpenGL samples queries, AABB query rendering, frustum pre-pass support, and one-frame-latency result reads.
  • Added visibility filtering for vanilla and NeoForge block, model, item, flame, leash, name-tag, particle, shadow, text, and custom feature renderers.
  • Added padded R32F depth conversion and FidelityFX SPD mip-chain foundations.
  • Refactored compute pipelines to use named resource layouts and ordered binding allocation.
  • Added explicit texture, image, buffer, atomic-counter, and bindless image-array bindings.
  • Added GPU capability reporting, extended texture formats, OpenGL texture allocation, and ARB bindless texture handles/residency scopes.
  • Added reusable GPU resource pools, transform/size UBOs, rendering debug options, and development JVM arguments.
  • Updated ApiStatus.Internal placement and sync-module imports.
  • Added the test_occlusion block, block entity renderer, generated assets, and compute-test binding updates.

Impact and Compatibility

  • The Hi-Z path currently provides depth conversion and SPD infrastructure; visibility decisions and SPD dispatch still require follow-up work.
  • The bindless SPD pipeline is defined, but runtime registration and dispatch selection are not complete.
  • Bindless image arrays require ARB_bindless_texture; the regular SPD path remains available.
  • ALRComputePass now uses explicit bindings, lazy Supplier<String> debug groups, and popDebugGroup(); internal callers were updated.
  • The rendering and test modules compile successfully with the focused Gradle tasks.

@ZhuRuoLing
ZhuRuoLing marked this pull request as draft August 7, 2026 21:58
@ZhuRuoLing
ZhuRuoLing force-pushed the feat/occusion_culling branch from 3c58b50 to 4cdf68c Compare August 13, 2026 22:34
@ZhuRuoLing ZhuRuoLing changed the title Refactor API status handling and add occlusion culling feat(rendering): add occlusion culling backends and bindless texturing Sep 4, 2026
@ZhuRuoLing
ZhuRuoLing marked this pull request as ready for review September 8, 2026 11:22
@Anvil-Dev Anvil-Dev deleted a comment from Gugle2308 Sep 8, 2026
@Anvil-Dev Anvil-Dev deleted a comment from Gugle2308 Sep 8, 2026
@Anvil-Dev Anvil-Dev deleted a comment from Gugle2308 Sep 8, 2026
@Anvil-Dev Anvil-Dev deleted a comment from Gugle2308 Sep 8, 2026
@Anvil-Dev Anvil-Dev deleted a comment from Gugle2308 Sep 8, 2026
@Anvil-Dev Anvil-Dev deleted a comment from Gugle2308 Sep 8, 2026
@Anvil-Dev Anvil-Dev deleted a comment from Gugle2308 Sep 8, 2026
@Anvil-Dev Anvil-Dev deleted a comment from Gugle2308 Sep 8, 2026
@Anvil-Dev Anvil-Dev deleted a comment from Gugle2308 Sep 8, 2026
@Anvil-Dev Anvil-Dev deleted a comment from Gugle2308 Sep 8, 2026
@Anvil-Dev Anvil-Dev deleted a comment from Gugle2308 Sep 8, 2026
@Anvil-Dev Anvil-Dev deleted a comment from Gugle2308 Sep 8, 2026
@Anvil-Dev Anvil-Dev deleted a comment from Gugle2308 Sep 8, 2026
@Gugle2308

Copy link
Copy Markdown

⚠️ Dangerous command requires approval:

grep -o '"head": *{' /tmp/pr95.json; python3 -c "
import json
d=json.load(open('/tmp/pr95.json'))
print('head sha:', d['head']['sha'])
print('head ref:', d['head']['ref'])
print('base ref:', d['base']...

Reason: script execution via -e/-c flag

Reply /approve to execute, /approve session to approve this pattern for the session, /approve always to approve permanently, or /deny to cancel.

@Gugle2308

Copy link
Copy Markdown

All verification complete. This is round 18 (十八复) — delta is a single commit 「SO AMD FUCK U」fixing an AMD driver issue, and the fix is incomplete (regular shader only). Writing the review:

代码审查摘要 — PR #95(十八复 / synchronize)

操作: synchronize · HEAD: 7fda2234(「feat(rendering): SO AMD FUCK U」09-08 17:10Z,非零增量
本轮真增量: compare 3249356c...7fda2234 = 1 commit / 7 文件 / 224 行(vs 全量 157 文件 / 9594 行)
增量文件: ALRComputePipelines、GlComputePassBackend、ALRComputeProgramInstance、MinecraftMixin、DepthTexConverter、hiz_occlusion_test.csh、hiz_occlusion_test_bindless.csh

🔴 关键

  • AMD 动态索引 workaround 只修了 regular 变体,bindless 变体仍是动态 image 数组索引hiz_occlusion_test_bindless.csh:133 仍是 imageLoad(uInputs[mip], ...),而 regular 变体本轮新增 loadHiZ() 用 0..12 常量 case 逐 mip 展开(hiz_occlusion_test.csh:40-57)。两个 shader 的 mip 选择循环完全相同for level < validMips 内按 AABB 尺寸 break → mip 逐 invocation 不同 = 非 dynamically uniform)——对 opaque 数组做非常量索引本就是 UB,AMD 驱动上表现为此 commit 想修的故障。bindless 是活动派发路径HierarchicalZOcclusionCuller.dispatch 264-266 行按 useBindlessTexturing 选 HIZ_OCCLUSION_TEST_BINDLESS,且该管线已 registerPipeline),所以在「支持 bindless 的 AMD 机器」上故障原样保留。修复:把同一 loadHiZ switch 复制进 bindless 变体——这正是 §34 双 shader 分叉教训(十五复刚统一过 pixel 缩放行)的又一次重演:修一个变体忘另一个。

⚠️ 警告

  • GlComputePassBackend.setupTexture 注释掉的代码块 + 只为注释服务的参数programInstance 参数只被注释代码引用(按 binding 名查 TEXTURE_OR_IMAGE 布局 + glUniform1i)。如果 AnvilLib 全部 compute shader 的 sampler/image 都带 layout(binding=N),这块注释是多余实验,请连参数一起删掉;如果存在不带 layout binding 的 uniform sampler2D 而走 bindTexture() 的 shader,注释掉的 glUniform1i 是必须的(否则绑定到 unit≥1 的纹理永不生效,默认采 unit 0)——两种情况二选一,别留死代码。
  • MinecraftMixin.onCreateInstance 新增 LOGGER.info(ALRHICapabilities.getInstance().toString()) — 每次游戏启动打一条 INFO 级调试日志(上一行 ALROptimizations.create() 已消费过该单例,null 安全,纯噪音)。合并前删掉或降 DEBUG。

✅ 正向确认

  • 四条 SPD 管线 withName 去重FFX_SPD_DOWNSAMPLE_PASS_NO_LDSffx_spd_downsample_pass_no_lds..._BINDLESS_NO_LDS..._bindless_no_lds,不再与基础变体共享名字(§38 已核实 program 缓存 key=(location, defines),改名无碰撞风险,纯标签准确性收益)。
  • DepthTexConverter.runConvertTEXTURE_FETCH_BARRIER — convert 产物被后续 pass 以纹理采样方式消费,barrier 补得正确。
  • loadHiZ switch 0..12 覆盖完整数组(MAX_MIP_LEVELS=12 → 13 槽),default: 1.0 保守(恒过深度测试 = 不误剔);mipLevels 注释明确是「含 mip 0 的条目数」,clamp(..., MAX_MIP_LEVELS+1) 上限 13 → 循环内 mip ≤ 12,与数组/switch 边界自洽,无 off-by-one
  • bindless 变体 corners 缩进修正 = 与 regular 对齐的纯格式。

📋 跨轮次未修项核对(本轮未触碰文件,合并 grep 确认全部原样,行号 = 9594 行全量 diff 基线)

问题 行号 状态
simpleCodec(TestBloomBlock::new) codec 引用错类 9402 ❌ 未修
getBuffer(6 * 6) + drawIndexed(0, 0, 6 * 6, 1)(QUADS 24 顶点 vs 36 索引) 6440 / 6497 ❌ 未修(GPU_QUERY 接线后 active)
new AABB(worldPosition) 零尺寸盒 + inflate(0.1) 9441 / 6805 ❌ 未修
IntSizeUbo 宽高互换(getHeight 先行) 3324 ❌ 未修
midTex = textures.get(6) SPD mid-mip 语义 6214 / 6250 ❌ 未修
mipmap 节流(十六复 §37 引入项) 5200-5307 原样(interval 默认 0,inert)
GL46.* 入口点 / isSupported 恒 true / 阻塞读 / alrSetWasUsed / 提交门控死锁等 各处 ❌ 未修
十七复 ⚠️GL_KHR_shader_subgroup 探测 vs shader _quad : require、define=0 变体无条件注册、HZOC 死 import) ❌ 本轮未触碰

结论

REQUEST_CHANGES — 本轮 commit 的 AMD 修复方向正确(常量索引 switch + TEXTURE_FETCH_BARRIER),但只修了双变体中的一半:bindless 派发路径上动态 image 数组索引原样保留,AMD 故障在 bindless 配置下必然复现;请同步修复 bindless 变体并清理 setupTexture 死代码与启动 INFO 日志。旧 blocker(codec 错类 / 6*6 索引越界 / AABB 零尺寸 / IntSizeUbo)已跨 10+ 轮未修,建议优先处理。

gh 未认证(token invalid,401),标题未修改(现标题准确无需改)。

@Gugle2308

Copy link
Copy Markdown

🌿 Roseau API Breaking Change Report

Module Status Breaking Changes
codec ✅ Compatible 0
collision ✅ Compatible 0
config ✅ Compatible 0
integration ✅ Compatible 0
moveable-entity-block ✅ Compatible 0
network ✅ Compatible 0
rendering 🔴 BC detected 44
space-select ✅ Compatible 0
font ✅ Compatible 0
util ✅ Compatible 0
explosion ✅ Compatible 0
rpc ✅ Compatible 0
multiblock ✅ Compatible 0
recipe ✅ Compatible 0
registrum ✅ Compatible 0
sync ✅ Compatible 0
wheel ✅ Compatible 0
main ✅ Compatible 0

🔴 rendering — 44 breaking change(s)

dev/anvilcraft/lib/v2/rendering/extension/blaze3d/ALRGpuDeviceExtension.java

dev.anvilcraft.lib.v2.rendering.extension.blaze3d.ALRGpuDeviceExtension
dev.anvilcraft.lib.v2.rendering.extension.blaze3d.ALRGpuDeviceExtension
TYPE_NEW_ABSTRACT_METHOD
✓ binary-compatible
✗ source-breaking

dev/anvilcraft/lib/v2/rendering/extension/blaze3d/ALRGpuDeviceExtension.java

dev.anvilcraft.lib.v2.rendering.extension.blaze3d.ALRGpuDeviceExtension
dev.anvilcraft.lib.v2.rendering.extension.blaze3d.ALRGpuDeviceExtension
TYPE_NEW_ABSTRACT_METHOD
✓ binary-compatible
✗ source-breaking

dev/anvilcraft/lib/v2/rendering/extension/blaze3d/ALRGpuDeviceExtension.java

dev.anvilcraft.lib.v2.rendering.extension.blaze3d.ALRGpuDeviceExtension
dev.anvilcraft.lib.v2.rendering.extension.blaze3d.ALRGpuDeviceExtension
TYPE_NEW_ABSTRACT_METHOD
✓ binary-compatible
✗ source-breaking

dev/anvilcraft/lib/v2/rendering/extension/blaze3d/ALRGpuDeviceExtension.java

dev.anvilcraft.lib.v2.rendering.extension.blaze3d.ALRGpuDeviceExtension
dev.anvilcraft.lib.v2.rendering.extension.blaze3d.ALRGpuDeviceExtension
TYPE_NEW_ABSTRACT_METHOD
✓ binary-compatible
✗ source-breaking

dev/anvilcraft/lib/v2/rendering/extension/blaze3d/ALRGpuDeviceExtension.java

dev.anvilcraft.lib.v2.rendering.extension.blaze3d.ALRGpuDeviceExtension
dev.anvilcraft.lib.v2.rendering.extension.blaze3d.ALRGpuDeviceExtension
TYPE_NEW_ABSTRACT_METHOD
✓ binary-compatible
✗ source-breaking

dev/anvilcraft/lib/v2/rendering/extension/blaze3d/ALRGpuDeviceExtension.java

dev.anvilcraft.lib.v2.rendering.extension.blaze3d.ALRGpuDeviceExtension
dev.anvilcraft.lib.v2.rendering.extension.blaze3d.ALRGpuDeviceExtension
TYPE_NEW_ABSTRACT_METHOD
✓ binary-compatible
✗ source-breaking

dev/anvilcraft/lib/v2/rendering/extension/blaze3d/ALRGpuDeviceExtension.java

dev.anvilcraft.lib.v2.rendering.extension.blaze3d.ALRGpuDeviceExtension
dev.anvilcraft.lib.v2.rendering.extension.blaze3d.ALRGpuDeviceExtension
TYPE_NEW_ABSTRACT_METHOD
✓ binary-compatible
✗ source-breaking

dev/anvilcraft/lib/v2/rendering/extension/blaze3d/ALRGpuDeviceExtension.java

dev.anvilcraft.lib.v2.rendering.extension.blaze3d.ALRGpuDeviceExtension
dev.anvilcraft.lib.v2.rendering.extension.blaze3d.ALRGpuDeviceExtension
TYPE_NEW_ABSTRACT_METHOD
✓ binary-compatible
✗ source-breaking

dev/anvilcraft/lib/v2/rendering/extension/blaze3d/ALRGpuDeviceExtension.java

dev.anvilcraft.lib.v2.rendering.extension.blaze3d.ALRGpuDeviceExtension
dev.anvilcraft.lib.v2.rendering.extension.blaze3d.ALRGpuDeviceExtension.alrCompileComputeShader(dev.anvilcraft.lib.v2.rendering.extension.blaze3d.compute.shader.ALRComputeProgramInstanceKey)
EXECUTABLE_REMOVED
✗ binary-breaking
✗ source-breaking

dev/anvilcraft/lib/v2/rendering/extension/blaze3d/compute/pipeline/ALRComputePass.java:66

dev.anvilcraft.lib.v2.rendering.extension.blaze3d.compute.pipeline.ALRComputePass
dev.anvilcraft.lib.v2.rendering.extension.blaze3d.compute.pipeline.ALRComputePass.bind(int,dev.anvilcraft.lib.v2.rendering.extension.blaze3d.compute.pipeline.bindings.ComputeBindingLayout<T>,T)
METHOD_RETURN_TYPE_ERASURE_CHANGED
✗ binary-breaking
✓ source-compatible

dev/anvilcraft/lib/v2/rendering/extension/blaze3d/compute/pipeline/ALRComputePass.java:66

dev.anvilcraft.lib.v2.rendering.extension.blaze3d.compute.pipeline.ALRComputePass
dev.anvilcraft.lib.v2.rendering.extension.blaze3d.compute.pipeline.ALRComputePass.bind(int,dev.anvilcraft.lib.v2.rendering.extension.blaze3d.compute.pipeline.bindings.ComputeBindingLayout<T>,T)
METHOD_RETURN_TYPE_CHANGED_INCOMPATIBLE
✓ binary-compatible
✗ source-breaking

dev/anvilcraft/lib/v2/rendering/extension/blaze3d/compute/pipeline/ALRComputePass.java:59

dev.anvilcraft.lib.v2.rendering.extension.blaze3d.compute.pipeline.ALRComputePass
dev.anvilcraft.lib.v2.rendering.extension.blaze3d.compute.pipeline.ALRComputePass.bindAll(java.util.List<? extends java.lang.Object>)
EXECUTABLE_REMOVED
✗ binary-breaking
✗ source-breaking

dev/anvilcraft/lib/v2/rendering/extension/blaze3d/compute/pipeline/ALRComputePass.java:24

dev.anvilcraft.lib.v2.rendering.extension.blaze3d.compute.pipeline.ALRComputePass
dev.anvilcraft.lib.v2.rendering.extension.blaze3d.compute.pipeline.ALRComputePass.popDebugGroup(java.lang.String)
EXECUTABLE_REMOVED
✗ binary-breaking
✗ source-breaking

dev/anvilcraft/lib/v2/rendering/extension/blaze3d/compute/pipeline/ALRComputePass.java:20

dev.anvilcraft.lib.v2.rendering.extension.blaze3d.compute.pipeline.ALRComputePass
dev.anvilcraft.lib.v2.rendering.extension.blaze3d.compute.pipeline.ALRComputePass.pushDebugGroup(java.lang.String)
EXECUTABLE_REMOVED
✗ binary-breaking
✗ source-breaking

dev/anvilcraft/lib/v2/rendering/extension/blaze3d/compute/pipeline/ALRComputePassBackend.java

dev.anvilcraft.lib.v2.rendering.extension.blaze3d.compute.pipeline.ALRComputePassBackend
dev.anvilcraft.lib.v2.rendering.extension.blaze3d.compute.pipeline.ALRComputePassBackend.pushDebugGroup(java.lang.String)
EXECUTABLE_REMOVED
✗ binary-breaking
✗ source-breaking

dev/anvilcraft/lib/v2/rendering/extension/blaze3d/compute/pipeline/ALRComputePipeline.java

dev.anvilcraft.lib.v2.rendering.extension.blaze3d.compute.pipeline.ALRComputePipeline
dev.anvilcraft.lib.v2.rendering.extension.blaze3d.compute.pipeline.ALRComputePipeline
TYPE_KIND_CHANGED
✗ binary-breaking
✗ source-breaking

dev/anvilcraft/lib/v2/rendering/extension/blaze3d/compute/pipeline/bindings/AtomicCounterBinding.java

dev.anvilcraft.lib.v2.rendering.extension.blaze3d.compute.pipeline.bindings.AtomicCounterBinding
dev.anvilcraft.lib.v2.rendering.extension.blaze3d.compute.pipeline.bindings.AtomicCounterBinding
TYPE_NEW_ABSTRACT_METHOD
✓ binary-compatible
✗ source-breaking

dev/anvilcraft/lib/v2/rendering/extension/blaze3d/compute/pipeline/bindings/AtomicCounterBinding.java:17

dev.anvilcraft.lib.v2.rendering.extension.blaze3d.compute.pipeline.bindings.AtomicCounterBinding
dev.anvilcraft.lib.v2.rendering.extension.blaze3d.compute.pipeline.bindings.AtomicCounterBinding.apply(int,com.mojang.blaze3d.buffers.GpuBufferSlice,dev.anvilcraft.lib.v2.rendering.extension.blaze3d.compute.pipeline.ALRComputePass)
EXECUTABLE_REMOVED
✗ binary-breaking
✗ source-breaking

dev/anvilcraft/lib/v2/rendering/extension/blaze3d/compute/pipeline/bindings/ComputeBindingLayout.java

dev.anvilcraft.lib.v2.rendering.extension.blaze3d.compute.pipeline.bindings.AtomicCounterBinding
dev.anvilcraft.lib.v2.rendering.extension.blaze3d.compute.pipeline.bindings.ComputeBindingLayout.apply(int,T,dev.anvilcraft.lib.v2.rendering.extension.blaze3d.compute.pipeline.ALRComputePass)
EXECUTABLE_REMOVED
✗ binary-breaking
✗ source-breaking

dev/anvilcraft/lib/v2/rendering/extension/blaze3d/compute/pipeline/bindings/ComputeBindingLayout.java

dev.anvilcraft.lib.v2.rendering.extension.blaze3d.compute.pipeline.bindings.ComputeBindingLayout
dev.anvilcraft.lib.v2.rendering.extension.blaze3d.compute.pipeline.bindings.ComputeBindingLayout
TYPE_NEW_ABSTRACT_METHOD
✓ binary-compatible
✗ source-breaking

dev/anvilcraft/lib/v2/rendering/extension/blaze3d/compute/pipeline/bindings/ComputeBindingLayout.java

dev.anvilcraft.lib.v2.rendering.extension.blaze3d.compute.pipeline.bindings.ComputeBindingLayout
dev.anvilcraft.lib.v2.rendering.extension.blaze3d.compute.pipeline.bindings.ComputeBindingLayout.apply(int,T,dev.anvilcraft.lib.v2.rendering.extension.blaze3d.compute.pipeline.ALRComputePass)
EXECUTABLE_REMOVED
✗ binary-breaking
✗ source-breaking

dev/anvilcraft/lib/v2/rendering/extension/blaze3d/compute/pipeline/bindings/ComputeBindingLayout.java

dev.anvilcraft.lib.v2.rendering.extension.blaze3d.compute.pipeline.bindings.ImageBinding
dev.anvilcraft.lib.v2.rendering.extension.blaze3d.compute.pipeline.bindings.ComputeBindingLayout.apply(int,T,dev.anvilcraft.lib.v2.rendering.extension.blaze3d.compute.pipeline.ALRComputePass)
EXECUTABLE_REMOVED
✗ binary-breaking
✗ source-breaking

dev/anvilcraft/lib/v2/rendering/extension/blaze3d/compute/pipeline/bindings/ImageBinding.java

dev.anvilcraft.lib.v2.rendering.extension.blaze3d.compute.pipeline.bindings.ImageBinding
dev.anvilcraft.lib.v2.rendering.extension.blaze3d.compute.pipeline.bindings.ImageBinding
TYPE_NEW_ABSTRACT_METHOD
✓ binary-compatible
✗ source-breaking

dev/anvilcraft/lib/v2/rendering/extension/blaze3d/compute/pipeline/bindings/ImageBinding.java:26

dev.anvilcraft.lib.v2.rendering.extension.blaze3d.compute.pipeline.bindings.ImageBinding
dev.anvilcraft.lib.v2.rendering.extension.blaze3d.compute.pipeline.bindings.ImageBinding.apply(int,com.mojang.blaze3d.textures.GpuTexture,dev.anvilcraft.lib.v2.rendering.extension.blaze3d.compute.pipeline.ALRComputePass)
EXECUTABLE_REMOVED
✗ binary-breaking
✗ source-breaking

dev/anvilcraft/lib/v2/rendering/extension/blaze3d/compute/pipeline/bindings/ComputeBindingLayout.java

dev.anvilcraft.lib.v2.rendering.extension.blaze3d.compute.pipeline.bindings.ShaderStorageBinding
dev.anvilcraft.lib.v2.rendering.extension.blaze3d.compute.pipeline.bindings.ComputeBindingLayout.apply(int,T,dev.anvilcraft.lib.v2.rendering.extension.blaze3d.compute.pipeline.ALRComputePass)
EXECUTABLE_REMOVED
✗ binary-breaking
✗ source-breaking

dev/anvilcraft/lib/v2/rendering/extension/blaze3d/compute/pipeline/bindings/ShaderStorageBinding.java

dev.anvilcraft.lib.v2.rendering.extension.blaze3d.compute.pipeline.bindings.ShaderStorageBinding
dev.anvilcraft.lib.v2.rendering.extension.blaze3d.compute.pipeline.bindings.ShaderStorageBinding
TYPE_NEW_ABSTRACT_METHOD
✓ binary-compatible
✗ source-breaking

dev/anvilcraft/lib/v2/rendering/extension/blaze3d/compute/pipeline/bindings/ShaderStorageBinding.java:18

dev.anvilcraft.lib.v2.rendering.extension.blaze3d.compute.pipeline.bindings.ShaderStorageBinding
dev.anvilcraft.lib.v2.rendering.extension.blaze3d.compute.pipeline.bindings.ShaderStorageBinding.apply(int,com.mojang.blaze3d.buffers.GpuBufferSlice,dev.anvilcraft.lib.v2.rendering.extension.blaze3d.compute.pipeline.ALRComputePass)
EXECUTABLE_REMOVED
✗ binary-breaking
✗ source-breaking

dev/anvilcraft/lib/v2/rendering/extension/blaze3d/compute/pipeline/bindings/ComputeBindingLayout.java

dev.anvilcraft.lib.v2.rendering.extension.blaze3d.compute.pipeline.bindings.TextureBinding
dev.anvilcraft.lib.v2.rendering.extension.blaze3d.compute.pipeline.bindings.ComputeBindingLayout.apply(int,T,dev.anvilcraft.lib.v2.rendering.extension.blaze3d.compute.pipeline.ALRComputePass)
EXECUTABLE_REMOVED
✗ binary-breaking
✗ source-breaking

dev/anvilcraft/lib/v2/rendering/extension/blaze3d/compute/pipeline/bindings/TextureBinding.java

dev.anvilcraft.lib.v2.rendering.extension.blaze3d.compute.pipeline.bindings.TextureBinding
dev.anvilcraft.lib.v2.rendering.extension.blaze3d.compute.pipeline.bindings.TextureBinding
TYPE_NEW_ABSTRACT_METHOD
✓ binary-compatible
✗ source-breaking

dev/anvilcraft/lib/v2/rendering/extension/blaze3d/compute/pipeline/bindings/TextureBinding.java:18

dev.anvilcraft.lib.v2.rendering.extension.blaze3d.compute.pipeline.bindings.TextureBinding
dev.anvilcraft.lib.v2.rendering.extension.blaze3d.compute.pipeline.bindings.TextureBinding.apply(int,dev.anvilcraft.lib.v2.rendering.extension.blaze3d.compute.pipeline.bindings.TextureBinding$SamplerAndTexture,dev.anvilcraft.lib.v2.rendering.extension.blaze3d.compute.pipeline.ALRComputePass)
EXECUTABLE_REMOVED
✗ binary-breaking
✗ source-breaking

dev/anvilcraft/lib/v2/rendering/extension/blaze3d/compute/pipeline/bindings/ComputeBindingLayout.java

dev.anvilcraft.lib.v2.rendering.extension.blaze3d.compute.pipeline.bindings.UniformBlockBinding
dev.anvilcraft.lib.v2.rendering.extension.blaze3d.compute.pipeline.bindings.ComputeBindingLayout.apply(int,T,dev.anvilcraft.lib.v2.rendering.extension.blaze3d.compute.pipeline.ALRComputePass)
EXECUTABLE_REMOVED
✗ binary-breaking
✗ source-breaking

dev/anvilcraft/lib/v2/rendering/extension/blaze3d/compute/pipeline/bindings/UniformBlockBinding.java

dev.anvilcraft.lib.v2.rendering.extension.blaze3d.compute.pipeline.bindings.UniformBlockBinding
dev.anvilcraft.lib.v2.rendering.extension.blaze3d.compute.pipeline.bindings.UniformBlockBinding
TYPE_NEW_ABSTRACT_METHOD
✓ binary-compatible
✗ source-breaking

dev/anvilcraft/lib/v2/rendering/extension/blaze3d/compute/pipeline/bindings/UniformBlockBinding.java:17

dev.anvilcraft.lib.v2.rendering.extension.blaze3d.compute.pipeline.bindings.UniformBlockBinding
dev.anvilcraft.lib.v2.rendering.extension.blaze3d.compute.pipeline.bindings.UniformBlockBinding.apply(int,com.mojang.blaze3d.buffers.GpuBufferSlice,dev.anvilcraft.lib.v2.rendering.extension.blaze3d.compute.pipeline.ALRComputePass)
EXECUTABLE_REMOVED
✗ binary-breaking
✗ source-breaking

dev/anvilcraft/lib/v2/rendering/extension/blaze3d/compute/shader/ALRComputeProgramInstance.java

dev.anvilcraft.lib.v2.rendering.extension.blaze3d.compute.shader.ALRComputeProgramInstance
dev.anvilcraft.lib.v2.rendering.extension.blaze3d.compute.shader.ALRComputeProgramInstance
TYPE_KIND_CHANGED
✗ binary-breaking
✗ source-breaking

dev/anvilcraft/lib/v2/rendering/extension/blaze3d/compute/shader/ShaderResourceType.java

dev.anvilcraft.lib.v2.rendering.extension.blaze3d.compute.shader.ShaderResourceType
dev.anvilcraft.lib.v2.rendering.extension.blaze3d.compute.shader.ShaderResourceType.IMAGE
FIELD_REMOVED
✗ binary-breaking
✗ source-breaking

dev/anvilcraft/lib/v2/rendering/extension/blaze3d/compute/shader/ShaderResourceType.java

dev.anvilcraft.lib.v2.rendering.extension.blaze3d.compute.shader.ShaderResourceType
dev.anvilcraft.lib.v2.rendering.extension.blaze3d.compute.shader.ShaderResourceType.TEXTURE
FIELD_REMOVED
✗ binary-breaking
✗ source-breaking

dev/anvilcraft/lib/v2/rendering/foundation/buffers/layout/BufferSizeCalculator.java

dev.anvilcraft.lib.v2.rendering.foundation.buffers.layout.BufferSizeCalculator
dev.anvilcraft.lib.v2.rendering.foundation.buffers.layout.BufferSizeCalculator
TYPE_NEW_ABSTRACT_METHOD
✓ binary-compatible
✗ source-breaking

dev/anvilcraft/lib/v2/rendering/foundation/buffers/layout/BufferSizeCalculator.java

dev.anvilcraft.lib.v2.rendering.foundation.buffers.layout.BufferSizeCalculator
dev.anvilcraft.lib.v2.rendering.foundation.buffers.layout.BufferSizeCalculator
TYPE_NEW_ABSTRACT_METHOD
✓ binary-compatible
✗ source-breaking

dev/anvilcraft/lib/v2/rendering/foundation/buffers/layout/BufferWriter.java

dev.anvilcraft.lib.v2.rendering.foundation.buffers.layout.BufferWriter
dev.anvilcraft.lib.v2.rendering.foundation.buffers.layout.BufferWriter
TYPE_NEW_ABSTRACT_METHOD
✓ binary-compatible
✗ source-breaking

dev/anvilcraft/lib/v2/rendering/foundation/buffers/layout/BufferWriter.java

dev.anvilcraft.lib.v2.rendering.foundation.buffers.layout.BufferWriter
dev.anvilcraft.lib.v2.rendering.foundation.buffers.layout.BufferWriter
TYPE_NEW_ABSTRACT_METHOD
✓ binary-compatible
✗ source-breaking

dev/anvilcraft/lib/v2/rendering/foundation/buffers/layout/BufferWriter.java

dev.anvilcraft.lib.v2.rendering.foundation.buffers.layout.BufferWriter
dev.anvilcraft.lib.v2.rendering.foundation.buffers.layout.BufferWriter
TYPE_NEW_ABSTRACT_METHOD
✓ binary-compatible
✗ source-breaking

dev/anvilcraft/lib/v2/rendering/foundation/buffers/layout/BufferWriter.java

dev.anvilcraft.lib.v2.rendering.foundation.buffers.layout.BufferWriter
dev.anvilcraft.lib.v2.rendering.foundation.buffers.layout.BufferWriter
TYPE_NEW_ABSTRACT_METHOD
✓ binary-compatible
✗ source-breaking

dev/anvilcraft/lib/v2/rendering/foundation/buffers/layout/BufferWriter.java:38

dev.anvilcraft.lib.v2.rendering.foundation.buffers.layout.BufferWriter
dev.anvilcraft.lib.v2.rendering.foundation.buffers.layout.BufferWriter.putStructArray(E[],dev.anvilcraft.lib.v2.rendering.foundation.buffers.object.BufferObjectLayoutDefinition<E>)
EXECUTABLE_REMOVED
✗ binary-breaking
✗ source-breaking

dev/anvilcraft/lib/v2/rendering/foundation/buffers/layout/std140/Std140Writer.java:106

dev.anvilcraft.lib.v2.rendering.foundation.buffers.layout.std140.Std140Writer
dev.anvilcraft.lib.v2.rendering.foundation.buffers.layout.std140.Std140Writer.putStructArray(E[],dev.anvilcraft.lib.v2.rendering.foundation.buffers.object.BufferObjectLayoutDefinition<E>)
EXECUTABLE_REMOVED
✗ binary-breaking
✗ source-breaking

Full CSVs: see the Artifacts section of this workflow run.

@Gugle2308

Copy link
Copy Markdown

💾 Self-improvement review: Patched SKILL.md in skill 'rendering-gpu-pr-review' (1 replacement). · Patched references/pr95-occlusion-culling-review-matrix.md in skill 'rendering-gpu-pr-review' (1 replacement).

@Gugle2308

Copy link
Copy Markdown

代码审查摘要 — PR #95(synchronize 复审查 · 十九复)

操作: synchronize
本轮增量: 2 commits(29e0ae22「add ApiStatus.Internal annotation and cache disposing」+ 5a16c602「fix ai slop」09-09),compare 7fda2234...5a16c602 = 21 文件 / 455 行;全量 diff 158 文件 / 9719 行(上轮 9594,+125 漂移)
审查方法: compare API 增量定位 → 增量 diff 全读 → 旧项合并 grep 回归(codec/6*6/AABB/IntSizeUbo/midTex/isSupported/GL46/Unsafe)


🔴 关键(本轮新增)

  • GlTextureMixin(新文件)无守卫硬转 + dispose 不解除驻留 — 注入 GlTexture.close() HEAD,对全游戏每一次纹理关闭(含原版纹理)生效:
    1. (ALRGpuDeviceExtension) RenderSystem.getDevice()instanceof/null 守卫——device 为 null(关闭时序/非渲染线程)时 backend.alrGetBindlessTexturingSupport() 直接 NPE;mixin 未生效时 CCE。这是 §8 模式落在最热路径上(每次纹理销毁都跑),建议改为 if (RenderSystem.getDevice() instanceof ALRGpuDeviceExtension backend && backend.alrGetBindlessTexturingSupport() != null)
    2. alrTextureDisposed 只删 cache 条目,不调用 alrTextureHandleDeleteResident(glMakeTextureHandleNonResidentARB)。若纹理关闭时其 resident scope 仍开着(scope.close 延后执行),GL 对象已删后 scope.close 会对失效 handle 调 nonResident → GL_INVALID_VALUE/UB。需保证「scope 先于纹理 close 关闭」,或在 dispose 时对仍 resident 的 handle 补 de-resident。
    3. 缓存键是 (texture, sampler) 实例引用,eviction 用 key.texture() == texture 恒等比较——同 glId 经不同 Java 实例(view/包装)访问时命中不了;好在 eviction 发生在 HEAD(GL 删除前),时序方向正确,但建议注释说明该恒等前提。

⚠️ 警告

  • OcclusionCuller 接口打 @ApiStatus.Internal,与本轮同步加的公开使用 javadoc 自相矛盾 — 新 javadoc 用「A typical block-entity renderer submits its geometry as follows」示范 ALROptimizations.getOcclusionCuller() + wrapSubmitNodeStorage 用法(面向库使用者),却把整个接口标 Internal。二选一:真内部 → javadoc 示例标注 internal-only/移除;对外扩展点 → 去掉接口级 Internal(保留 OCCLUSION_QUERY/TestOcclusion 等实现的 Internal 即可)。
  • alrTextureDisposed 是接口新增抽象方法(非 default)——BindlessTexturingSupport 若有其他实现者会编译失败;目前仅 GlBindlessTexturingSupport 一个实现,确认无 test/mock 实现者即可。
  • 旧 blockers 本轮文件未触碰,全部仍存(行号为 9719 行全量 diff 基线):
    • getBuffer(6 * 6) + drawIndexed(0, 0, 6 * 6, 1)6564 / 6621(QUADS 6 面=24 顶点却用 TRIANGLES 索引数 36,GPU 越界读,active)
    • frustum pre-pass 命中的 key 仍建 query 并绘制(6569-6581 无 continue)——结果在 shouldDraw 已被 CPU 侧短路,纯浪费 + 池抖动
    • runQueries 的 push/pop debug group 无 try/finally(push 6571 / pop 6632)——renderPass 内异常跳过 releaseInstance 循环 + pop,debug 栈失衡 + 池泄漏
    • IntSizeUbo DEFINITION getHeight 先于 getWidth(3347,与 GLSL 声明序互换)
    • new AABB(worldPosition) 零尺寸盒(9566)+ inflate(0.1)(6929)
    • midTex = textures.get(6)(6336/6372,SPD mid-mip 槽语义错)
    • GPU_QUERY.isSupported() 恒 true(4958-4960)
    • GL46 硬依赖入口点 ×38
    • MemoryAccess sun.misc.Unsafe 反射读取(7125-7148)
    • alrSetWasUsed(true) 篡改 original collection(5157)
    • §31 阈值不对称:useBindlessTexturingmaxImageUnit() < 16HIERARCHICAL_Z.isSupported()> 16(4969)——==16 时两侧判定矛盾

✅ 修复确认(正向)

  • TestOcclusionBlock.codec() 错类终于修复simpleCodec(TestBloomBlock::new)simpleCodec(TestOcclusionBlock::new)(9527),§25 多轮 blocker 闭环。
  • HierarchicalZOcclusionCuller 死 import 清理(移除 ALROptions/ALRHICapabilities/ALRComputePipeline)——呼应「fix ai slop」提交名。
  • GlTextureMixin 注册在 anvillib_rendering.mixins.jsonclient 数组(line 29,与 GlDeviceMixin 同级)——GlTexture 是 client-only 类,dist 归属正确,无 §33 类问题。
  • §30「handle cache 无 evict」TODO 落地alrTextureDisposed 遍历 texture/image 双 cache 按纹理清键,方向正确。
  • OcclusionCuller.createInstance 末尾 return new NoOpOcclusionCuller() 与 javadoc「never null」声明一致 ✅。
  • 52 处 import org.jetbrains.annotations.ApiStatus 新增中,本轮 17 个文件各仅 1 处、无同文件重复 import。

💡 建议

  • @SuppressWarnings("resource") 放在 alrTextureDisposed 上仅因 record key 持 GpuTexture——语义上该方法是「放弃缓存引用」而非关闭资源,可加一行注释说明(避免后人误以为这里释放了 GL 资源)。
  • ApiStatus.Internal 批量清扫本身是好事(明确内部 API 边界),建议顺带把 createInstance@SuppressWarnings("ConstantValue") 清理掉——如今 fallback 链已是运行期判定,该抑制项疑似过期。

📋 结论: REQUEST_CHANGES

本轮增量质量比前几轮好(codec 九轮终修 + 死代码清理 + evict 落地),但 GlTextureMixin 在全局纹理关闭热路径上缺 null/instanceof 守卫、dispose 不解除驻留,属必须补强的健壮性问题;drawIndexed 6*6 越界、零尺寸 AABB、IntSizeUbo 互换等 active 旧 blocker 仍原样存在,建议下轮一并处理。

(gh 未认证 — token invalid,跳过标题修改;标题本身准确无需改。)

@Gugle2308

Copy link
Copy Markdown

💾 Self-improvement review: Patched SKILL.md in skill 'rendering-gpu-pr-review' (1 replacement). · Patched references/pr95-occlusion-culling-review-matrix.md in skill 'rendering-gpu-pr-review' (1 replacement).

@Gugle2308

Copy link
Copy Markdown

🌿 Roseau API Breaking Change Report

Module Status Breaking Changes
codec ✅ Compatible 0
collision ✅ Compatible 0
config ✅ Compatible 0
integration ✅ Compatible 0
moveable-entity-block ✅ Compatible 0
network ✅ Compatible 0
rendering 🔴 BC detected 44
space-select ✅ Compatible 0
font ✅ Compatible 0
util ✅ Compatible 0
explosion ✅ Compatible 0
rpc ✅ Compatible 0
multiblock ✅ Compatible 0
recipe ✅ Compatible 0
registrum ✅ Compatible 0
sync ✅ Compatible 0
wheel ✅ Compatible 0
main ✅ Compatible 0

🔴 rendering — 44 breaking change(s)

dev/anvilcraft/lib/v2/rendering/extension/blaze3d/ALRGpuDeviceExtension.java

dev.anvilcraft.lib.v2.rendering.extension.blaze3d.ALRGpuDeviceExtension
dev.anvilcraft.lib.v2.rendering.extension.blaze3d.ALRGpuDeviceExtension
TYPE_NEW_ABSTRACT_METHOD
✓ binary-compatible
✗ source-breaking

dev/anvilcraft/lib/v2/rendering/extension/blaze3d/ALRGpuDeviceExtension.java

dev.anvilcraft.lib.v2.rendering.extension.blaze3d.ALRGpuDeviceExtension
dev.anvilcraft.lib.v2.rendering.extension.blaze3d.ALRGpuDeviceExtension
TYPE_NEW_ABSTRACT_METHOD
✓ binary-compatible
✗ source-breaking

dev/anvilcraft/lib/v2/rendering/extension/blaze3d/ALRGpuDeviceExtension.java

dev.anvilcraft.lib.v2.rendering.extension.blaze3d.ALRGpuDeviceExtension
dev.anvilcraft.lib.v2.rendering.extension.blaze3d.ALRGpuDeviceExtension
TYPE_NEW_ABSTRACT_METHOD
✓ binary-compatible
✗ source-breaking

dev/anvilcraft/lib/v2/rendering/extension/blaze3d/ALRGpuDeviceExtension.java

dev.anvilcraft.lib.v2.rendering.extension.blaze3d.ALRGpuDeviceExtension
dev.anvilcraft.lib.v2.rendering.extension.blaze3d.ALRGpuDeviceExtension
TYPE_NEW_ABSTRACT_METHOD
✓ binary-compatible
✗ source-breaking

dev/anvilcraft/lib/v2/rendering/extension/blaze3d/ALRGpuDeviceExtension.java

dev.anvilcraft.lib.v2.rendering.extension.blaze3d.ALRGpuDeviceExtension
dev.anvilcraft.lib.v2.rendering.extension.blaze3d.ALRGpuDeviceExtension
TYPE_NEW_ABSTRACT_METHOD
✓ binary-compatible
✗ source-breaking

dev/anvilcraft/lib/v2/rendering/extension/blaze3d/ALRGpuDeviceExtension.java

dev.anvilcraft.lib.v2.rendering.extension.blaze3d.ALRGpuDeviceExtension
dev.anvilcraft.lib.v2.rendering.extension.blaze3d.ALRGpuDeviceExtension
TYPE_NEW_ABSTRACT_METHOD
✓ binary-compatible
✗ source-breaking

dev/anvilcraft/lib/v2/rendering/extension/blaze3d/ALRGpuDeviceExtension.java

dev.anvilcraft.lib.v2.rendering.extension.blaze3d.ALRGpuDeviceExtension
dev.anvilcraft.lib.v2.rendering.extension.blaze3d.ALRGpuDeviceExtension
TYPE_NEW_ABSTRACT_METHOD
✓ binary-compatible
✗ source-breaking

dev/anvilcraft/lib/v2/rendering/extension/blaze3d/ALRGpuDeviceExtension.java

dev.anvilcraft.lib.v2.rendering.extension.blaze3d.ALRGpuDeviceExtension
dev.anvilcraft.lib.v2.rendering.extension.blaze3d.ALRGpuDeviceExtension
TYPE_NEW_ABSTRACT_METHOD
✓ binary-compatible
✗ source-breaking

dev/anvilcraft/lib/v2/rendering/extension/blaze3d/ALRGpuDeviceExtension.java

dev.anvilcraft.lib.v2.rendering.extension.blaze3d.ALRGpuDeviceExtension
dev.anvilcraft.lib.v2.rendering.extension.blaze3d.ALRGpuDeviceExtension.alrCompileComputeShader(dev.anvilcraft.lib.v2.rendering.extension.blaze3d.compute.shader.ALRComputeProgramInstanceKey)
EXECUTABLE_REMOVED
✗ binary-breaking
✗ source-breaking

dev/anvilcraft/lib/v2/rendering/extension/blaze3d/compute/pipeline/ALRComputePass.java:66

dev.anvilcraft.lib.v2.rendering.extension.blaze3d.compute.pipeline.ALRComputePass
dev.anvilcraft.lib.v2.rendering.extension.blaze3d.compute.pipeline.ALRComputePass.bind(int,dev.anvilcraft.lib.v2.rendering.extension.blaze3d.compute.pipeline.bindings.ComputeBindingLayout<T>,T)
METHOD_RETURN_TYPE_ERASURE_CHANGED
✗ binary-breaking
✓ source-compatible

dev/anvilcraft/lib/v2/rendering/extension/blaze3d/compute/pipeline/ALRComputePass.java:66

dev.anvilcraft.lib.v2.rendering.extension.blaze3d.compute.pipeline.ALRComputePass
dev.anvilcraft.lib.v2.rendering.extension.blaze3d.compute.pipeline.ALRComputePass.bind(int,dev.anvilcraft.lib.v2.rendering.extension.blaze3d.compute.pipeline.bindings.ComputeBindingLayout<T>,T)
METHOD_RETURN_TYPE_CHANGED_INCOMPATIBLE
✓ binary-compatible
✗ source-breaking

dev/anvilcraft/lib/v2/rendering/extension/blaze3d/compute/pipeline/ALRComputePass.java:59

dev.anvilcraft.lib.v2.rendering.extension.blaze3d.compute.pipeline.ALRComputePass
dev.anvilcraft.lib.v2.rendering.extension.blaze3d.compute.pipeline.ALRComputePass.bindAll(java.util.List<? extends java.lang.Object>)
EXECUTABLE_REMOVED
✗ binary-breaking
✗ source-breaking

dev/anvilcraft/lib/v2/rendering/extension/blaze3d/compute/pipeline/ALRComputePass.java:24

dev.anvilcraft.lib.v2.rendering.extension.blaze3d.compute.pipeline.ALRComputePass
dev.anvilcraft.lib.v2.rendering.extension.blaze3d.compute.pipeline.ALRComputePass.popDebugGroup(java.lang.String)
EXECUTABLE_REMOVED
✗ binary-breaking
✗ source-breaking

dev/anvilcraft/lib/v2/rendering/extension/blaze3d/compute/pipeline/ALRComputePass.java:20

dev.anvilcraft.lib.v2.rendering.extension.blaze3d.compute.pipeline.ALRComputePass
dev.anvilcraft.lib.v2.rendering.extension.blaze3d.compute.pipeline.ALRComputePass.pushDebugGroup(java.lang.String)
EXECUTABLE_REMOVED
✗ binary-breaking
✗ source-breaking

dev/anvilcraft/lib/v2/rendering/extension/blaze3d/compute/pipeline/ALRComputePassBackend.java

dev.anvilcraft.lib.v2.rendering.extension.blaze3d.compute.pipeline.ALRComputePassBackend
dev.anvilcraft.lib.v2.rendering.extension.blaze3d.compute.pipeline.ALRComputePassBackend.pushDebugGroup(java.lang.String)
EXECUTABLE_REMOVED
✗ binary-breaking
✗ source-breaking

dev/anvilcraft/lib/v2/rendering/extension/blaze3d/compute/pipeline/ALRComputePipeline.java

dev.anvilcraft.lib.v2.rendering.extension.blaze3d.compute.pipeline.ALRComputePipeline
dev.anvilcraft.lib.v2.rendering.extension.blaze3d.compute.pipeline.ALRComputePipeline
TYPE_KIND_CHANGED
✗ binary-breaking
✗ source-breaking

dev/anvilcraft/lib/v2/rendering/extension/blaze3d/compute/pipeline/bindings/AtomicCounterBinding.java

dev.anvilcraft.lib.v2.rendering.extension.blaze3d.compute.pipeline.bindings.AtomicCounterBinding
dev.anvilcraft.lib.v2.rendering.extension.blaze3d.compute.pipeline.bindings.AtomicCounterBinding
TYPE_NEW_ABSTRACT_METHOD
✓ binary-compatible
✗ source-breaking

dev/anvilcraft/lib/v2/rendering/extension/blaze3d/compute/pipeline/bindings/AtomicCounterBinding.java:17

dev.anvilcraft.lib.v2.rendering.extension.blaze3d.compute.pipeline.bindings.AtomicCounterBinding
dev.anvilcraft.lib.v2.rendering.extension.blaze3d.compute.pipeline.bindings.AtomicCounterBinding.apply(int,com.mojang.blaze3d.buffers.GpuBufferSlice,dev.anvilcraft.lib.v2.rendering.extension.blaze3d.compute.pipeline.ALRComputePass)
EXECUTABLE_REMOVED
✗ binary-breaking
✗ source-breaking

dev/anvilcraft/lib/v2/rendering/extension/blaze3d/compute/pipeline/bindings/ComputeBindingLayout.java

dev.anvilcraft.lib.v2.rendering.extension.blaze3d.compute.pipeline.bindings.AtomicCounterBinding
dev.anvilcraft.lib.v2.rendering.extension.blaze3d.compute.pipeline.bindings.ComputeBindingLayout.apply(int,T,dev.anvilcraft.lib.v2.rendering.extension.blaze3d.compute.pipeline.ALRComputePass)
EXECUTABLE_REMOVED
✗ binary-breaking
✗ source-breaking

dev/anvilcraft/lib/v2/rendering/extension/blaze3d/compute/pipeline/bindings/ComputeBindingLayout.java

dev.anvilcraft.lib.v2.rendering.extension.blaze3d.compute.pipeline.bindings.ComputeBindingLayout
dev.anvilcraft.lib.v2.rendering.extension.blaze3d.compute.pipeline.bindings.ComputeBindingLayout
TYPE_NEW_ABSTRACT_METHOD
✓ binary-compatible
✗ source-breaking

dev/anvilcraft/lib/v2/rendering/extension/blaze3d/compute/pipeline/bindings/ComputeBindingLayout.java

dev.anvilcraft.lib.v2.rendering.extension.blaze3d.compute.pipeline.bindings.ComputeBindingLayout
dev.anvilcraft.lib.v2.rendering.extension.blaze3d.compute.pipeline.bindings.ComputeBindingLayout.apply(int,T,dev.anvilcraft.lib.v2.rendering.extension.blaze3d.compute.pipeline.ALRComputePass)
EXECUTABLE_REMOVED
✗ binary-breaking
✗ source-breaking

dev/anvilcraft/lib/v2/rendering/extension/blaze3d/compute/pipeline/bindings/ComputeBindingLayout.java

dev.anvilcraft.lib.v2.rendering.extension.blaze3d.compute.pipeline.bindings.ImageBinding
dev.anvilcraft.lib.v2.rendering.extension.blaze3d.compute.pipeline.bindings.ComputeBindingLayout.apply(int,T,dev.anvilcraft.lib.v2.rendering.extension.blaze3d.compute.pipeline.ALRComputePass)
EXECUTABLE_REMOVED
✗ binary-breaking
✗ source-breaking

dev/anvilcraft/lib/v2/rendering/extension/blaze3d/compute/pipeline/bindings/ImageBinding.java

dev.anvilcraft.lib.v2.rendering.extension.blaze3d.compute.pipeline.bindings.ImageBinding
dev.anvilcraft.lib.v2.rendering.extension.blaze3d.compute.pipeline.bindings.ImageBinding
TYPE_NEW_ABSTRACT_METHOD
✓ binary-compatible
✗ source-breaking

dev/anvilcraft/lib/v2/rendering/extension/blaze3d/compute/pipeline/bindings/ImageBinding.java:26

dev.anvilcraft.lib.v2.rendering.extension.blaze3d.compute.pipeline.bindings.ImageBinding
dev.anvilcraft.lib.v2.rendering.extension.blaze3d.compute.pipeline.bindings.ImageBinding.apply(int,com.mojang.blaze3d.textures.GpuTexture,dev.anvilcraft.lib.v2.rendering.extension.blaze3d.compute.pipeline.ALRComputePass)
EXECUTABLE_REMOVED
✗ binary-breaking
✗ source-breaking

dev/anvilcraft/lib/v2/rendering/extension/blaze3d/compute/pipeline/bindings/ComputeBindingLayout.java

dev.anvilcraft.lib.v2.rendering.extension.blaze3d.compute.pipeline.bindings.ShaderStorageBinding
dev.anvilcraft.lib.v2.rendering.extension.blaze3d.compute.pipeline.bindings.ComputeBindingLayout.apply(int,T,dev.anvilcraft.lib.v2.rendering.extension.blaze3d.compute.pipeline.ALRComputePass)
EXECUTABLE_REMOVED
✗ binary-breaking
✗ source-breaking

dev/anvilcraft/lib/v2/rendering/extension/blaze3d/compute/pipeline/bindings/ShaderStorageBinding.java

dev.anvilcraft.lib.v2.rendering.extension.blaze3d.compute.pipeline.bindings.ShaderStorageBinding
dev.anvilcraft.lib.v2.rendering.extension.blaze3d.compute.pipeline.bindings.ShaderStorageBinding
TYPE_NEW_ABSTRACT_METHOD
✓ binary-compatible
✗ source-breaking

dev/anvilcraft/lib/v2/rendering/extension/blaze3d/compute/pipeline/bindings/ShaderStorageBinding.java:18

dev.anvilcraft.lib.v2.rendering.extension.blaze3d.compute.pipeline.bindings.ShaderStorageBinding
dev.anvilcraft.lib.v2.rendering.extension.blaze3d.compute.pipeline.bindings.ShaderStorageBinding.apply(int,com.mojang.blaze3d.buffers.GpuBufferSlice,dev.anvilcraft.lib.v2.rendering.extension.blaze3d.compute.pipeline.ALRComputePass)
EXECUTABLE_REMOVED
✗ binary-breaking
✗ source-breaking

dev/anvilcraft/lib/v2/rendering/extension/blaze3d/compute/pipeline/bindings/ComputeBindingLayout.java

dev.anvilcraft.lib.v2.rendering.extension.blaze3d.compute.pipeline.bindings.TextureBinding
dev.anvilcraft.lib.v2.rendering.extension.blaze3d.compute.pipeline.bindings.ComputeBindingLayout.apply(int,T,dev.anvilcraft.lib.v2.rendering.extension.blaze3d.compute.pipeline.ALRComputePass)
EXECUTABLE_REMOVED
✗ binary-breaking
✗ source-breaking

dev/anvilcraft/lib/v2/rendering/extension/blaze3d/compute/pipeline/bindings/TextureBinding.java

dev.anvilcraft.lib.v2.rendering.extension.blaze3d.compute.pipeline.bindings.TextureBinding
dev.anvilcraft.lib.v2.rendering.extension.blaze3d.compute.pipeline.bindings.TextureBinding
TYPE_NEW_ABSTRACT_METHOD
✓ binary-compatible
✗ source-breaking

dev/anvilcraft/lib/v2/rendering/extension/blaze3d/compute/pipeline/bindings/TextureBinding.java:18

dev.anvilcraft.lib.v2.rendering.extension.blaze3d.compute.pipeline.bindings.TextureBinding
dev.anvilcraft.lib.v2.rendering.extension.blaze3d.compute.pipeline.bindings.TextureBinding.apply(int,dev.anvilcraft.lib.v2.rendering.extension.blaze3d.compute.pipeline.bindings.TextureBinding$SamplerAndTexture,dev.anvilcraft.lib.v2.rendering.extension.blaze3d.compute.pipeline.ALRComputePass)
EXECUTABLE_REMOVED
✗ binary-breaking
✗ source-breaking

dev/anvilcraft/lib/v2/rendering/extension/blaze3d/compute/pipeline/bindings/ComputeBindingLayout.java

dev.anvilcraft.lib.v2.rendering.extension.blaze3d.compute.pipeline.bindings.UniformBlockBinding
dev.anvilcraft.lib.v2.rendering.extension.blaze3d.compute.pipeline.bindings.ComputeBindingLayout.apply(int,T,dev.anvilcraft.lib.v2.rendering.extension.blaze3d.compute.pipeline.ALRComputePass)
EXECUTABLE_REMOVED
✗ binary-breaking
✗ source-breaking

dev/anvilcraft/lib/v2/rendering/extension/blaze3d/compute/pipeline/bindings/UniformBlockBinding.java

dev.anvilcraft.lib.v2.rendering.extension.blaze3d.compute.pipeline.bindings.UniformBlockBinding
dev.anvilcraft.lib.v2.rendering.extension.blaze3d.compute.pipeline.bindings.UniformBlockBinding
TYPE_NEW_ABSTRACT_METHOD
✓ binary-compatible
✗ source-breaking

dev/anvilcraft/lib/v2/rendering/extension/blaze3d/compute/pipeline/bindings/UniformBlockBinding.java:17

dev.anvilcraft.lib.v2.rendering.extension.blaze3d.compute.pipeline.bindings.UniformBlockBinding
dev.anvilcraft.lib.v2.rendering.extension.blaze3d.compute.pipeline.bindings.UniformBlockBinding.apply(int,com.mojang.blaze3d.buffers.GpuBufferSlice,dev.anvilcraft.lib.v2.rendering.extension.blaze3d.compute.pipeline.ALRComputePass)
EXECUTABLE_REMOVED
✗ binary-breaking
✗ source-breaking

dev/anvilcraft/lib/v2/rendering/extension/blaze3d/compute/shader/ALRComputeProgramInstance.java

dev.anvilcraft.lib.v2.rendering.extension.blaze3d.compute.shader.ALRComputeProgramInstance
dev.anvilcraft.lib.v2.rendering.extension.blaze3d.compute.shader.ALRComputeProgramInstance
TYPE_KIND_CHANGED
✗ binary-breaking
✗ source-breaking

dev/anvilcraft/lib/v2/rendering/extension/blaze3d/compute/shader/ShaderResourceType.java

dev.anvilcraft.lib.v2.rendering.extension.blaze3d.compute.shader.ShaderResourceType
dev.anvilcraft.lib.v2.rendering.extension.blaze3d.compute.shader.ShaderResourceType.IMAGE
FIELD_REMOVED
✗ binary-breaking
✗ source-breaking

dev/anvilcraft/lib/v2/rendering/extension/blaze3d/compute/shader/ShaderResourceType.java

dev.anvilcraft.lib.v2.rendering.extension.blaze3d.compute.shader.ShaderResourceType
dev.anvilcraft.lib.v2.rendering.extension.blaze3d.compute.shader.ShaderResourceType.TEXTURE
FIELD_REMOVED
✗ binary-breaking
✗ source-breaking

dev/anvilcraft/lib/v2/rendering/foundation/buffers/layout/BufferSizeCalculator.java

dev.anvilcraft.lib.v2.rendering.foundation.buffers.layout.BufferSizeCalculator
dev.anvilcraft.lib.v2.rendering.foundation.buffers.layout.BufferSizeCalculator
TYPE_NEW_ABSTRACT_METHOD
✓ binary-compatible
✗ source-breaking

dev/anvilcraft/lib/v2/rendering/foundation/buffers/layout/BufferSizeCalculator.java

dev.anvilcraft.lib.v2.rendering.foundation.buffers.layout.BufferSizeCalculator
dev.anvilcraft.lib.v2.rendering.foundation.buffers.layout.BufferSizeCalculator
TYPE_NEW_ABSTRACT_METHOD
✓ binary-compatible
✗ source-breaking

dev/anvilcraft/lib/v2/rendering/foundation/buffers/layout/BufferWriter.java

dev.anvilcraft.lib.v2.rendering.foundation.buffers.layout.BufferWriter
dev.anvilcraft.lib.v2.rendering.foundation.buffers.layout.BufferWriter
TYPE_NEW_ABSTRACT_METHOD
✓ binary-compatible
✗ source-breaking

dev/anvilcraft/lib/v2/rendering/foundation/buffers/layout/BufferWriter.java

dev.anvilcraft.lib.v2.rendering.foundation.buffers.layout.BufferWriter
dev.anvilcraft.lib.v2.rendering.foundation.buffers.layout.BufferWriter
TYPE_NEW_ABSTRACT_METHOD
✓ binary-compatible
✗ source-breaking

dev/anvilcraft/lib/v2/rendering/foundation/buffers/layout/BufferWriter.java

dev.anvilcraft.lib.v2.rendering.foundation.buffers.layout.BufferWriter
dev.anvilcraft.lib.v2.rendering.foundation.buffers.layout.BufferWriter
TYPE_NEW_ABSTRACT_METHOD
✓ binary-compatible
✗ source-breaking

dev/anvilcraft/lib/v2/rendering/foundation/buffers/layout/BufferWriter.java

dev.anvilcraft.lib.v2.rendering.foundation.buffers.layout.BufferWriter
dev.anvilcraft.lib.v2.rendering.foundation.buffers.layout.BufferWriter
TYPE_NEW_ABSTRACT_METHOD
✓ binary-compatible
✗ source-breaking

dev/anvilcraft/lib/v2/rendering/foundation/buffers/layout/BufferWriter.java:38

dev.anvilcraft.lib.v2.rendering.foundation.buffers.layout.BufferWriter
dev.anvilcraft.lib.v2.rendering.foundation.buffers.layout.BufferWriter.putStructArray(E[],dev.anvilcraft.lib.v2.rendering.foundation.buffers.object.BufferObjectLayoutDefinition<E>)
EXECUTABLE_REMOVED
✗ binary-breaking
✗ source-breaking

dev/anvilcraft/lib/v2/rendering/foundation/buffers/layout/std140/Std140Writer.java:106

dev.anvilcraft.lib.v2.rendering.foundation.buffers.layout.std140.Std140Writer
dev.anvilcraft.lib.v2.rendering.foundation.buffers.layout.std140.Std140Writer.putStructArray(E[],dev.anvilcraft.lib.v2.rendering.foundation.buffers.object.BufferObjectLayoutDefinition<E>)
EXECUTABLE_REMOVED
✗ binary-breaking
✗ source-breaking

Full CSVs: see the Artifacts section of this workflow run.

@Gugle2308

Copy link
Copy Markdown

⚠️ Dangerous command requires approval:

cd /tmp; cat > ext.sh <<'EOF'
#!/bin/bash
# usage: ext.sh <file-suffix> <diff-file>
F="$1"; D="${2:-/tmp/pr95.diff"
}"
H=$(mktemp)
grep -n "^diff --git" "$D" > "$H"
START=$(grep -n "^diff --git" "$D" ...

Reason: shell execution via heredoc

Reply /approve to execute, /approve session to approve this pattern for the session, /approve always to approve permanently, or /deny to cancel.

@Gugle2308

Copy link
Copy Markdown

🌿 Roseau API Breaking Change Report

Module Status Breaking Changes
codec ✅ Compatible 0
collision ✅ Compatible 0
config ✅ Compatible 0
integration ✅ Compatible 0
moveable-entity-block ✅ Compatible 0
network ✅ Compatible 0
rendering 🔴 BC detected 44
space-select ✅ Compatible 0
font ✅ Compatible 0
util ✅ Compatible 0
explosion ✅ Compatible 0
rpc ✅ Compatible 0
multiblock ✅ Compatible 0
recipe ✅ Compatible 0
registrum ✅ Compatible 0
sync ✅ Compatible 0
wheel ✅ Compatible 0
main ✅ Compatible 0

🔴 rendering — 44 breaking change(s)

dev/anvilcraft/lib/v2/rendering/extension/blaze3d/ALRGpuDeviceExtension.java

dev.anvilcraft.lib.v2.rendering.extension.blaze3d.ALRGpuDeviceExtension
dev.anvilcraft.lib.v2.rendering.extension.blaze3d.ALRGpuDeviceExtension
TYPE_NEW_ABSTRACT_METHOD
✓ binary-compatible
✗ source-breaking

dev/anvilcraft/lib/v2/rendering/extension/blaze3d/ALRGpuDeviceExtension.java

dev.anvilcraft.lib.v2.rendering.extension.blaze3d.ALRGpuDeviceExtension
dev.anvilcraft.lib.v2.rendering.extension.blaze3d.ALRGpuDeviceExtension
TYPE_NEW_ABSTRACT_METHOD
✓ binary-compatible
✗ source-breaking

dev/anvilcraft/lib/v2/rendering/extension/blaze3d/ALRGpuDeviceExtension.java

dev.anvilcraft.lib.v2.rendering.extension.blaze3d.ALRGpuDeviceExtension
dev.anvilcraft.lib.v2.rendering.extension.blaze3d.ALRGpuDeviceExtension
TYPE_NEW_ABSTRACT_METHOD
✓ binary-compatible
✗ source-breaking

dev/anvilcraft/lib/v2/rendering/extension/blaze3d/ALRGpuDeviceExtension.java

dev.anvilcraft.lib.v2.rendering.extension.blaze3d.ALRGpuDeviceExtension
dev.anvilcraft.lib.v2.rendering.extension.blaze3d.ALRGpuDeviceExtension
TYPE_NEW_ABSTRACT_METHOD
✓ binary-compatible
✗ source-breaking

dev/anvilcraft/lib/v2/rendering/extension/blaze3d/ALRGpuDeviceExtension.java

dev.anvilcraft.lib.v2.rendering.extension.blaze3d.ALRGpuDeviceExtension
dev.anvilcraft.lib.v2.rendering.extension.blaze3d.ALRGpuDeviceExtension
TYPE_NEW_ABSTRACT_METHOD
✓ binary-compatible
✗ source-breaking

dev/anvilcraft/lib/v2/rendering/extension/blaze3d/ALRGpuDeviceExtension.java

dev.anvilcraft.lib.v2.rendering.extension.blaze3d.ALRGpuDeviceExtension
dev.anvilcraft.lib.v2.rendering.extension.blaze3d.ALRGpuDeviceExtension
TYPE_NEW_ABSTRACT_METHOD
✓ binary-compatible
✗ source-breaking

dev/anvilcraft/lib/v2/rendering/extension/blaze3d/ALRGpuDeviceExtension.java

dev.anvilcraft.lib.v2.rendering.extension.blaze3d.ALRGpuDeviceExtension
dev.anvilcraft.lib.v2.rendering.extension.blaze3d.ALRGpuDeviceExtension
TYPE_NEW_ABSTRACT_METHOD
✓ binary-compatible
✗ source-breaking

dev/anvilcraft/lib/v2/rendering/extension/blaze3d/ALRGpuDeviceExtension.java

dev.anvilcraft.lib.v2.rendering.extension.blaze3d.ALRGpuDeviceExtension
dev.anvilcraft.lib.v2.rendering.extension.blaze3d.ALRGpuDeviceExtension
TYPE_NEW_ABSTRACT_METHOD
✓ binary-compatible
✗ source-breaking

dev/anvilcraft/lib/v2/rendering/extension/blaze3d/ALRGpuDeviceExtension.java

dev.anvilcraft.lib.v2.rendering.extension.blaze3d.ALRGpuDeviceExtension
dev.anvilcraft.lib.v2.rendering.extension.blaze3d.ALRGpuDeviceExtension.alrCompileComputeShader(dev.anvilcraft.lib.v2.rendering.extension.blaze3d.compute.shader.ALRComputeProgramInstanceKey)
EXECUTABLE_REMOVED
✗ binary-breaking
✗ source-breaking

dev/anvilcraft/lib/v2/rendering/extension/blaze3d/compute/pipeline/ALRComputePass.java:66

dev.anvilcraft.lib.v2.rendering.extension.blaze3d.compute.pipeline.ALRComputePass
dev.anvilcraft.lib.v2.rendering.extension.blaze3d.compute.pipeline.ALRComputePass.bind(int,dev.anvilcraft.lib.v2.rendering.extension.blaze3d.compute.pipeline.bindings.ComputeBindingLayout<T>,T)
METHOD_RETURN_TYPE_ERASURE_CHANGED
✗ binary-breaking
✓ source-compatible

dev/anvilcraft/lib/v2/rendering/extension/blaze3d/compute/pipeline/ALRComputePass.java:66

dev.anvilcraft.lib.v2.rendering.extension.blaze3d.compute.pipeline.ALRComputePass
dev.anvilcraft.lib.v2.rendering.extension.blaze3d.compute.pipeline.ALRComputePass.bind(int,dev.anvilcraft.lib.v2.rendering.extension.blaze3d.compute.pipeline.bindings.ComputeBindingLayout<T>,T)
METHOD_RETURN_TYPE_CHANGED_INCOMPATIBLE
✓ binary-compatible
✗ source-breaking

dev/anvilcraft/lib/v2/rendering/extension/blaze3d/compute/pipeline/ALRComputePass.java:59

dev.anvilcraft.lib.v2.rendering.extension.blaze3d.compute.pipeline.ALRComputePass
dev.anvilcraft.lib.v2.rendering.extension.blaze3d.compute.pipeline.ALRComputePass.bindAll(java.util.List<? extends java.lang.Object>)
EXECUTABLE_REMOVED
✗ binary-breaking
✗ source-breaking

dev/anvilcraft/lib/v2/rendering/extension/blaze3d/compute/pipeline/ALRComputePass.java:24

dev.anvilcraft.lib.v2.rendering.extension.blaze3d.compute.pipeline.ALRComputePass
dev.anvilcraft.lib.v2.rendering.extension.blaze3d.compute.pipeline.ALRComputePass.popDebugGroup(java.lang.String)
EXECUTABLE_REMOVED
✗ binary-breaking
✗ source-breaking

dev/anvilcraft/lib/v2/rendering/extension/blaze3d/compute/pipeline/ALRComputePass.java:20

dev.anvilcraft.lib.v2.rendering.extension.blaze3d.compute.pipeline.ALRComputePass
dev.anvilcraft.lib.v2.rendering.extension.blaze3d.compute.pipeline.ALRComputePass.pushDebugGroup(java.lang.String)
EXECUTABLE_REMOVED
✗ binary-breaking
✗ source-breaking

dev/anvilcraft/lib/v2/rendering/extension/blaze3d/compute/pipeline/ALRComputePassBackend.java

dev.anvilcraft.lib.v2.rendering.extension.blaze3d.compute.pipeline.ALRComputePassBackend
dev.anvilcraft.lib.v2.rendering.extension.blaze3d.compute.pipeline.ALRComputePassBackend.pushDebugGroup(java.lang.String)
EXECUTABLE_REMOVED
✗ binary-breaking
✗ source-breaking

dev/anvilcraft/lib/v2/rendering/extension/blaze3d/compute/pipeline/ALRComputePipeline.java

dev.anvilcraft.lib.v2.rendering.extension.blaze3d.compute.pipeline.ALRComputePipeline
dev.anvilcraft.lib.v2.rendering.extension.blaze3d.compute.pipeline.ALRComputePipeline
TYPE_KIND_CHANGED
✗ binary-breaking
✗ source-breaking

dev/anvilcraft/lib/v2/rendering/extension/blaze3d/compute/pipeline/bindings/AtomicCounterBinding.java

dev.anvilcraft.lib.v2.rendering.extension.blaze3d.compute.pipeline.bindings.AtomicCounterBinding
dev.anvilcraft.lib.v2.rendering.extension.blaze3d.compute.pipeline.bindings.AtomicCounterBinding
TYPE_NEW_ABSTRACT_METHOD
✓ binary-compatible
✗ source-breaking

dev/anvilcraft/lib/v2/rendering/extension/blaze3d/compute/pipeline/bindings/AtomicCounterBinding.java:17

dev.anvilcraft.lib.v2.rendering.extension.blaze3d.compute.pipeline.bindings.AtomicCounterBinding
dev.anvilcraft.lib.v2.rendering.extension.blaze3d.compute.pipeline.bindings.AtomicCounterBinding.apply(int,com.mojang.blaze3d.buffers.GpuBufferSlice,dev.anvilcraft.lib.v2.rendering.extension.blaze3d.compute.pipeline.ALRComputePass)
EXECUTABLE_REMOVED
✗ binary-breaking
✗ source-breaking

dev/anvilcraft/lib/v2/rendering/extension/blaze3d/compute/pipeline/bindings/ComputeBindingLayout.java

dev.anvilcraft.lib.v2.rendering.extension.blaze3d.compute.pipeline.bindings.AtomicCounterBinding
dev.anvilcraft.lib.v2.rendering.extension.blaze3d.compute.pipeline.bindings.ComputeBindingLayout.apply(int,T,dev.anvilcraft.lib.v2.rendering.extension.blaze3d.compute.pipeline.ALRComputePass)
EXECUTABLE_REMOVED
✗ binary-breaking
✗ source-breaking

dev/anvilcraft/lib/v2/rendering/extension/blaze3d/compute/pipeline/bindings/ComputeBindingLayout.java

dev.anvilcraft.lib.v2.rendering.extension.blaze3d.compute.pipeline.bindings.ComputeBindingLayout
dev.anvilcraft.lib.v2.rendering.extension.blaze3d.compute.pipeline.bindings.ComputeBindingLayout
TYPE_NEW_ABSTRACT_METHOD
✓ binary-compatible
✗ source-breaking

dev/anvilcraft/lib/v2/rendering/extension/blaze3d/compute/pipeline/bindings/ComputeBindingLayout.java

dev.anvilcraft.lib.v2.rendering.extension.blaze3d.compute.pipeline.bindings.ComputeBindingLayout
dev.anvilcraft.lib.v2.rendering.extension.blaze3d.compute.pipeline.bindings.ComputeBindingLayout.apply(int,T,dev.anvilcraft.lib.v2.rendering.extension.blaze3d.compute.pipeline.ALRComputePass)
EXECUTABLE_REMOVED
✗ binary-breaking
✗ source-breaking

dev/anvilcraft/lib/v2/rendering/extension/blaze3d/compute/pipeline/bindings/ComputeBindingLayout.java

dev.anvilcraft.lib.v2.rendering.extension.blaze3d.compute.pipeline.bindings.ImageBinding
dev.anvilcraft.lib.v2.rendering.extension.blaze3d.compute.pipeline.bindings.ComputeBindingLayout.apply(int,T,dev.anvilcraft.lib.v2.rendering.extension.blaze3d.compute.pipeline.ALRComputePass)
EXECUTABLE_REMOVED
✗ binary-breaking
✗ source-breaking

dev/anvilcraft/lib/v2/rendering/extension/blaze3d/compute/pipeline/bindings/ImageBinding.java

dev.anvilcraft.lib.v2.rendering.extension.blaze3d.compute.pipeline.bindings.ImageBinding
dev.anvilcraft.lib.v2.rendering.extension.blaze3d.compute.pipeline.bindings.ImageBinding
TYPE_NEW_ABSTRACT_METHOD
✓ binary-compatible
✗ source-breaking

dev/anvilcraft/lib/v2/rendering/extension/blaze3d/compute/pipeline/bindings/ImageBinding.java:26

dev.anvilcraft.lib.v2.rendering.extension.blaze3d.compute.pipeline.bindings.ImageBinding
dev.anvilcraft.lib.v2.rendering.extension.blaze3d.compute.pipeline.bindings.ImageBinding.apply(int,com.mojang.blaze3d.textures.GpuTexture,dev.anvilcraft.lib.v2.rendering.extension.blaze3d.compute.pipeline.ALRComputePass)
EXECUTABLE_REMOVED
✗ binary-breaking
✗ source-breaking

dev/anvilcraft/lib/v2/rendering/extension/blaze3d/compute/pipeline/bindings/ComputeBindingLayout.java

dev.anvilcraft.lib.v2.rendering.extension.blaze3d.compute.pipeline.bindings.ShaderStorageBinding
dev.anvilcraft.lib.v2.rendering.extension.blaze3d.compute.pipeline.bindings.ComputeBindingLayout.apply(int,T,dev.anvilcraft.lib.v2.rendering.extension.blaze3d.compute.pipeline.ALRComputePass)
EXECUTABLE_REMOVED
✗ binary-breaking
✗ source-breaking

dev/anvilcraft/lib/v2/rendering/extension/blaze3d/compute/pipeline/bindings/ShaderStorageBinding.java

dev.anvilcraft.lib.v2.rendering.extension.blaze3d.compute.pipeline.bindings.ShaderStorageBinding
dev.anvilcraft.lib.v2.rendering.extension.blaze3d.compute.pipeline.bindings.ShaderStorageBinding
TYPE_NEW_ABSTRACT_METHOD
✓ binary-compatible
✗ source-breaking

dev/anvilcraft/lib/v2/rendering/extension/blaze3d/compute/pipeline/bindings/ShaderStorageBinding.java:18

dev.anvilcraft.lib.v2.rendering.extension.blaze3d.compute.pipeline.bindings.ShaderStorageBinding
dev.anvilcraft.lib.v2.rendering.extension.blaze3d.compute.pipeline.bindings.ShaderStorageBinding.apply(int,com.mojang.blaze3d.buffers.GpuBufferSlice,dev.anvilcraft.lib.v2.rendering.extension.blaze3d.compute.pipeline.ALRComputePass)
EXECUTABLE_REMOVED
✗ binary-breaking
✗ source-breaking

dev/anvilcraft/lib/v2/rendering/extension/blaze3d/compute/pipeline/bindings/ComputeBindingLayout.java

dev.anvilcraft.lib.v2.rendering.extension.blaze3d.compute.pipeline.bindings.TextureBinding
dev.anvilcraft.lib.v2.rendering.extension.blaze3d.compute.pipeline.bindings.ComputeBindingLayout.apply(int,T,dev.anvilcraft.lib.v2.rendering.extension.blaze3d.compute.pipeline.ALRComputePass)
EXECUTABLE_REMOVED
✗ binary-breaking
✗ source-breaking

dev/anvilcraft/lib/v2/rendering/extension/blaze3d/compute/pipeline/bindings/TextureBinding.java

dev.anvilcraft.lib.v2.rendering.extension.blaze3d.compute.pipeline.bindings.TextureBinding
dev.anvilcraft.lib.v2.rendering.extension.blaze3d.compute.pipeline.bindings.TextureBinding
TYPE_NEW_ABSTRACT_METHOD
✓ binary-compatible
✗ source-breaking

dev/anvilcraft/lib/v2/rendering/extension/blaze3d/compute/pipeline/bindings/TextureBinding.java:18

dev.anvilcraft.lib.v2.rendering.extension.blaze3d.compute.pipeline.bindings.TextureBinding
dev.anvilcraft.lib.v2.rendering.extension.blaze3d.compute.pipeline.bindings.TextureBinding.apply(int,dev.anvilcraft.lib.v2.rendering.extension.blaze3d.compute.pipeline.bindings.TextureBinding$SamplerAndTexture,dev.anvilcraft.lib.v2.rendering.extension.blaze3d.compute.pipeline.ALRComputePass)
EXECUTABLE_REMOVED
✗ binary-breaking
✗ source-breaking

dev/anvilcraft/lib/v2/rendering/extension/blaze3d/compute/pipeline/bindings/ComputeBindingLayout.java

dev.anvilcraft.lib.v2.rendering.extension.blaze3d.compute.pipeline.bindings.UniformBlockBinding
dev.anvilcraft.lib.v2.rendering.extension.blaze3d.compute.pipeline.bindings.ComputeBindingLayout.apply(int,T,dev.anvilcraft.lib.v2.rendering.extension.blaze3d.compute.pipeline.ALRComputePass)
EXECUTABLE_REMOVED
✗ binary-breaking
✗ source-breaking

dev/anvilcraft/lib/v2/rendering/extension/blaze3d/compute/pipeline/bindings/UniformBlockBinding.java

dev.anvilcraft.lib.v2.rendering.extension.blaze3d.compute.pipeline.bindings.UniformBlockBinding
dev.anvilcraft.lib.v2.rendering.extension.blaze3d.compute.pipeline.bindings.UniformBlockBinding
TYPE_NEW_ABSTRACT_METHOD
✓ binary-compatible
✗ source-breaking

dev/anvilcraft/lib/v2/rendering/extension/blaze3d/compute/pipeline/bindings/UniformBlockBinding.java:17

dev.anvilcraft.lib.v2.rendering.extension.blaze3d.compute.pipeline.bindings.UniformBlockBinding
dev.anvilcraft.lib.v2.rendering.extension.blaze3d.compute.pipeline.bindings.UniformBlockBinding.apply(int,com.mojang.blaze3d.buffers.GpuBufferSlice,dev.anvilcraft.lib.v2.rendering.extension.blaze3d.compute.pipeline.ALRComputePass)
EXECUTABLE_REMOVED
✗ binary-breaking
✗ source-breaking

dev/anvilcraft/lib/v2/rendering/extension/blaze3d/compute/shader/ALRComputeProgramInstance.java

dev.anvilcraft.lib.v2.rendering.extension.blaze3d.compute.shader.ALRComputeProgramInstance
dev.anvilcraft.lib.v2.rendering.extension.blaze3d.compute.shader.ALRComputeProgramInstance
TYPE_KIND_CHANGED
✗ binary-breaking
✗ source-breaking

dev/anvilcraft/lib/v2/rendering/extension/blaze3d/compute/shader/ShaderResourceType.java

dev.anvilcraft.lib.v2.rendering.extension.blaze3d.compute.shader.ShaderResourceType
dev.anvilcraft.lib.v2.rendering.extension.blaze3d.compute.shader.ShaderResourceType.IMAGE
FIELD_REMOVED
✗ binary-breaking
✗ source-breaking

dev/anvilcraft/lib/v2/rendering/extension/blaze3d/compute/shader/ShaderResourceType.java

dev.anvilcraft.lib.v2.rendering.extension.blaze3d.compute.shader.ShaderResourceType
dev.anvilcraft.lib.v2.rendering.extension.blaze3d.compute.shader.ShaderResourceType.TEXTURE
FIELD_REMOVED
✗ binary-breaking
✗ source-breaking

dev/anvilcraft/lib/v2/rendering/foundation/buffers/layout/BufferSizeCalculator.java

dev.anvilcraft.lib.v2.rendering.foundation.buffers.layout.BufferSizeCalculator
dev.anvilcraft.lib.v2.rendering.foundation.buffers.layout.BufferSizeCalculator
TYPE_NEW_ABSTRACT_METHOD
✓ binary-compatible
✗ source-breaking

dev/anvilcraft/lib/v2/rendering/foundation/buffers/layout/BufferSizeCalculator.java

dev.anvilcraft.lib.v2.rendering.foundation.buffers.layout.BufferSizeCalculator
dev.anvilcraft.lib.v2.rendering.foundation.buffers.layout.BufferSizeCalculator
TYPE_NEW_ABSTRACT_METHOD
✓ binary-compatible
✗ source-breaking

dev/anvilcraft/lib/v2/rendering/foundation/buffers/layout/BufferWriter.java

dev.anvilcraft.lib.v2.rendering.foundation.buffers.layout.BufferWriter
dev.anvilcraft.lib.v2.rendering.foundation.buffers.layout.BufferWriter
TYPE_NEW_ABSTRACT_METHOD
✓ binary-compatible
✗ source-breaking

dev/anvilcraft/lib/v2/rendering/foundation/buffers/layout/BufferWriter.java

dev.anvilcraft.lib.v2.rendering.foundation.buffers.layout.BufferWriter
dev.anvilcraft.lib.v2.rendering.foundation.buffers.layout.BufferWriter
TYPE_NEW_ABSTRACT_METHOD
✓ binary-compatible
✗ source-breaking

dev/anvilcraft/lib/v2/rendering/foundation/buffers/layout/BufferWriter.java

dev.anvilcraft.lib.v2.rendering.foundation.buffers.layout.BufferWriter
dev.anvilcraft.lib.v2.rendering.foundation.buffers.layout.BufferWriter
TYPE_NEW_ABSTRACT_METHOD
✓ binary-compatible
✗ source-breaking

dev/anvilcraft/lib/v2/rendering/foundation/buffers/layout/BufferWriter.java

dev.anvilcraft.lib.v2.rendering.foundation.buffers.layout.BufferWriter
dev.anvilcraft.lib.v2.rendering.foundation.buffers.layout.BufferWriter
TYPE_NEW_ABSTRACT_METHOD
✓ binary-compatible
✗ source-breaking

dev/anvilcraft/lib/v2/rendering/foundation/buffers/layout/BufferWriter.java:38

dev.anvilcraft.lib.v2.rendering.foundation.buffers.layout.BufferWriter
dev.anvilcraft.lib.v2.rendering.foundation.buffers.layout.BufferWriter.putStructArray(E[],dev.anvilcraft.lib.v2.rendering.foundation.buffers.object.BufferObjectLayoutDefinition<E>)
EXECUTABLE_REMOVED
✗ binary-breaking
✗ source-breaking

dev/anvilcraft/lib/v2/rendering/foundation/buffers/layout/std140/Std140Writer.java:106

dev.anvilcraft.lib.v2.rendering.foundation.buffers.layout.std140.Std140Writer
dev.anvilcraft.lib.v2.rendering.foundation.buffers.layout.std140.Std140Writer.putStructArray(E[],dev.anvilcraft.lib.v2.rendering.foundation.buffers.object.BufferObjectLayoutDefinition<E>)
EXECUTABLE_REMOVED
✗ binary-breaking
✗ source-breaking

Full CSVs: see the Artifacts section of this workflow run.

@Gugle2308

Copy link
Copy Markdown

审查完成。以下是审查意见(将自动发布到 PR #95 评论区)。


代码审查摘要 — PR #95

操作: synchronize(分支 feat/occusion_cullingdev/26.1,head d76bccc
范围: 174 个文件(156 Java,86 新增,0 删除)/ 10,033 行 diff / 30 commits
与基线关系: merge-base = aa123c92,目标分支仅领先 1 个 commit(module.wheel),无重叠文件,无需 rebase


✅ 绑定/着色器交叉验证(本 PR 核心,逐条核对通过)

我把 Java 端 bind* 的 binding point 与着色器里的 layout(binding=N) 全部做了交叉验证,生产代码全部一致

Pass 着色器声明 Java 调用 结论
depth_convert.csh ConvertParam=0(UBO)/Input=1(tex)/Output=2(img) DepthTexConverter:UBO 0 / tex 1 / img 2
hiz_occlusion_test.csh CB=0/ShaderInput=0/ShaderOutput=1/uInputs img=0 HierarchicalZOcclusionCuller:UBO 0 / SSBO 0,1 / imageArray 0
ffx_spd_downsample_pass.csh cbFSR1=0/atomic=0/mid_mip img=1/mips img=2 SinglePassDownsampler:UBO 0 / SSBO 0 / img 1 / arr 2
MAX_MIP_LEVELS 12(着色器) uInputs[13] MIP_LAYER_COUNT = 12+1 = 13、pipeline withArrayOfImage(...,13) ✅ 三处自洽
bindless withBindlessArrayOfImage("rw_..._mips") / ("uInputs") bindBindlessImageArray("同名") 按名解析 ✅ 名称精确匹配
OCCLUSION_QUERY pipeline WRITE_NONE + DepthStencilState(LESS_THAN_EQUAL, false) ✅ 只读深度、不写颜色/深度

顶点/矩阵约定也正确:occlusion_query.vshProjMat * CameraViewMat * ModelViewMatQueryInstance.prepareTransformviewRotationMatrix + 相机相对平移 + translate(min)·scale(size)(单位立方体映射到 AABB,DEFAULT_VERTEX_BUFFER_SIZE = 3*4*4*6 = 288 与实际 24 顶点 × POSITION(12B) 完全吻合);getBuffer(6*6) + drawIndexed(0,0,36,1) 与 6 个 QUADS 一致。

🔴 关键

  1. module.test/.../test/client/compute/ComputeSupport.java computeBlur() — 绑定目标写错(bindAll 机械翻译事故)
    pass.setPipeline(TestPipelines.BLUR);
    pass.bindShaderStorage(0, addInputSSBO.slice());   // ❌ 应为 bindUniformBlock(0, blurParamUBO.slice())
    pass.bindTexture(1, new TextureBinding.SamplerAndTexture(theSampler, colorTexture));
    pass.bindImage(2, outputTexture, false, true);
    TestPipelines.BLUR 声明顺序为 withUniformBlock("BlurParam")(0) → withTexture("InTexture")(1) → withWriteOnlyImage("OutImage")(2)。改前是 bindAll(List.of(blurParamUBO.slice(), ...));改后 把 ADD 用例的 addInputSSBO 当成绑定 0 的 SSBO 绑了进去blurParamUBO 虽然 upload() 了却从未绑定 → 着色器读到未绑定/垃圾 width/height,blur 结果错误(绑定点类型也错了,UBO vs SSBO 是两个命名空间)。
    这是本次「显式绑定」重构里唯一一处翻译错误,但它恰好是被其它 mod 当作范例抄的测试模块代码,建议修复并顺手加一条与 add() 相同的 counter 断言。

⚠️ 警告

  1. foundation/buffers/... 之外引入 util/MemoryAccess.javasun.misc.Unsafe + LWJGL 内部 JNINativeInterface.NewDirectByteBufferGlSamplesQuery.getValue()SinglePassDownsampler:208 是唯二调用点,两处都有公开 LWJGL API 可替代:

    • GlSamplesQuery:直接 stack.mallocInt(1); glGetQueryObjectuiv(id, GL_QUERY_RESULT, stack); return stack.getInt(0);(当前用 nmalloc(4) + Unsafe 读裸地址)
    • SinglePassDownsamplerMemoryUtil.memSet(MemoryUtil.memAddress(buffer), 0, size)(或 memSet(ByteBuffer, int)
      sun.misc.Unsafe 内存访问方法在 JDK 24+ 首次使用即告警、后续版本默认 deny 会直接抛 UnsupportedOperationException(代码里已经用 @SuppressWarnings("removal") 承认了这一点)。作为要给别的 mod 用的库,这是一条可避免的 JDK 版本兼容地雷。
  2. GlComputePassBackend.setupState() 语义由「静默跳过」变为「抛异常」

    if (program == null || program == PROGRAM.INVALID) throw new IllegalStateException("dispatching compute using a invalid program");

    调用链是 Hi-Z processFeatures → SubmitCustomGeometryEvent(LOWEST),即异常会直接穿透到关卡渲染路径 → 崩游戏。计算着色器由 ALRComputeShaderManager 在资源重载时异步编译,建议保留 fail-fast 但降级为「记日志 + 本次 pass 跳过」或至少限定在非重载期抛出。

  3. module.gradle clientIrisWorkaround run config

    • 新增了重复行 systemProperty('neoforge.enabledGameTestNamespaces', project.mod_id)(原本已有一行)
    • 删除了 systemProperty("neoforge.disableGlValidation", "true") —— 所有开发者的 GL 校验被重新打开,是行为变更,请确认是有意的
    • 把调试用参数硬编码进共享 run config:alrTextureDebugClear=true(会让每个开发者每次启动都开启纹理 debug clear)、--renderDebugLabels-XX:+UseParallelGC-XX:+UnlockDiagnosticVMOptions-XX:+DebugNonSafepoints。建议改为 -P property 开关,避免污染他人开发环境。
  4. 静态/全局状态跨 GPU device 生命周期存活

    • QueryInstance.CreationContext.vertexBufferstaticGpuBuffer(注释写「should keep alive when game running」)——device 重建后会拿旧 device 的 buffer 使用
    • GpuQueryOcclusionCuller.close()空实现DynamicUniformStorage 512×192B、query 池、CommandEncoder 都不释放),HierarchicalZOcclusionCuller.close() 也不释放 downsampler/converter/staging
    • ALROptimizations.create() 可直接替换单例,旧实例不会被 close(),而它是静态字段
      建议:把 culler 的资源生命周期挂到 device 上,或至少在 create() 替换时关闭旧实例。
  5. HierarchicalZOcclusionCuller 缺 null 防护,与另两个后端不一致isEmpty()/collectStatistics()/shouldDraw() 在首次 beginRenderingFrame() 之前调用会 NPE(previousFrameState/currentFrameState 为 null),而 GpuQueryOcclusionCuller/NoOpOcclusionCuller 都做了判空。若首帧事件顺序(多数屏幕/加载界面早于 RenderFrameEvent.Pre)与预期不同,会直接崩。

  6. fetchResults() 的边界与统计口径

    if (orDefault > results.length) { warn; return true; }   // 应为 >=,当前是越界写死的 off-by-one
    ...
    for (int result : results) { if (result == 0) culled++; }  // 遍历整个数组,而非前 size 个

    results.length > size(数组只涨不缩)时,culled 会统计到上一帧甚至更早的残留值,collectStatistics()culled/rendered 不可信。

  7. QueryInstance.cameraInside 是死代码setCameraInside 全仓库无调用点,因此 FrameState.runQueries

    if (!queries.get(i).isCameraInside()) transforms[i] = ...;   // 恒为 true

    FullTransformsUbo[] transforms 里的 null 空位都不可达。相机在盒内的情况实际由 FrameState.cameraInside 列表处理(这条是对的),建议删掉 QueryInstance 侧的重复机制 + 那个可能给 DynamicUniformStorage.writeUniforms() 传 null 元素的路径(未验证 vanilla 对 null 元素的容错)。

💡 建议

  • GpuQueryOcclusionCuller 每帧用阻塞式 glGetQueryObjectuiv(GL_QUERY_RESULT) 读取上一帧结果GlSamplesQuery.getValue()),会在帧首造成 CPU 同步 stall。既然已经是一帧延迟,建议改查 GL_QUERY_RESULT_AVAILABLE,未就绪时按「可见」处理,可完全去掉 stall。
  • frustum 预筛的 key 仍会发起 queryrunQueries 里命中 frustumCulled 后没有 continue,照样 acquireInstance + 画盒 + begin/end query,而 shouldDraw 已经对它们返回 false —— 这里可以直接跳过,省一半 query 提交。另外该选项默认 falseALROptions.OCCLUSION_QUERY_USE_FRUSTUM_PRE_PASS),是否应默认开启值得讨论。
  • GlComputePassBackend.ResidentState.references 只增不减、且从未被读取(没有 decrement/查询方法)——releaseResidentHandles() 每帧整体 make-non-resident,引用计数实际不参与任何判断,属死代码,建议删或补完整。
  • 大量注释掉的调试代码残留在生产路径GlComputePassBackend.setupBindlessImageArrays 里整段注释的 System.out.println 调试块、setupTexture 里注释掉的 _glUniform1i 逻辑、HierarchicalZOcclusionCuller.fetchResults// if (flag){ logger.error("222222222222222222222222"); }。全部 diff 中带分号的注释代码行有 58 行,建议清理(尤其那串数字日志)。
  • Hi-Z 每帧新建 2 个 CommandEncoderfetchResultsprocessFeatures),而 GL 后端在构造时就复用一个,建议统一。
  • ensureBuffers 依赖调用顺序requiredInputSize 取的是 inputSSBO.getDefinition().size(),其正确性依赖 dispatch() 里「先 setActualSize(elementCount)ensureBuffers」这一顺序。既然已经有 actualSize(elementCount),建议改用它做缓冲尺寸来源,避免将来重排两行就造成缓冲过小。
  • OcclusionSubmitNodeCollection 依赖 SubmitNodeCollection.clear()/endFrame()/wasUsed() 的私有语义(还通过 accessor 反写 original.wasUsed)。设计上是「录制到包装集合 → 镜像进原集合 → 由原集合渲染」,逻辑自洽,但这类耦合在 MC 每次渲染管线更新后都需要重新验证,建议在类注释里写明依赖点。
  • OcclusionFeatureRendererHelper.filterVisibleFeatures:culler 非空时每帧、每 feature renderer 都新分配一个 ArrayList(12 个渲染器)。建议「未过滤掉任何元素时返回原列表」。附注:ModifyReceiver 目标 List.iterator() 若匹配到多个列表会全部套用,但由于 shouldDraw 对未知对象默认返回 true,多匹配是无害的(这点设计很好)。
  • TestOcclusionTile(common 侧 BE)在构造器里 new OcclusionKey(...):把客户端渲染概念塞进通用 BlockEntity。目前 OcclusionKey 只依赖 AABB/Supplier,专用服务器上不会炸,但这是文档推荐的写法,建议把 key 放到 RenderState/客户端侧创建,避免通用代码耦合 module.rendering
  • module.test/src/generated/resources/assets/minecraft/models/block/diamond_block.json:测试模块生成并入库了 minecraft: 命名空间的方块模型(内容与 vanilla 相同)。会与其他资源包/未来 vanilla 变更产生覆盖与重复资源告警,建议改用自有的测试模型。
  • build.gradleCreateModuleTask 重构是正确修复(配置期 tasks.register {} 体改为 @TaskAction),👍。另:module.sync/processor 那 5 个文件本次只有 +import ApiStatus; 一行改动(纯 import churn),如果只是 @ApiStatus.Internal 位置调整,可考虑从本 PR 拆出以缩小体积。

🟢 看起来不错

  • 后端选择链(ALROptions.OCCLUSION_CULLING_FORCE_IMPL → Hi-Z → GPU Query → NoOp)与 HIERARCHICAL_Z.isSupported() 的能力门槛(compute && (bindless || maxImageUnit > 16))和 SinglePassDownsamplerbindless && maxImageUnit < 16 选择逻辑互补自洽——图像单元不足时走 bindless(不占 image unit),足够时走常规路径。
  • LoopResetPool 覆写了游标式 acquire,改为全槽扫描 + 满则 expand(),因此 query/instance 池不会随帧数无界增长(我按 SimpleResetPool.acquire 的游标语义推演过泄漏,确认被 LoopResetPool 覆盖规避了)。
  • 两个池 + FrameState 的「N-2 释放、N-1 读结果」时序正确:读取结果时对应 query 仍处于 acquired,不会被本帧复用,一帧延迟读取无竞态。
  • OCCLUSION_QUERY pipeline 用 WRITE_NONE + 深度测试 LESS/EQUAL 且不写深度,不会污染场景深度/颜色。
  • GlStateManager._glUseProgram 替换裸 GL46.glUseProgram 修掉了 MC 状态缓存与实际 GL 状态不一致的经典隐患。
  • 显式绑定重构在生产代码中全部与着色器 layout(binding=N) 一致(见上表),private 资源、@ApiStatus.InternalSupplier<String> 懒 debug group、try/finally 释放 resident handle 都做得比改前更严谨。
  • 新增 12 个 feature renderer mixin 全部登记进 anvillib_rendering.mixins.jsonen_ud.jsonen_us.json 同步且上下翻转正确;test_occlusion 的 block/BE/lang/blockstate/item/loot_table 注册完整。

📋 声称验证表

声称 状态 对应文件
OcclusionCuller/OcclusionKey/OcclusionMethod/CullingStatistics/包装提交节点存储 optimization/occlusion/*query/*hiz/*
自动后端选择(Hi-Z / GPU Query / NoOp) OcclusionMethodALROptimizationsOcclusionCuller.createInstance
池化 GL samples query、AABB query 渲染、frustum 预筛、一帧延迟读取 ✅(预筛默认 false) GpuSampleQueryPoolQueryInstanceFrameStateGlSamplesQuery
vanilla + NeoForge 各 feature renderer 可见性过滤 ✅ 12 个 mixin mixins/features/*(已全部登记 mixins.json)
padded R32F 深度转换 + FidelityFX SPD mip 链 DepthTexConverterSinglePassDownsamplerdepth_convert.cshffx_spd_*.csh
compute pipeline 命名布局 + 有序绑定分配 ALRComputePipelinebindings/*ALRComputePipelines
texture/image/buffer/atomic/bindless image array 显式绑定 ALRComputePassGlComputePassBackend
GPU 能力上报、扩展纹理格式、GL 纹理分配、ARB bindless handle/residency ALRHICapabilitiesExtendedTextureFormatGlExtendedTextureGlBindlessTexturingSupportGlTextureResidentScope
复用 GPU 资源池、transform/size UBO、渲染调试选项、开发 JVM 参数 ✅(JVM 参数见警告 4) foundation/*FullTransformsUboALROptionsmodule.gradle
ApiStatus.Internal 位置调整 + sync 模块 import 同步 ✅(纯 churn) module.sync/**(仅 +import 行)
test_occlusion 方块/BER/生成资源 + compute 测试绑定更新 ⚠️ ComputeSupport.computeBlur 绑定写错(关键 1),其余 ✅
TODO:完成 Hi-Z SPD dispatch 与可见性决策 isSupported 门槛已按 capability 设置
TODO:注册并选择 bindless SPD pipeline FFX_SPD_..._BINDLESS,按 capabilities.bindlessTexturing() 运行时选择
TODO:Minecraft 运行时与 GPU 验证 ⚠️ 无法从 diff 验证 建议把验证结论(GPU/驱动、帧率、各后端实测)写进 PR 描述
Impact 段「visibility decisions / SPD dispatch 仍需后续工作」「bindless pipeline 运行时注册与选择尚未完成」 ❌ 与代码和 TODO 段互相矛盾 HierarchicalZOcclusionCuller.processFeatures/dispatch/shouldDraw 与 bindless 选择均已实现,请更新描述

结论: REQUEST_CHANGES — 架构与绑定正确性整体扎实(生产路径的 binding point 与着色器 layout(binding=N) 逐条核对通过),但必须先修 ComputeSupport.computeBlur() 的绑定错误,并处理 module.gradle 的重复行/debug 参数入库、GlComputePassBackend 抛异常策略、MemoryAccesssun.misc.Unsafe 依赖这几项;同时更新 PR 描述中与 TODO 自相矛盾的部分。

标题 feat(rendering): add occlusion culling backends and bindless texturing 与内容相符且清晰,未修改(无需 gh pr edit)。

🧪 测试建议

被测目标 推荐场景 优先级
ComputeSupport.computeBlur() 修复绑定后,比对 GPU 输出与 CPU 参考实现的模糊结果;仿 add() 加 counter 断言,防止再次绑错 🔴
OcclusionFeatureRendererHelper.filterVisibleFeatures 空 culler → 必须返回原列表实例;culler 判定部分不可见 → 只剔除命中项;任何情况下不得把整列表清空 🔴
FrameState.shouldDraw / fetchResults 新 key 默认可见;cameraInside 优先于 query 结果;query 值 0/1 的两条路径;results.length > size 时的统计口径 🟡
OcclusionTestSSBO.actualSize(n) vs getDefinition().size(STD430) 断言二者一致(13 个 ivec2 + n 个 AABB 的 std430 偏移),锁住缓冲尺寸不被重排破坏 🟡
Std140LayoutRulesTest 扩展覆盖 FullTransformsUboOcclusionTestCBOcclusionTestSSBO——着色器依赖的手写 std140/std430 偏移正是最难察觉的破坏点(该测试文件本 PR 已更新签名,是好的先例) 🟡
OcclusionCuller.createInstance / OcclusionMethod capability 矩阵:强制 impl 名称合法/非法、无 compute、无 bindless、maxImageUnit 8/16/17 的组合 🟢
GlSamplesQuery release()result 必须复位为 -1(可用假 GL 层/mock 验证),防止跨帧读旧值 🟢

由 Hermes Agent 审查

@Gugle2308

Copy link
Copy Markdown

💾 Self-improvement review: Patched SKILL.md in skill 'rendering-gpu-pr-review' (1 replacement). · Patched references/pr95-occlusion-culling-review-matrix.md in skill 'rendering-gpu-pr-review' (1 replacement).

@Gugle2308

Copy link
Copy Markdown

代码审查摘要 — PR #95

操作: edited
范围: 174 个文件(156 Java / 86 新增 / 0 删除,含 18 个 shader 与 JSON)/ 10,033 行 diff(+7,563 / −185)
分支: feat/occusion_cullingdev/26.1

审查方法:curl 下载 patch-diff + 本地 git fetch origin pull/95/head:pr95-new 全量源码交叉引用(worktree /opt/data/workspace/anvillib-pr95),13 个 shader 与 Java 绑定点逐一对账。

📋 声称验证表

PR 声称 状态 对应实现
OcclusionCuller/Key/Method/统计/包装存储 optimization/occlusion/*(含 OcclusionSubmitNodeStorage/Collection
自动后端选择(Hi-Z / GPU Query / no-op) OcclusionMethod + OcclusionCuller.createInstance
池化 GL samples 查询、AABB 查询渲染、frustum 预通道、一帧延迟读回 GlSamplesQueryGpuSampleQueryPoolQueryInstance(Pool)FrameState
原版/NeoForge 各渲染特性可见性过滤 mixins/features/ 12 个 + 5 个 accessor,全部在 mixins.json 注册且类文件存在
padded R32F 深度转换 + FFX SPD mip 链 ✅(部分未完成) DepthTexConverterSinglePassDownsamplerdepth_convert.cshffx_spd_*.csh
compute pipeline 命名资源布局 + 有序绑定分配 ComputeBindingLayout.applyOrderedbindingsByName/bindingsByTypeALRComputePass.bind
显式 texture/image/buffer/atomic/bindless 绑定 GlComputePassBackend.bindArrayOfTexture/bindBindlessImageArray
GPU 能力上报、扩展纹理格式、GL 纹理分配、ARB bindless 句柄与常驻作用域 ALRHICapabilitiesExtendedTextureFormatGlBindlessTexturingSupport
资源池 / UBO / debug 选项 / 开发 JVM 参数 GpuReusableResourcePoolFullTransformsUboALROptionsmodule.gradle
「更新 ApiStatus.Internal 位置」 ⚠️ 大量新增 @ApiStatus.Internal同时删除了 MinecraftMixinALRIntegrationCompatMixinPluginItemStackRenderStateMixin 上原有的 @ApiStatus.Internal
test_occlusion 方块 + BER + 生成资源 ⚠️ ⚠️ 第 10、11 条

绑定编号对账结论(逐 shader 核对,✅):depth_convert.csh UBO=0/sampler=1/image=2 ↔ Java bindUniformBlock(0)/bindTexture(1)/bindImage(2)hiz_occlusion_test.csh UBO=0/SSBO=0,1/image 数组=0 ↔ bindUniformBlock(0)/bindShaderStorage(0,1)/bindArrayOfTexture(0,…);SPD sampler=0、mid=1、mips 数组=2..14 ↔ bindTexture(0)/bindImage(1)/bindArrayOfTexture(2,…)--size 校验(13=13)也对得上。


🔴 关键

  1. OcclusionCuller.createInstance 默认优先启用尚未完成的 Hi-Z 后端(会表现为「物体随机消失」)
    HIERARCHICAL_Z 排在 GPU_QUERY 之前,而 PR 描述自己写明「visibility decisions and SPD dispatch still require follow-up work」,代码里也留着未完成的证据:

    • hiz_occlusion_test.csh:93 — padding 与 framebuffer 尺寸的换算被注释掉://pixel *= vec2(mipLayers[0]) / cbOcclusionTest.viewportSize;viewportSize 是 framebuffer 尺寸,而 mipLayers[0]padded(64 对齐)尺寸,两者不等时(几乎总是)采样坐标最多错位 63px → 读到错误的 Hi-Z 值 → 错误剔除(可见物消失)或漏剔除
    • SinglePassDownsampler.spdDispatchImpl:222 — // TODO validate thisHierarchicalZOcclusionCuller.fetchResults:160-162 留着注释掉的调试输出;hiz_occlusion_test.csh:144 // TODO
    • SinglePassDownsamplersource(mip0,即 converter 输出的深度图)既绑成 read-only sampler(texture unit 0)又作为 image 数组元素 0 参与读(LoadSrcImage → imageLoad(mips[0]))——同一 level/layer 同时做 sampler 与 image 访问属 GL 反馈环,规范上是未定义行为。
      建议:默认 GPU_QUERY,Hi-Z 仅在 -DalrOcclusionCullingForceImplementation=HIERARCHICAL_Z 下启用,待坐标映射与 SPD 路径验证通过后再改默认值。
  2. 持久映射 staging buffer 缺 fence/flush,且 barrier 位用错 → Hi-Z 输入 SSBO 可能读到上一帧/垃圾数据
    StagingSupport.GpuStagingSupport:78mapBuffer(buffer, true, true) 建立常驻映射,但从不 glFlushMappedBufferRange / glFenceSync / glWaitSyncHierarchicalZOcclusionCuller.dispatch:242-243 只用 MemoryBarrierFlag.BUFFER_UPDATE_BARRIERGL_BUFFER_UPDATE_BARRIER_BIT),而 CPU 对持久映射缓冲的写入要让后续 GL 命令可见,需要 GL_CLIENT_MAPPED_BUFFER_BARRIER_BIT(作者的 // TODO check if mojang added coherent flag 正指向这里)。此外每帧重写该缓冲时未等待上一帧 GPU 读取完成 → 典型的持久映射数据竞争(表现为随机/间歇性错误剔除,难复现)。
    建议:改用 GL_CLIENT_MAPPED_BUFFER_BARRIER_BIT + 每帧 fence(或双缓冲轮转),或直接用 commandEncoder.writeToBuffer

  3. GlTextureMixin 在纹理关闭路径上可能 NPE,会拖垮资源重载/退出
    GlTextureMixin.alr$notifyTextureDisposed:17-18 直接 ((ALRGpuDeviceExtension) RenderSystem.getDevice())GlTexture.close() 可能发生在设备销毁之后(资源重载、窗口/上下文重建、游戏退出),此时 getDevice() 返回 null → 在关闭路径抛 NPE,影响面比普通渲染错误更大。
    建议GpuDevice device = RenderSystem.getDevice(); if (device == null) return;,并加 RenderSystem.isOnRenderThread() 保护(GlTexture.close() 不保证只在渲染线程)。

  4. HierarchicalZOcclusionCuller.shouldDraw:335 边界判断 off-by-one
    if (orDefault > results.length),随后 results[orDefault] —— 应为 >=。当前调用链下 orDefault ≤ size-1 ≤ results.length-1 使其不可达,但这是潜伏的 AIOOBE,且 results 数组复用旧帧数据(只在变小时不重建),一旦上游 id 分配方式变化就会命中。


⚠️ 警告

  1. GlComputePassBackend.setupState 由「静默 return」改为抛 IllegalStateException:以前 shader 无效时是 no-op,现在非法 program 直接崩溃。本 PR 恰好引入了按能力选择的 shader 变体(SPD 的 LDS/NO_LDS、Hi-Z 的 bindless/非 bindless),一旦某个变体在某驱动上编译失败(ALRComputeProgramInstance.INVALID),影响从「该效果失效」升级为「游戏崩溃」。建议 log + skip,或至少把 pipeline identifier 与编译日志带进异常。
    另外 dispatchWorkgroups/dispatchWorkgroupsIndirectfinally { releaseResidentHandles(); }:finally 内抛异常会掩盖原异常,且 close() 同时抛失败异常时,ALRComputePass 的 try-with-resources 会叠加 suppressed——建议 finally 只做清理不抛。

  2. GlDeviceMixin.alrCreateExtendedTexture 静默忽略 depthOrLayers:非 cubemap 分支只有 glTexImage2DGlDeviceMixin:172-184),depthOrLayers>1 会得到单层纹理,但对象里仍记录该值 → 调用方以为拿到了 2D 阵列。要么补 glTexImage3D 分支,要么在 depthOrLayers != 1 && !isCubemap 时显式抛错。同时整段使用魔数(1634067355333085/33082/330831285),建议换 GlConst/GL11/GL46 常量。

  3. 测试模块 ComputeSupport.INSTANCE 可为 null,且所有调用点都未判空ComputeSupport:34isComputeSupported() ? new ComputeSupport() : null,而 init()空方法ComputeSupport:233-234),仅用于触发类初始化;类初始化时读取的 COMPUTE_SUPPORTED 是否已由渲染模块的 MinecraftMixin 调过 ALRComputeCapabilities.init(),取决于两个 @Mixin(Minecraft.<init>) 的注入顺序 —— 顺序不利时 INSTANCE 会被永久置为 null,随后 AnvilLibTestClient:52/57/86GuiTestScreen:221/226/232ComputeSupport.INSTANCE.xxx 直接 NPE。建议改 @Nullable + 每处判空(或惰性 getter + Optional)。

  4. 12 个 feature mixin 使用 @ModifyReceiver(..., expect = 2) 硬编码命中次数(如 NameTagFeatureRendererMixin):命中次数一旦变化(vanilla 调整 iterator 调用数)会在类加载期抛 Mixin 错误 → 启动崩溃。建议 require = 0 + 多目标,或改用 @Redirect/@ModifyArg,并补注释说明为什么是 2。

  5. OcclusionSubmitNodeCollection 与 MC 内部结构强耦合submitFeatureToCuller() 逐一搬迁 16 个内部列表,并依赖 5 个 accessor 屏蔽的字段名(solidModelSubmitswasUsed…);beginOcclusionRecord 里对每条记录都调用 clear() + endFrame(),其语义(为何每条记录开始都要 endFrame、多次调用是否幂等)没有注释。建议补文档或加防御性校验。

  6. OcclusionCuller 生命周期不闭合close() 从未被任何地方调用;ALROptimizations.create() 直接覆盖 occlusionCuller 而不关闭旧实例;HierarchicalZOcclusionCuller.close() 只关了 testCBBuffer/inputBuffer/outputBufferdownsampler/depthTexConverter/stagingInputBuffer 的 GPU 资源(多张 R32F 纹理、sparams/counter buffer)无释放路径 → 设备重建即泄漏。

  7. 破坏性接口变更(AnvilLib 是被附属模组依赖的库模块)未在 PR 描述中作为兼容性事项列出

    • 删除 ALRComputePass.bindAll(List<?>)(public 方法,附属模组会编译失败
    • ALRComputePassBackend.pushDebugGroup(String)Supplier<String>popDebugGroup(String)popDebugGroup()
    • ComputeBindingLayout.applyapplyOrdered(返回增量,语义变了)
    • BufferWriter.intoBuffer()intoBuffer(boolean)putStructArray(E[])(E[], int)
    • ALRGpuDeviceExtension/BackendExtension.alrCompileComputeShaderalrCompileComputePipeline(pipeline, key)
      建议:保留 @Deprecated 桥接方法或明确说明这是下一个大版本的破坏性变更。(ALRComputePassBackendALRGpuDeviceBackendExtension 已标 @ApiStatus.Internal 可接受;BufferWriter 未标注。)
  8. GlComputePassBackend.bindBindlessImageArrayList 累积而不是按 key 覆盖:其他绑定都用 Int2ObjectMap 以绑定点去重覆盖,这里 this.bindlessImageArrayBindings.add(state) 无去重;当前 ALRComputePass 每次新建且 close() 清空所以不泄漏,但一旦 pass 被复用/多次 dispatch,会重复创建句柄并反复重绑历史状态。建议改为按 binding 名去重的 Map。

  9. ALRComputePipeline.getBinding(int bindingPointStart, ShaderResourceType) 语义与命名不符且无越界检查:参数实际是「该类型内的索引」而非 binding 点;且 TEXTURE_OR_IMAGE 合并后纹理与 image 共用同一编号空间(depth_convert.csh 的 sampler=1/image=2 正依赖这一点)——这个隐式契约没有写在任何地方,调用方极易写错 layout(binding=N)。建议重命名参数、加 bindingsByName 校验并在 Builder 上写明「按声明顺序统一编号」。

  10. OcclusionTestSSBO 用可变 size 的 layout 定义aabbsTypeaabbsTypeForSizeCalc 两份几乎相同的定义),ensureBuffers 的正确性依赖 setActualSize(elementCount)getDefinition() 之前被调用(顺序耦合,且 setActualSize 改了 aabbsType 却用另一份定义算 size)。建议把 elementCount 作为显式参数传给 size 计算,而不是让 layout 定义带运行期可变状态。

  11. 测试生成资源覆盖了 vanilla 模型module.test/src/generated/resources/assets/minecraft/models/block/diamond_block.jsonTexturedModel.CUBE.create(Blocks.DIAMOND_BLOCK, …) 的 datagen 副作用产物,内容与 vanilla 相同但会被打进 mod 资源包覆盖 minecraft:block/diamond_block(vanilla 后续改模型时会被这份旧副本顶掉)。建议 blockstate 直接引用已有模型,或不要把该文件纳入提交。顺便:本次 diff 有 9 处缺尾换行(含 SyncPayload.javaExtendedTextureFormat.java、多个 generated json)。

  12. module.gradlesystemProperty('neoforge.enabledGameTestNamespaces', project.mod_id) 连续写了两遍(重复行);同时移除了 neoforge.disableGlValidation=true——dev 运行配置里开启 GL 校验配合本 PR 的 _getError()/clearGlErrors() 用法可能产生刷屏,建议在描述里交代意图。

  13. scope 外改动build.gradlecreateModule 任务重构成 DefaultTask(配置缓存改进,与渲染无关)、module.sync 若干文件的 import 调整,均与本 PR 主题无关,建议拆到独立 PR 或至少在描述中标注。


💡 建议

  1. ALROptions.getPropertyBoolean(String) 单参数重载是个陷阱:属性缺失时 !"false".equals(null)返回 true,导致 SPD_OPTION_WAVE_INTEROP_LDS 默认开启,且 -DalrSpdOptionUseWaveInteropLds=0/空串也会被判为 true。建议统一为 Boolean.parseBoolean + 显式默认值,或删掉单参数重载。
    关联风险:SinglePassDownsampler:130-135 只用 shaderSubgroup 门控 LDS 变体,而 shader 里 #extension GL_KHR_shader_subgroup_quad : require——请确认 GL_KHR_shader_subgroup(无后缀)确实是 LWJGL 提供的字段名,并且它足以保证 quad 子组扩展可用;否则应探测 GL_KHR_shader_subgroup_quad(仅提供 basic 的驱动会编译失败 → 触发上面 ⚠️1 的崩溃路径)。
  2. 清理注释掉的调试/未完成代码QueryInstance:95 // ChatGPT can make mistakes. Check important info.GlComputePassBackend 中的大段注释调试块与 //TODO test on amd//TODO check if mojang added coherent flag// TODO validate this、被注释的 SPD define(SPD_MAX_MIP_LEVELS)等。建议合并前清理或转为 issue 跟踪。
  3. CullingStatistics.message 类型是 List<String>OcclusionCullingDebugEntry 直接字符串拼接会输出 [a, b];建议改名 messages 或换成 @Nullable String
  4. OcclusionKey.nameSupplier<String>)从未被任何代码消费 → 死 API;建议用于 debug 输出或删除。
  5. HierarchicalZOcclusionCuller 每帧 createCommandEncoder() 两次(fetchResults/processFeatures),可复用一个;@Setter mipmapUpdateInterval 未同步重置 mipmapUpdateCdisEmpty()/collectStatistics() 未判 previousFrameState == nullGpuQueryOcclusionCuller 的同名方法有保护,两实现行为不一致)。
  6. QueryInstance.CreationContext.vertexBufferstatic 且无释放路径,设备/上下文重建后会持有失效的 GpuBuffer;建议挂在 culler 实例上随 close() 释放。
  7. GlComputePassBackend.setupArrayOfImagebindingPointStart 起连续占用 image unit,多组数组绑定会互相覆盖且无冲突检测;bindArrayOfTexture 建议加 range 校验。
  8. putVec2Array(int size, Vector2f[])size 遍历数组,Array.size(int) 又允许运行期改 size —— size > 数组长度时 AIOOBE(OcclusionTestSSBO.getAabbs 返回的数组长度 ≥ size 时才安全)。建议加断言或改为 subList/长度派生。
  9. ALRComputeProgramInstanceownerINVALID 实例上为 null 但字段未标 @Nullableequals/hashCodeowner(含 bindings 列表)纳入,建议明确这些语义(或只按 id)。
  10. @ApiStatus.Internal 的增删不一致(见验证表第 10 行):要么统一加到所有内部实现类,要么在描述里说明标准。

🟢 看起来不错

  • ALRComputePass/GlComputePassBackend 的 debug group 用 try/finally 配对,dispatchWorkgroupsIndirect 也补上了 group(之前在多层 group 下会失衡)。
  • bindless 句柄的引用计数 + read/write 权限合并ensureResident)设计合理,dispatch 后统一 releaseResidentHandles()close() 用 suppressed 聚合多重失败。
  • 改用 GlStateManager._glUseProgram / _bindTexture 走状态缓存,取代裸 GL46.glUseProgram,避免状态缓存失效。
  • 去掉 bindAll(List<?>) 的 raw/unchecked 用法,改为按声明顺序分配 binding point + ImmutableList.copyOf(bindings) 固化。
  • std140/std430 的 Vec2/IVec2 数组 writer 与 size calculator 交叉核对一致(stride 分别 16/8,alignment() 同步返回 16/8,StructArray 的 stride 计算两处一致)——我逐项比对过,没有发现常见的 padding 计数错误。
  • ALRHICapabilities 把 GL 探测集中到一处并缓存(含 maxImageUnits),StagingSupportisGlOnDx12() 走 CPU 回退 —— 兼容性考虑到位。
  • onResize 链路完整(MainTargetResizeEvent → 双路径实现 → padded 尺寸先算后传),没有遗留陈旧尺寸。
  • 新增 test_occlusion 方块 + TESR 作为最小可复现入口(可直接用 F3 调试条目 anvillib_rendering:occlusion_culling 观察统计),对后续验证很有帮助。

结论: REQUEST_CHANGES — 框架设计(后端抽象、池化查询、有序绑定、bindless 句柄管理)方向正确且实现质量总体不错,但存在三个必须先处理的阻塞项:(1) 默认启用作者自认未完成、且存在 padding 坐标映射缺陷与反馈环的 Hi-Z 后端;(2) 持久映射 staging buffer 缺少 fence/flush 且 barrier 位不正确,会引入随机剔除错误;(3) GlTextureMixin 在纹理关闭路径上的 NPE 风险。另请补齐 bindAll 等 public API 破坏性变更的兼容策略说明。

标题未自动修改:gh auth status 显示 /opt/data/home/.config/gh/hosts.yml 中 token 已失效(不执行 export GITHUB_TOKEN)。建议标题:feat(rendering): add occlusion culling backends and bindless texturing(可补 and refactor compute bindings 以覆盖 compute 绑定重构部分)。

🧪 测试建议

被测目标 推荐测试场景 优先级
GpuQueryOcclusionCuller(一帧延迟) 首帧无 previousFrameState 时必返回 visible;连续两帧同一 OcclusionKey 的结果读回;相机进入 AABB 时强制可见;OCclusionKey 每帧复用时 bb 更新生效 🔴
HierarchicalZOcclusionCuller.shouldDraw results 长度边界(orDefault == results.length)、results == null、key 不在上一帧 map 中;非 64 对齐窗口尺寸(padded ≠ framebuffer)下的坐标换算 🔴
StagingSupport.GpuStagingSupport 连续两帧写入后回读一致性;buffer 扩容后旧映射关闭;isGlOnDx12() 走 CPU 路径 🔴
OcclusionSubmitNodeCollection beginOcclusionRecord 未配对结束 → 抛 IllegalStateException;重复 begin;空记录(wasUsed == false)不提交;16 个 submit 列表搬迁的完整性(搬移后原集合内容一致) 🟡
FrameState.addKey/fetchResults 同一 key 多个 feature 只分配一个 query;culled/features/total 统计与输入一致;glGetQueryObjectuiv 结果 0/1 映射 🟡
ALRComputePipeline.getBinding(name/type) 名称不存在返回 null;getBinding(int,type) 越界行为;bindingsByType 中 texture 与 image 混排的顺序 🟡
std140/std430 putVec2Array/putIVec2Array stride=16/8 与 size calculator 一致(写入后 buffer position 应为 align + stride*size);size 与数组长度不一致 🟡
GlComputePassBackend resident 句柄 同一纹理以不同 read/write 需求两次绑定 → 权限合并为非驻留再驻留;dispatch 后 residentHandles 清空;close() 后重复 close 幂等 🟡
GlDeviceMixin.alrCreateExtendedTexture depthOrLayers > 1 的期望行为(当前被忽略);cubemap usage 位;GL_OUT_OF_MEMORY 抛出路径 🟡
ALROptions.getPropertyBoolean 属性缺失 / "false" / "0" / "" 四种取值的期望结果(当前 0"" 均判为 true) 🟢
OcclusionCuller.createInstance alrOcclusionCullingForceImplementation 非法值回退到自动选择;isSupported() 为 false 时跳过对应后端;最终回退 NoOp 🟢

由 Hermes Agent 审查

@Gugle2308

Copy link
Copy Markdown

💾 Self-improvement review: Patched SKILL.md in skill 'rendering-gpu-pr-review' (1 replacement). · Patched SKILL.md in skill 'pr-diff-scope-reconciliation' (1 replacement). · Patched references/pr95-occlusion-culling-review-matrix.md in skill 'rendering-gpu-pr-review' (1 replacement).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants