glmark2代码分析4(程序流程)

main函数流程

main函数的主要工作有:

  1. 解析输入参数
  2. 初始化log,appname
  3. 打印帮助 if (Options::show_help) Options::print_help();
  4. 设置窗口大小Options::size = (800, 600)
  5. 实例化canvas,配置相关参数
  6. 实例化SceneCollection,在定义scenes时就通过构造函数,调用add_scenes,将各个scene实例添加到vector中。
  7. register_scenes将scene再导入到sceneMap_中,时名字和scene的map类型
  8. if (Options::list_scenes) list_scenes(); 打印列出scenes
  9. canvas.init(),窗口初始化,初始化OpenGL和默认配置
    native_state_.init_display()
    gl_state_.init_display(native_state_.display(), visual_config_);
    reset();
  10. canvas.visible(true);
  11. 执行benchmark,加载benchmarks并循环执行测试。

总结下,main函数中主要是做canvas的创建,和初始化,然后是scene的初始化,到do_benchmark中开始加载和创建测试的benchmark链。

False
True
Yes
No
Yes
No
False
True
True
False
开始
Options::parse_args
结束
Log::init
show_help
Options::size = 800, 600
InitScenes
list_scenes
canvas.init
benchmark_collection.populate_from_options
Options::validate
do_validation
enchmark

canvas初始化

窗口初始化部分的主要工作:

    CanvasGeneric canvas(native_state, gl_state, Options::size.first, Options::size.second);

    canvas.offscreen(Options::offscreen);

    canvas.visual_config(Options::visual_config);
    canvas.init()
        canvas.visible(true);

scene初始化

scene初始部分的主要工作有:

    SceneCollection scenes(canvas);
    scenes.register_scenes();

执行过程

benchmark的执行流程:

分别是do_validation和do_benchmark,两个的整体流程一致:

  1. 通过 benchmark_collection.populate_from_options() 加载具体测试项 benchmark;
  2. 根据 Option 定义 Loop 类型,然后循环执行loop中的测试项:while (loop->step());
  3. do_validation 只是验证下这个bench是不是可以执行,很快会结束,不统计得分
  4. do_benchmark 是会按照配置参数完全执行bench,会计算得分
Yes
No
do_validation
populate_from_options
MainLoopValidation
loop->step
do_benchmark
populate_from_options
needs_decoration
MainLoopDecoration
loop->step
loop->score
MainLoop
三个mainloop的区别

这里相当是 Options 的参数会走出三个 MainLoop 的分支:

  • MainLoopValidation:
    -继承自MainLoop,跑一个快速的验证,只跑第一帧。
    重构 draw 方法,在 canvas_.update() 之后设置运行结束 scene_->running(false)
    重构 log_scene_result 方法,打印 validate 的结果,在MainLoop的 step 中会调用 log_scene_result,log_scene_result 中会调用 validate 函数,每一个 scene 都会定义validate函数。
  • MainLoopDecoration:
    装饰作用,重点是会打印帧率和title,重构的draw、before_scene_setup、after_scene_setup中添加了判断 if (show_fps_) 和 if (show_title_) 的处理。
    这两个mainloop根据needs_decoration区分,判断 benchmarks_ 中只要一个bench是 needs_decoration 的,就返回true, bench的needs_decoration是看option中如果设置show-fps为true或者title为空。
  • MainLoop:
    这里有一个思想:从过重构mainloop将条件分散到不同的类中执行,然后到scene的时候又回到相同的调用里。
testbench的加载populate_from_options

testbench的加载在 BenchmarkCollection::populate_from_options 中执行,分三种情况依次判断:

  1. 输入参数 benchmark 非空,用参数生成 Benchmark 对象,添加进 benchmark_ 中;
  2. 输入参数 benchmark_files 非空,调用 add_benchmarks_from_files 从文件种读取配置,生成Benchmark 添加进 benchmark_ 中;
  3. 如果 benchmark_ 中没有一个scene(判断 scene name 是不是空),调用 DefaultBenchmarks 的 populate 添加默认的 option 配置,生成 Benchmark 添加进 benchmark_ 中;
void
BenchmarkCollection::populate_from_options()
{
    if (!Options::benchmarks.empty())
        add(Options::benchmarks);

    if (!Options::benchmark_files.empty())
        add_benchmarks_from_files();

    if (!benchmarks_contain_normal_scenes())
        add(DefaultBenchmarks::get());
}
mainloop的step执行
  1. 遍历 benchmarks_ 找到一个有效的 scene,判断有效方法为:scene的name非空。
  2. 找到一个有效的scene之后,调用 setup_scene ,设置option、shader精度和开始的时间戳。同时前后调用 before_scene_setup 和 after_scene_setup,这两个只有在decoration中有操作。
  3. 判断是否中止,如果继续运行,调用draw函数进行canvas和scene的真正绘制。draw中会update canvas和scene的状态和参数。
  4. 再次判断运行状态是否是running,如果运行结束,记录log和result,teardown scene并切换next benchmark。
    问题:scene_setup_status_ == SceneSetupStatusSuccess之后才计算分值
    可作为代码模板:
while (bench_iter_ != benchmarks_.end()) {
    scene_ = &(*bench_iter_)->scene();
    if (scene_->name().empty())
        (*bench_iter_)->setup_scene();  //从option中拿配置参数,将参数写到scene中,生成一个scene的
    else
        break;

    next_benchmark();  
}
//操作为给遍历指针++,如果到底了或者有forever运行,将指针重新指到开始。
void
MainLoop::next_benchmark()
{
    bench_iter_++;
    if (bench_iter_ == benchmarks_.end() && Options::run_forever)
        bench_iter_ = benchmarks_.begin();
}
MainLoop的draw函数
void
MainLoop::draw()
{
    canvas_.clear();  //调用到两个Canvas子类中的clear,时glClearColor、glClearDepth和glClear
    scene_->draw();  //调用到具体scene的draw函数
    scene_->update();   //更新帧数和事件
    canvas_.update();   //判断当前帧的状态,有swap、finish、readpixel
}

整体循环流程

main函数中:while (loop->step());
MainLoop::step函数中:判断中间变量 scene_ 是否为空,从 benchmarks_ 中逐个取出给 scene_
然后调用scene的draw进行渲染测试,结束后指针查找下一个 next_benchmark

总结

总结下:scene是运行的各个用例的类型,根据option参数可以配置不同的测试点。在scenecollection中将各个scene对象串起来做成链表保存在SceneMap中,和scene的name形成一个map表,方便后面的查询;到populate_from_options中根据参数(scene:options)取出scene和option,创建成Benchmark组成具体的测试项链,这里用get_scene_by_name通过name获取在SceneMap中存的scene对象。整个过程中相当于多了一个SceneMap对scene对象进行管理。所以,总结两点:
1、测试的benchmark是可以通过option配置,保证scene复用;
2、用map对scene对象管理,为第一点提供支持。

  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值