renderdoc源码分析(二) resource manager

写在前面
1. 只针对renderdoc opengl es 场景进行说明, vukan的没有,不过其实应该也差不多啦,若有必要后面再考虑补上。
2. 本文使用 文字+图+代码 的方式叙述,若只想了解原理过程,可忽略代码部分

由于renderdoc代码还算复杂和乱,代码部分主要是辅助有兴趣阅读源码的同学去抓住代码主要逻辑。
3. renderdoc 相关名词
4. 对一帧抓流时,
1. 开始时机:前一帧swapbuffer时,具体逻辑做在StartFrameCapture()接口;
2. 结束时机:当前这一帧swapbuffer时,具体逻辑做在EndFrameCapture()接口;
即,前一帧的结束就是这一帧的开始嘛, 如图:

请添加图片描述

what

  1. resource manager, 顾名思义就是renderdoc 用来管理gl资源的,在opengles之上自己做了个状态机, 用来记录gl 资源的使用情况。
  2. gl资源在renderdoc resource manager里边主要由3个结构体来描述,
    GLResource:记录该资源 类型、在opengl es状态机里边的id,如glGenTextures生成的texture值;
    ResourceId:记录该资源在resource manager 里边的id,
    GLResourceRecord:以chunks形式,记录操作该资源的相关gl接口调用,尤其是创建、绑定、属性设置、数据upload,如glGenTextures,glGenBuffers等,一条glXXX用一块chunks记录。
  3. gl resource:
    以下这些在renderdoc都可以描述为资源,基本涵盖所有gl资源了,有点类似于 linux里一切皆文件思想哈哈哈,
enum GLNamespace
{
   
   
  eResUnknown = 0,
  eResSpecial,
  eResTexture,
  eResSampler,
  eResFramebuffer,
  eResRenderbuffer,
  eResBuffer,
  eResVertexArray,
  eResShader,
  eResProgram,
  eResProgramPipe,
  eResFeedback,
  eResQuery,
  eResSync,
  eResExternalMemory,
  eResExternalSemaphore,
};

why

  1. 在opengles 之上做了个状态机, 能起到如下作用,
    抓流场景:
    (1)性能、内存优化: BackgroundCapturing时 对于每一块gl resource,记录其数据更新时间(postpone机制)、当前帧是否使用(frame reference机制)、是否dirty(dirty机制),
    当进行真正的抓流ActiveCapturing时,就可以只序列化保存在当前帧使用的资源相关chunks;
    重放场景:
    (1)新旧资源映射: 对于来自opengl状态机的资源id, 抓流序列化时保存下来,
    重放是,需要去创建一个对应的资源,由于id不保证一次,所以需要做一个映射,
    即:origing GLResource <------> live GLResource
    (2) 性能优化:
    抓一帧时,有的资源是在该帧开始前就upload数据到gpu侧的,
    那么需要在每次重放帧开始前,先对该资源gpu侧显存进行初始化,若每次都从磁盘把数据找出来再disk–>cpu–>gpu,太耗性能,
    所以可以在resource manager里边做一个记录: live resource/origing resource <–> initialContents,
    initialContents放在cpu侧内存, 每次重放前做cpu—data—> gpu就ok了。

无论是resource manager本身,还是其里边实现的下面那些frame reference、dirty、persistent、postpone等各种机制,都不是必须的,是对性能和内存的优化,
抓流时也可以都不用,hook后简单粗暴记录下所有gl调用和资源,而随之带来的当然是无论BackgroundCapturing还是ActiveCapturing时的各种卡顿和内存占用过大。

frame reference 机制

  1. what
    标记一帧里边某个资源有被使用
  2. why
    优化内存与性能: 抓流时,该帧没被标记的资源,就不需要保存了。
  3. 相关接口
template <typename Configuration>
void ResourceManager<Configuration>::MarkResourceFrameReferenced(ResourceId id, FrameRefType refType)

//EndFrameCapture 时,序列化frame reference 资源
template <typename Configuration>
void ResourceManager<Configuration>::InsertReferencedChunks(WriteSerialiser &ser)

dirty机制

  1. what
    用 MarkDirtyResource( )标记该资源脏了,用在该资源gpu侧内容被改变时;
    区别于frame reference resource, 用MarkResourceFrameReferenced()标记该帧有使用了该资源
  2. why
    BackgroundCapturing场景,应用每次对资源更新数据时,renderdoc不需要每次都保存,因为实际上抓帧时,只要在这一帧开始前资源的最后一次内容就行了。
    例如对于一块buffer:
//BackgroundCapturing
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffName);
//frame1
glBufferData(GL_ELEMENT_ARRAY_BUFFER, data_size_in_bytes, data1, GL_STATIC_DRAW);
//frame2
glBufferData(GL_ELEMENT_ARRAY_BUFFER, data_size_in_bytes, data2, GL_STATIC_DRAW);
//framen
glBufferData(GL_ELEMENT_ARRAY_BUFFER, data_size_in_bytes, dataN, GL_STATIC_DRAW);

//ActiveCapturing
//frame capture
//对于当前要抓的这一帧,若用到了buffName,那么我们需要保存的就只是dataN的内容, 
//所以对于BackgroundCapturing时更新的数据data1、data2等,只要每次更新数据时做个dirty标记就行,
//表示这块资源dirty,可是没有保存,咱们在抓帧时把他保存下来就行
  1. 相关接口
 void MarkDirtyResource(ResourceId id);
  void MarkDirtyResource(GLResource res)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值