案 例 研 究 : 使 用 英 特 尔 GPA 优 化 兵 王 游 戏 的 性 能 英 特 尔 : 卢 卷 彬, Kiefer Kuah 巨 人 : 余 娜 娜 1. 介 绍 兵 王 是 由 巨 人 网 络 公 司 旗 下, 上 海 巨 贤 公 司 耗 时 两 年 自 主 研 发 的 一 款 未 来 战 争 MMORGP 兵 王 使 用 了 优 秀 的 3D 引 擎 技 术, 在 声 光 特 效 方 面 有 极 其 优 秀 的 表 现 为 了 使 兵 王 能 够 流 畅 的 运 行 在 更 多 玩 家 的 机 器 上, 我 们 在 英 特 尔 集 成 显 卡 上 对 游 戏 进 行 了 优 化 英 特 尔 集 成 显 卡 的 出 货 量 非 常 大, 超 过 了 60%(Q3 2011, Jon Peddie Research 统 计 ), 其 性 能 和 特 性 也 日 益 增 强, 是 游 戏 开 发 者 应 该 重 点 关 注 的 对 象 为 了 帮 助 游 戏 开 发 者 在 英 特 尔 集 成 显 卡 上 优 化 游 戏 性 能, 英 特 尔 推 出 了 一 款 出 色 的 免 费 的 性 能 分 析 工 具, 英 特 尔 图 形 性 能 分 析 器 (Graphics Performance Analyzers, 简 称 GPA), 不 用 修 改 游 戏 的 代 码, 不 用 安 装 特 殊 的 驱 动 版 本 就 能 够 使 用 游 戏 开 发 者 可 以 利 用 这 个 工 具 清 晰 的 了 解 自 己 的 游 戏 在 什 么 地 方 耗 费 了 更 多 的 时 间, 以 进 行 有 针 对 性 的 优 化 GPA 是 我 们 在 这 次 优 化 中 使 用 的 主 要 工 具 2. 优 化 准 备 以 下 的 分 析 和 优 化 基 于 Intel HD Graphics 3000 硬 件 平 台, 代 号 Sandybridge( 简 称 SNB),SNB 拥 有 出 色 的 图 形 性 能, 完 全 可 以 满 足 绝 大 多 数 网 络 游 戏 对 性 能 的 需 求 我 们 使 用 的 操 作 系 统 为 Windows 7, 64 位 版 本,GPA 版 本 为 4.2 关 于 优 化 场 景 的 选 择, 兵 王 支 持 大 规 模 的 群 体 作 战, 开 发 者 对 这 种 场 景 下 的 游 戏 性 能 特 别 关 注, 所 以 我 们 选 择 的 是 以 下 的 一 个 群 体 战 斗 场 景, 其 中 有 ~100 个 玩 家, 并 且 有 大 量 的 武 器 和 技 能 特 效, 游 戏 的 性 能 在 这 个 时 候 遇 到 很 大 的 挑 战, 只 有 10fps 左 右, 如 图 1 所 示 : 图 1, 性 能 分 析 和 优 化 的 目 标 场 景, 有 ~100 个 玩 家 和 坐 骑, 大 量 的 技 能 特 效,fps 为 10 左 右
3. GPA 系 统 分 析 器 HUD GPA HUD 可 以 从 平 台 的 角 度 分 析 游 戏 的 性 能, 它 提 供 了 超 过 80 个 关 于 CPU,D3D runtime 和 GPU 的 性 能 指 标, 以 及 Null Hardware,Disable all draw calls, 1x1 ScissorRect, 2x2 Texture,Simple Pixel Shader 等 覆 盖 模 式, 收 集 这 些 性 能 指 标 和 覆 盖 模 式 得 到 的 数 据, 可 以 帮 助 我 们 分 析 出 游 戏 的 瓶 颈 所 在 使 用 GPA HUD 分 析 游 戏 的 这 个 场 景 后 我 们 得 到 以 下 的 结 果 : 游 戏 在 该 场 景 下,FPS 只 能 维 持 在 10 左 右, 此 时 的 Null Hardware 和 Null Driver 覆 盖 模 式 分 别 只 能 达 到 14fps 和 20fps 左 右, 也 就 是 说 显 卡 无 限 快 的 时 候, 游 戏 也 只 能 跑 到 14fps, 因 此 游 戏 在 CPU 上 的 性 能 消 耗 非 常 大 游 戏 有 7800 多 个 draw calls, 这 个 一 个 非 常 大 的 数 字 大 量 的 draw calls, 会 导 致 游 戏 程 序,D3D runtime 以 及 显 卡 驱 动 等 这 些 CPU 上 的 计 算 量 增 加, 由 此 导 致 性 能 非 常 的 低 所 以, 游 戏 在 这 个 场 景 中 的 优 化 重 点, 应 该 是 合 并 小 的 画 图 操 作, 减 少 draw calls 和 State Changes 的 数 量, 这 样 可 以 同 时 减 少 CPU 和 GPU 上 的 负 担 4. GPA 帧 分 析 器 GPA 可 以 抓 取 游 戏 的 一 帧 数 据, 然 后 使 用 帧 分 析 器 进 行 离 线 的 详 细 分 析 帧 分 析 器 打 开 一 帧 的 过 程, 就 相 当 于 是 重 新 发 送 指 令 让 GPU 渲 染 出 这 一 帧 帧 分 析 器 界 面 主 要 包 含 上 部 分 的 柱 状 图 (A), 它 们 代 表 的 是 游 戏 中 按 照 调 用 顺 序 排 列 的 Clear, Draw Primitive,StretchRect 等, 我 们 统 称 为 ergs, 可 以 通 过 设 置 X 轴 和 Y 轴 来 快 速 的 定 位 最 耗 时 的 调 用, 比 如 X 轴 设 为 GPU Duration,Y 轴 设 为 GPU Breakdown 界 面 左 边 中 间 (B) 是 所 有 ergs 的 列 表, 左 边 下 面 (C) 是 Render Target, 右 边 下 面 (D) 是 一 系 列 Tab, 包 括 性 能 数 据,ergs 的 纹 理,shader,state,API log 等 等 我 们 在 目 标 场 景 中 抓 取 了 一 帧 数 据, 下 图 2 是 使 用 帧 分 析 器 打 开 这 帧 数 据 的 界 面 : 图 2, 帧 分 析 器 打 开 场 景 的 界 面
从 图 2 所 示 的 帧 分 析 器 界 面 我 们 可 以 看 出, 渲 染 这 一 帧 GPU 花 费 的 时 间 为 71ms 游 戏 的 渲 染 步 骤 是 先 生 成 阴 影 贴 图 (0-1198), 然 后 是 正 常 场 景 的 渲 染, 最 后 是 后 处 理 以 及 UI 部 分 阴 影 贴 图 使 用 了 1198 个 draw calls, 通 过 GPA 帧 分 析 器 的 纹 理 tab 可 以 查 看 这 些 draw calls 所 使 用 的 纹 理, 我 们 发 现, 游 戏 对 某 些 特 效 也 计 算 了 阴 影 : 图 3, 生 成 阴 影 贴 图 的 draw calls 中, 发 现 了 特 效 的 纹 理, 游 戏 对 特 效 也 计 算 了 阴 影 如 图 3 所 示, 选 中 的 那 个 纹 理, 以 及 相 邻 的 纹 理, 都 是 特 效 相 关 的, 而 游 戏 设 计 之 初 并 没 有 要 求 计 算 它 们 的 阴 影, 可 以 移 除 掉 另 外, 游 戏 花 费 了 5526 个 draw calls 来 渲 染 场 景 中 的 所 有 物 体, 占 了 整 个 一 帧 的 72.6% 的 时 间 这 5526 个 draw calls 中, 有 超 过 4000 个 是 渲 染 特 效 部 分, 它 们 占 用 了 整 个 一 帧 44.9% 的 时 间, 这 是 优 化 的 重 点 目 标, 如 图 4 所 示, 在 界 面 的 render target 那 里 可 以 看 到 所 有 的 特 效 : 图 4, 渲 染 特 效 的 draw calls 有 4079 个, 占 用 一 帧 44.9% 的 时 间
通 过 查 看 和 分 析 这 些 特 效, 我 们 发 现 每 一 个 特 效 的 draw call 所 渲 染 的 东 西 都 是 非 常 小 的, 而 且 它 们 所 使 用 纹 理, 多 数 都 是 小 纹 理, 如 下 所 示 : 图 5, 特 效 的 draw call 都 很 小,10 个 draw calls 只 渲 染 了 一 小 部 分 特 效 上 图 5 中, 选 中 的 这 10 个 相 邻 的 draw calls 使 用 的 都 是 这 个 128*128 的 蓝 色 纹 理, 所 渲 染 的 东 西 也 是 相 邻 的, 我 们 可 以 考 虑 合 并 这 几 个 draw calls 同 时, 考 虑 到 纹 理 比 较 小, 我 们 还 可 以 合 并 相 邻 的 特 效 纹 理, 这 样 可 以 减 少 SETTEXTURE 的 次 数, 也 减 少 了 CPU 端 的 消 耗 坐 骑 和 人 物 部 分 的 渲 染, 也 划 分 得 很 细, 头 发, 脸 孔, 衣 服, 武 器 等 都 是 由 单 独 的 draw call 完 成 这 些 也 可 以 进 行 适 当 的 合 并, 从 而 减 少 draw calls 和 state changes 的 数 量 5. 优 化 策 略 和 结 果 : 5.1 移 除 特 效 的 阴 影 计 算 如 前 面 的 图 3 所 示, 游 戏 中 对 特 效 也 计 算 了 实 时 阴 影, 一 般 来 说, 特 效 是 不 需 要 计 算 阴 影 的 移 除 掉 这 些 draw calls 后, 生 成 阴 影 贴 图 的 draw calls 从 1198 个 减 少 到 了 860 个, 这 部 分 的 GPU 时 间 消 耗 从 6.5ms 减 少 到 了 4.86ms 5.2 合 并 特 效 draw calls 和 纹 理 由 前 面 的 分 析 我 们 知 道, 要 优 化 游 戏 在 该 场 景 下 的 性 能, 最 重 要 的 就 是 减 少 CPU 端 的 消 耗, 也 就 是 要 减 少 游 戏 的 draw calls 和 State Changes 的 数 量 场 景 中 特 效 的 draw calls 数 量 是 最 多 的, 而 且 特 效 的 draw calls 都 是 非 常 小 的, 所 以 我 们 首 先 来 合 并 特 效 的 draw calls
图 6, 优 化 前, 使 用 了 37 个 draw calls 来 完 成 右 边 的 特 效 图 7, 优 化 后, 对 特 效 的 顶 点 和 纹 理 都 进 行 了 合 并, 使 用 一 个 draw call 就 完 成 了 类 似 的 特 效 从 以 上 图 6 和 图 7 的 对 比 我 们 看 到, 合 并 优 化 后, 渲 染 相 同 的 特 效, 我 们 减 少 了 draw calls 的 数 量, 从 37 减 少 到 1, 纹 理 也 从 4 个 合 并 到 1 个 整 个 一 帧, 特 效 的 draw calls 数 量 从 4000 多 次 减 少 到 了 700 多 次,set texture 的 次 数 从 3764 减 少 到 2029 次 整 个 特 效 部 分 的 GPU 时 间 从 45ms 减 少 到 了 21ms, 提 升 非 常 明 显! 下 图 8 为 优 化 后 的 结 果 :
图 8, 优 化 后 整 个 特 效 部 分 的 draw call 数 量 减 少 到 了 706 个 左 右, 特 效 的 GPU 时 间 从 45ms 减 少 到 了 21ms 5.3 合 并 人 物 和 坐 骑 的 渲 染 游 戏 对 人 物 的 渲 染 区 分 很 细, 帽 子, 头 发, 衣 服, 裤 子, 鞋 子, 武 器 等 都 由 独 立 的 draw calls 来 完 成, 对 坐 骑 也 是 由 3 个 draw calls 来 完 成 的, 虽 然 他 们 使 用 的 是 同 样 的 纹 理 以 下 以 坐 骑 为 例, 将 优 化 前 需 要 3 个 draw calls 完 成 的 渲 染, 合 并 为 一 个 draw call 来 完 成 图 9, 优 化 前, 使 用 了 3 个 draw calls 来 完 成 一 个 坐 骑 的 渲 染
图 10, 优 化 后, 合 并 了 坐 骑 的 IB 和 VB, 使 用 一 个 draw call 就 能 完 成 坐 骑 的 渲 染 如 上 图 9 和 图 10 所 示, 优 化 前 需 要 用 3 个 draw calls 来 完 成 一 个 坐 骑 的 渲 染, 我 们 合 并 了 坐 骑 的 IB 和 VB, 优 化 后 只 需 要 一 个 draw call 就 完 成 了 这 个 坐 骑 的 渲 染 整 个 一 帧 有 ~100 个 坐 骑, 合 并 优 化 后, 节 省 了 ~200 个 draw calls 我 们 针 对 人 物 也 进 行 了 类 似 的 合 并 优 化, 也 节 省 了 200 个 左 右 的 draw calls 5.4 移 除 重 复 的 SETTEXTURE 为 了 减 少 CPU 端 的 消 耗, 我 们 还 应 该 尽 量 减 少 state changes 的 数 量, 在 帧 分 析 器 对 另 外 一 个 场 景 的 分 析 中, 我 们 发 现, 每 个 draw call 都 会 设 置 自 己 所 需 要 的 所 有 纹 理, 而 不 管 是 否 和 上 一 个 draw call 使 用 了 相 同 的 纹 理
图 11, 相 邻 的 2 个 draw calls, 使 用 一 样 的 纹 理, 但 是 他 们 都 重 新 设 置 了 一 次 如 图 11 所 示, 柱 状 图 中 选 中 的 临 近 的 2 个 draw call, 是 在 画 地 形 部 分, 即 使 它 们 使 用 的 是 完 全 相 同 的 纹 理, 它 们 也 都 重 新 调 用 了 5 次 完 整 的 的 SETTEXTURE API 该 场 景 中 整 个 一 帧 总 共 有 1837 个 SETTEXTURE API 调 用 这 不 是 有 效 率 的 做 法, 如 果 相 邻 的 draw call 使 用 的 是 同 样 的 纹 理, 可 以 不 用 调 用 SETTEXTURE 再 次 设 置, 这 样 可 以 减 少 state changes 的 数 量, 提 高 游 戏 性 能 以 下 是 优 化 后 的 截 图, 移 除 掉 了 重 复 的 不 必 要 的 SETTEXTURE API 调 用, 如 图 12 所 示, 第 二 个 地 形 draw call 本 身 已 经 没 有 调 用 set texture 了 经 过 优 化 后, 整 个 一 帧 所 调 用 的 SETTEXTURE API 次 数 从 1837 次 减 少 到 了 554 次
图 12, 优 化 后, 如 果 纹 理 没 有 变 化, 则 不 重 复 设 置 了 经 过 以 上 几 种 优 化, 我 们 把 兵 王 在 这 个 场 景 下 的 draw calls 数 量 从 7839 次 减 少 到 了 3812 次,SETTEXTURE API 调 用 次 数 从 3764 次 减 少 到 了 2029 次 游 戏 帧 率 从 10fps 提 升 到 了 20fps 左 右, 基 本 能 够 流 畅 的 运 行, 达 到 了 游 戏 开 发 者 的 期 望 6. 总 结 : 本 文 介 绍 了 使 用 GPA 对 兵 王 进 行 性 能 分 析 和 优 化 的 过 程, 从 中 我 们 可 以 看 出, 游 戏 客 户 端 的 性 能 优 化 并 不 难, 我 们 所 使 用 的 优 化 方 法 也 都 很 常 见, 但 重 要 的 是 如 何 很 快 的 找 到 这 些 游 戏 热 点 和 瓶 颈 在 兵 王 的 性 能 分 析 和 优 化 过 程 中,GPA 发 挥 了 非 常 重 要 的 作 用, 通 过 它 我 们 很 容 易 就 发 现 了 游 戏 的 瓶 颈, 进 行 针 对 性 的 优 化, 游 戏 的 性 能 得 到 了 很 大 的 提 升 我 们 将 继 续 使 用 GPA 进 一 步 优 化 游 戏 作 者 简 介 卢 卷 彬 英 特 尔 公 司 的 应 用 工 程 师, 他 和 国 内 几 家 大 的 游 戏 公 司 有 着 多 年 的 合 作, 帮 助 他 们 在 英 特 尔 平 台 上 优 化 游 戏 客 户 端 的 性 能 余 娜 娜 巨 人 前 传 技 术 部 经 理, 参 与 开 发 过 3DRPG 仙 剑 奇 侠 传 三 - 问 情 篇,3DMMORPG 巨 人 兵 王 主 要 致 力 于 3D 引 擎 的 研 制 开 发, 与 Intel 的 几 年 合 作 中, 极 大 提 升 了 自 主 研 发 的 3D 引 擎 的 特 性, 在 效 果 提 升 的 基 础 上, 同 屏 人 数 也 大 大 提 升 Kiefer Kuah 英 特 尔 的 软 件 工 程 师, 他 主 要 负 责 游 戏 在 英 特 尔 平 台 上 的 优 化 工 作