. - #10
Merged
Merged
Conversation
根因:MetalGpuBuffer.<init> 对 size=0 无下限 clamp,allocationSize=(size+15)&~15 在 size=0 时为 0,经 metallum_create_buffer 传给 makeBuffer(length:0) 按 Apple 契约 返回 nil,抛裸 "Failed to create Metal buffer";叠加 nativeHandle() 只查 Java null 不查 address()==0,MemorySegment.NULL 静默穿透到 drawIndexedPrimitivesIndirect, AGXMetal 解引用 0x0 触发 SIGSEGV。 修复: - MetalGpuBuffer.<init>: 入口校验 size<=0 / 对齐溢出 / 超 maxBufferAllocationSize; 失败异常携带 size/resourceOptions/device 诊断(非裸消息) - MetalDevice: createBuffer 两重载入口拦截 size<=0 与空 ByteBuffer; 新增包级 maxBufferAllocationSize() 暴露 device 上限 - MetalGpuBuffer.nativeHandle(): 增加 address()==0L 检查,阻断 NULL 段穿透 - MetalRenderPass: drawIndexedIndirect 派发前校验 drawCount/indexBuffer/ indirect buffer isClosed/容量,失败 warn+return;drawIndexed 补 indexBuffer null 防御 - MetallumNative.swift: metallum_create_buffer 加 guard length>0; drawIndexedPrimitivesIndirect 加越界/溢出校验(defense in depth)
iOS 3-5 分钟延迟闪退根因:MetalCommandEncoder.dynamicBackingPool 是全仓 唯一无上限对象池,recycleDynamicBacking 永远 push 无 eviction;所有 backing 为 MTLStorageMode.Shared(iOS 计入 RSS)。叠加 acquire 立即/recycle 延迟 2-3 帧 不对称,稳态 live backing 数被延迟系数放大,iOS recommendedMaxWorkingSetSize 耗尽后 jetsam 杀进程或 makeBuffer 返回 nil 抛 IllegalStateException 崩渲染线程。 macOS 内存大+swap 容忍故未报告。 修复: - MetalDevice.composePoolKey 去 private 改包级静态,MetalCommandEncoder 复用 - MetalCommandEncoder 加 MAX_POOLED_DYNAMIC_BACKINGS_PER_SIZE=8;acquire/recycle 改用 composePoolKey(size, resourceOptions) 复合键(替代 size-only,维度一致) - recycleDynamicBacking 桶满时 metallum_release_object 释放(替代无界 push) - acquireDynamicBacking 在 makeBuffer nil(OOM)时 return MemorySegment.NULL + warn, 不抛 IllegalStateException;orphanWrite 检测 fresh.address()==0L 早退 return (在 recycle 之前,无双持),old backing 保持合法,GPU 读上一帧 uniform, 下一帧 destroyQueue.rotate 后池命中自动恢复(方案 A:跳过+log) 不实现 staging blit(核查不可行:hazard+transient 生命周期不匹配);不实现 mid-frame flush(架构侵入高)。
…loading iOS 跑图 3-6 分钟延迟闪退根因(前两轮修复 c0068c4/aee788d 后仍复现): MetalDevice.bufferPool 为 HashMap,每桶 16 上限但 distinct (size, resourceOptions) 桶数无上限,drainBufferPool 仅 device.close() 调用。 跑图时新区块加载产生各异 size 的 vertex/index buffer(每 region 几何不同 → allocationSize 不同 → 新桶),桶数单调增长,每桶最多 16 个 MTLBuffer 滞留。 iOS 集成 GPU 无独立显存,Private buffer 也计入 jetsam footprint(修正 "Private 不占 RSS"的 macOS 心智模型错误),累积到阈值后 jetsam 杀进程。 挂机不崩证明 uniform 路径(dynamicBackingPool,aee788d 已修)非本次主因。 修复: - bufferPool 从 HashMap 改为 LinkedHashMap(accessOrder=true),override removeEldestEntry,桶数超 MAX_POOLED_BUFFER_BUCKETS=32 时淘汰最旧桶, 遍历释放其中所有 MTLBuffer - MAX_POOLED_BUFFERS_PER_SIZE 16→8(防御纵深) - tryAcquirePooledBuffer/queueBufferRelease/drainBufferPool 逻辑不变 (LinkedHashMap.get/computeIfAbsent 自动维护 access-order, removeEldestEntry 自动触发;drainBufferPool 遍历释放逻辑不变) 不引入 dynamicBackingPool LRU(挂机不崩证明非主因)、storage mode 特判 (iOS 上 Private 也占 footprint,特判无效且破坏 macOS 语义)、周期性 drain (无 iOS memory-warning 钩子)、字节上限(Stats.java 死代码,过度工程)。
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.
No description provided.