确定 Vulkan 与 OpenGL ES 游戏渲染 API

在开发或优化 Android 游戏时,了解引擎使用的是哪种图形流水线通常会很有帮助;引擎可能会选择 Vulkan 或 GLES,而不会发出开发者可访问的明确信号。遗憾的是,在某些情况下,依靠 logcat 来验证游戏是在 Vulkan 上运行还是已静默回退到 OpenGL ES 可能并不可靠。

本指南介绍了如何使用 Android Performance Analyzer (APA) 和自定义 Perfetto SQL 查询来明确识别游戏的活跃渲染 API。

基于日志的验证的限制

  • 剥离的日志:正式版 build 通常会隐藏初始化和驱动程序加载痕迹。
  • 假正例:某些游戏引擎会在启动期间同时加载 Vulkan 和 OpenGL ES 库,并输出两者的初始化日志,即使其中一个最终失败并触发回退也是如此。
  • 静默回退:如果 Vulkan 初始化因设备专属驱动程序问题而失败,引擎通常会回退到 OpenGL ES,而不会抛出严重错误。

使用 APA 进行衡量

使用 Android Performance Analyzer,您可以记录系统跟踪,并通过 SQL 查询精确分析帧数据。请按照以下步骤衡量 Vulkan 和 GLES 的使用情况:

  1. 使用 APA 捕获跟踪记录:运行游戏,并使用 APA 在您要分析的片段(例如,您怀疑游戏过程中出现掉帧的时间点)期间捕获系统跟踪记录。连接设备并完成跟踪记录后,跟踪数据会加载到 APA 界面中。

  2. 点击 APA 中的 SQL 标签页:打开跟踪分析界面后,在界面的导航菜单中,点击 SQL 标签页以打开跟踪处理器环境,您可以在其中直接查询数据。

  3. 将以下 SQL 查询粘贴到 APA SQL 标签页中:复制以下 SQL 查询并将其粘贴到查询输入字段中。此查询会扫描跟踪记录,查找绘制 API 事件,例如 eglSwapBuffers、QueuePresentKHR 和 vkQueuePresentKHR。它会按进程名称对这些调用进行分组,并计算渲染 API 计数以及 Vulkan 与 OpenGL ES 渲染调用的百分比分布:

    WITH raw_slices AS (
      -- 1. Map each slice (API call) to its corresponding process or package via UTID and UPID
      SELECT
        p.name AS process_name,
        s.name AS slice_name
      FROM slice s
      JOIN thread_track tt ON s.track_id = tt.id
      JOIN thread t USING (utid)
      JOIN process p USING (upid)
      WHERE (s.name LIKE 'eglSwapBuffers%'
        OR s.name IN ('QueuePresentKHR', 'vkQueuePresentKHR'))
        -- Optional: To isolate your game, uncomment the following and filter by package name and thread name:
        -- AND p.name = 'com.example.mygame'
        -- AND t.name = 'RenderThread'
    ),
    process_stats AS (
      -- 2. Aggregate counts per individual process
      SELECT
        process_name,
        SUM(CASE WHEN slice_name LIKE 'eglSwapBuffers%' THEN 1 ELSE 0 END) AS egl_count,
        SUM(CASE WHEN slice_name IN ('QueuePresentKHR', 'vkQueuePresentKHR') THEN 1 ELSE 0 END) AS vulkan_count
      FROM raw_slices
      GROUP BY process_name
    ),
    process_totals AS (
      -- 3. Calculate total counts for denominator calculation
      SELECT
        process_name,
        egl_count,
        vulkan_count,
        (egl_count + vulkan_count) AS total_count
      FROM process_stats
    )
    -- 4. Calculate final percentage shares per row, preventing division by zero errors
    SELECT
      process_name,
      egl_count,
      vulkan_count,
      total_count,
      ROUND(CAST(egl_count AS REAL) * 100 / NULLIF(total_count, 0), 2) AS "egl_percentage(%)",
      ROUND(CAST(vulkan_count AS REAL) * 100 / NULLIF(total_count, 0), 2) AS "vulkan_percentage(%)"
    FROM process_totals
    ORDER BY total_count DESC;
    
  4. 运行查询:点击输入字段附近的运行查询按钮。 查询运行后,结果窗格中会显示一个表格,其中包含进程名称 (process_name)、OpenGL ES 呈现计数 (egl_count)、Vulkan 呈现计数 (vulkan_count)、总呈现计数 (total_count) 以及每个 API 的使用百分比(egl_percentage(%) 和 vulkan_percentage(%))。

    屏幕显示已执行的 SQL 查询以及在表格中显示的渲染 API 指标结果

常见误区

  • 避免 SurfaceFlinger 混淆:始终将搜索范围限定在游戏的应用线程 (RenderThread) 内。SurfaceFlinger 等系统级合成器进程可能会显示代表系统界面渲染(而非游戏内部渲染流水线)的 Vulkan 或 EGL 轨道。如需隔离游戏,请取消注释主 SQL 查询的 WHERE 子句中的可选过滤条件,并将 'com.example.mygame' 替换为游戏的软件包名称:

    -- AND p.name = 'com.example.mygame'
    -- AND t.name = 'RenderThread'
    
  • 预热期:请务必在游戏的主要 3D 场景完全加载之后记录跟踪记录。在启动画面或加载过渡期间进行捕获可能会导致初始化结果具有误导性。

LevelUp 豁免跟踪要求

如果您使用 Android Performance Analyzer (APA) 捕获跟踪记录以获得 Google Play 游戏 LevelUp 免检资格,则必须满足特定的硬件要求,跟踪记录才有效。

强烈建议您使用其中一款目标 Level Up 参考设备来捕获跟踪记录。

此外,为确保验证准确,您的跟踪记录不得在利用 ANGLE GPU 的设备上获取。具体而言,您不能使用以下设备来捕获 LevelUp 免检跟踪记录:

  • GPU 供应商为 SLSI (Samsung) 且使用 AMD Xclipse GPU 的任何设备
  • Pixel 11