GPU资源生命周期
全库目录221
本文目录11
纹理对象在CPU上已经析构,GPU仍可能持有未完成的读取。反过来,图内句柄结束也不意味着物理内存立刻释放。要把这几种寿命分开:内容何时有效、分配何时可复用,以及最后一条GPU访问何时完成。上传、回读、临时纹理和历史都沿这条规则管理。
内容与完成边界
帧内与跨帧资源
帧内模糊中间纹理只服务于少数通道,可以由渲染图管理。TAA 历史、阴影缓存和常驻材质纹理跨帧使用,需要外部所有者管理创建、重建和回收。动态分辨率、格式变化或相机切换可能使历史失效,应在采样前检测描述变化并清除。
逻辑资源创建 → 首次完整写入 → 后续读取 → 最后访问
↓
GPU 完成后物理回收数据传输
上传与回读
D3D12 upload heap、Vulkan host-visible 内存适合 CPU 写入,再交 GPU 使用。并非所有 host-visible 内存都同样快,也不能假设 CPU/GPU 共享物理内存便无需同步。
Vulkan 非 coherent 内存的 CPU 写入需按规范 flush,对齐范围涉及 nonCoherentAtomSize。GPU 写入后的 CPU 读取需先确认执行完成,再按需要 invalidate。coherent 免除部分缓存管理,不免除执行依赖。
离散 GPU 常把频繁使用的数据复制到 device-local 内存;统一内存设备要按平台缓存和存储模式选择。回读可先复制到 readback/staging 资源,再在完成值满足后读取。
环形上传区间
下面是数据结构伪代码。分配器记录每段最后使用的提交完成值,只有已完成段可以复用。
Allocate(bytes, alignment):
begin = AlignUp(writeCursor, alignment)
region = FindFreeRange(begin, bytes)
if region overlaps an in-flight range:
grow the ring or wait for its completion value
Reserve(region) // 立即占用,提交前也参与冲突检查
writeCursor = region.end
return region
Submit(region, value):
inFlight.push(region, value)
Collect(completedValue):
while inFlight is not empty and inFlight.front.value <= completedValue:
oldest = inFlight.pop_front()
free(oldest.region)分配与提交可能由多个线程执行,需要统一排序或锁;这里的 inFlight 按同一队列递增的提交完成值排序。环回时不能跨越未完成区间。等待会限制吞吐,扩容会增加峰值内存,选择依据是预算与可接受等待。
例如环容量1024字节,区间[0,512)被提交7使用,完成值仍为6。写游标走到末尾后回绕,新的256字节请求不能覆盖[0,256),即使CPU已经释放对应对象。完成值到7以后才可复用;分配器可以等待或扩容,但必须保留同一不重叠条件。
环形分配器必须在分配成功时就保留区间,提交时再给它附完成值。假设两个记录线程都在提交前申请上传数据,若只把已提交区间放入冲突表,两次申请可能返回同一位置。可将区间分成“已保留、已提交、已完成”三个状态,取消未提交命令时释放其保留,GPU 完成后释放已提交区间。
分配与复用
池复用与堆别名
资源池重用一个已创建纹理对象,可以减少频繁创建。堆别名让不同资源对象共享物理内存,要求寿命不重叠、分配兼容并处理别名屏障。池里没有CPU使用者,只说明应用暂时不取它;GPU上一帧可能仍在访问。因此池命中也要检查完成值。
渲染图资源导入可以表达外部纹理的读写,是否参与具体分配优化由引擎决定。CPU 引用计数不能独立证明 GPU 使用结束。
驻留与内存预算
虚拟地址、已分配堆和实际驻留内存不同。超出设备预算可能触发迁移、淘汰或分配失败。统计时区分常驻资源、缓存、在途上传、帧临时峰值和引擎保留池。单看进程总内存难以解释 GPU 抖动。
验证方法
- 将 GPU 负载拉长,快速循环上传和销毁,确认旧帧内容不会被覆盖。
- 记录资源创建数、池命中、待回收字节和完成值;停止提交后待回收量应逐步下降。
- 开关图内别名,检查图像一致性和内存峰值。
- 改变分辨率、相机数量和历史格式,检查旧历史是否被安全替换。
- 异步回读附帧号,确认 CPU 不把延迟结果用于错误的当前帧。
相关主题
示例状态:本页代码用于解释对应的数据和调用约束,完整资源创建、类型与调用环境由项目提供。除文中另列的实际实验外,本页未执行目标引擎编译、GPU捕获或性能计时。
参考资料
- Khronos:Memory Allocation:Host Access to Device Memory 与 VkMappedMemoryRange:映射、flush/invalidate 和 nonCoherentAtomSize 对齐。