使用 AMD Radeon™ GPU Detective 进行硬件崩溃分析

最初发布:
Amit Ben-Moshe's avatar
Amit Ben-Moshe

AMD Radeon™ GPU Detective (RGD) v1.4 版本(AMD 用于 GPU 崩溃事后分析的工具)带来了一项强大的新功能:硬件崩溃分析。启用后,RGD 会收集 GPU 崩溃时的低级硬件状态信息,并丰富崩溃分析 (.rgd) 输出文件中的信息,提供有意义的见解。

硬件崩溃分析有什么新内容?

新增已飞行着色器的执行标记

在 RGD v1.3 及之前版本中,执行标记树中的每个执行标记只能有 3 种状态之一

[X] finished
[>] in progress
[ ] not started

通过硬件崩溃分析,添加了第四种执行标记状态。RGD 会将飞行中的波前 (wavefronts) 与执行标记关联起来,并用 [#] 符号标记在崩溃期间有正在运行波前的节点。

[#] shader in flight

考虑以下 Direct3D® 12 应用程序的示例执行标记树

Legend
======
[X] finished
[>] in progress
[ ] not started
Command Buffer ID: 0xb14 (Queue type: Direct)
=============================================
[>] "Frame 694 CL0"
├─[>] "DownSamplePS"
│ ├─[X] ----------Barrier----------
│ ├─[X] Draw(VertexCount=3, InstanceCount=1)
│ ├─[X] Draw(VertexCount=3, InstanceCount=1)
│ ├─[X] Draw(VertexCount=3, InstanceCount=1)
│ ├─[>] Draw(VertexCount=3, InstanceCount=1)
│ ├─[>] Draw(VertexCount=3, InstanceCount=1)
│ └─[>] ----------Barrier----------
├─[>] "Bloom"
│ ├─[>] "BlurPS"
│ │ ├─[>] ----------Barrier----------
│ │ ├─[>] Draw(VertexCount=3, InstanceCount=1)
│ │ ├─[>] ----------Barrier----------
│ │ ├─[>] Draw(VertexCount=3, InstanceCount=1)
│ │ └─[>] ----------Barrier----------
│ ├─[>] ----------Barrier----------
│ ├─[>] Draw(VertexCount=3, InstanceCount=1)
│ ├─[>] ----------Barrier----------
│ ├─[>] "BlurPS"
│ │ ├─[>] ----------Barrier----------
│ │ ├─[>] Draw(VertexCount=3, InstanceCount=1)
│ │ ├─[>] ----------Barrier----------
│ │ ├─[>] Draw(VertexCount=3, InstanceCount=1)
│ │ └─[ ] ----------Barrier----------
│ ├─[ ] ----------Barrier----------

上面的执行标记树已经为我们识别出可疑的绘制调用指明了方向。它可以是“进行中”([>]) 的标记中的任何一个。有很多正在进行的绘制调用,但考虑到崩溃期间可能有大量的绘制调用在飞行中,仅缩小到几个潜在可疑的绘制调用本身就是一项巨大的时间节省。

然而,正如您在下面看到的,硬件崩溃分析功能将我们带得更远,它识别出在崩溃期间由正在飞行的着色器执行的“进行中”标记。当启用硬件崩溃分析捕获 AMD GPU 崩溃转储 (.rgd 文件) 时,相同的执行标记树将显示如下:

Legend
======
[X] finished
[>] in progress
[#] shader in flight
[ ] not started
Command Buffer ID: 0xb14 (Queue type: Direct)
=============================================
[>] "Frame 694 CL0"
├─[>] "DownSamplePS"
│ ├─[X] ----------Barrier----------
│ ├─[X] Draw(VertexCount=3, InstanceCount=1)
│ ├─[X] Draw(VertexCount=3, InstanceCount=1)
│ ├─[X] Draw(VertexCount=3, InstanceCount=1)
│ ├─[#] Draw(VertexCount=3, InstanceCount=1) <-- has a correlated running wave <SHADER INFO section IDs: {ShaderInfoID1}, API PSO hash = 0x3f0dcc77cb4a94c6, API stages: {Pixel}>
│ ├─[#] Draw(VertexCount=3, InstanceCount=1) <-- has a correlated running wave <SHADER INFO section IDs: {ShaderInfoID1}, API PSO hash = 0x3f0dcc77cb4a94c6, API stages: {Pixel}>
│ └─[>] ----------Barrier----------
├─[>] "Bloom"
│ ├─[>] "BlurPS"
│ │ ├─[>] ----------Barrier----------
│ │ ├─[>] Draw(VertexCount=3, InstanceCount=1)
│ │ ├─[>] ----------Barrier----------
│ │ ├─[>] Draw(VertexCount=3, InstanceCount=1)
│ │ └─[>] ----------Barrier----------
│ ├─[>] ----------Barrier----------
│ ├─[>] Draw(VertexCount=3, InstanceCount=1)
│ ├─[>] ----------Barrier----------
│ ├─[>] "BlurPS"
│ │ ├─[>] ----------Barrier----------
│ │ ├─[>] Draw(VertexCount=3, InstanceCount=1)
│ │ ├─[>] ----------Barrier----------
│ │ ├─[>] Draw(VertexCount=3, InstanceCount=1)
│ │ └─[ ] ----------Barrier----------
│ ├─[ ] ----------Barrier----------

注意 RGD 如何将潜在的罪魁祸首列表缩小到“DownSamplePS”子树中的仅两个特定的绘制调用。此外,RGD 现在识别出崩溃着色器的 API 阶段(本例中为像素着色器)、着色器正在执行的 API 管道(通过哈希字符串)以及着色器本身(稍后将在下一节中详细介绍)。

关于崩溃着色器的详细信息

正如您所见,飞行中执行标记的注释包含对 ShaderInfoID1 的引用。这是一个句柄,您可以使用它跳转到我们添加到 RGD 输出文件中的一个新部分:SHADER INFO 部分。名称 ShaderInfoID1 是任意的。它的目的是作为 RGD 输出文本文件范围内的唯一字符串标识符,允许您在搜索该字符串时快速跳转到文本文件的相关部分。

让我们看一下同一个崩溃的 Direct3D® 12 应用程序的新 SHADER INFO 部分,它通常出现在 RGD 输出文本文件的末尾

===========
SHADER INFO
===========
Shader info ID : ShaderInfoID1
API PSO hash : 0x3f0dcc77cb4a94c6
API shader hash: 0x9e7e544426c404defd8c0ea8a6f65c3b
API stage : Pixel
Disassembly
===========
.
.
.
v_interp_p2_f32 v2, v3, v1, v0 wait_exp:7 // 000000000360: CD010702 04020303
s_mov_b32 s4, s5 // 000000000368: BE840005
s_mov_b32 s5, s9 // 00000000036C: BE850009
s_load_b256 s[4:11], s[4:5], null // 000000000370: F40C0102 F8000000
s_waitcnt lgkmcnt(0) // 000000000378: BF89FC07
v_mul_f32_e64 v3, 2.0, s0 // 00000000037C: D5080003 000000F4
v_mul_f32_e64 v0, 2.0, s1 // 000000000384: D5080000 000002F4
s_delay_alu instid0(VALU_DEP_2) | instskip(NEXT) | instid1(VALU_DEP_2)// 00000000038C: BF870112
v_sub_f32_e32 v1, v4, v3 // 000000000390: 08020704
v_sub_f32_e32 v3, v2, v0 // 000000000394: 08060102
v_fma_f32 v0, s0, 2.0, v4 // 000000000398: D6130000 0411E800
v_fma_f32 v6, s1, 2.0, v2 // 0000000003A0: D6130006 0409E801
s_mov_b32 s12, 0x8007092 // 0000000003A8: BE8C00FF 08007092
s_mov_b32 s13, 0xfff000 // 0000000003B0: BE8D00FF 00FFF000
s_mov_b32 s14, 0x64500000 // 0000000003B8: BE8E00FF 64500000
s_mov_b32 s15, 0x80000000 // 0000000003C0: BE8F00FF 80000000
s_clause 0x8 // 0000000003C8: BF850008
> image_sample v[8:11], [v0, v6], s[4:11], s[12:15] dmask:0xf dim:SQ_RSRC_IMG_2D// 0000000003CC: F06C0F05 0C010800 00000006 <-- ***PAGE FAULT SUSPECT (128 waves)***
image_sample v[12:15], [v4, v6], s[4:11], s[12:15] dmask:0xf dim:SQ_RSRC_IMG_2D// 0000000003D8: F06C0F05 0C010C04 00000006
image_sample v[18:21], [v1, v6], s[4:11], s[12:15] dmask:0xf dim:SQ_RSRC_IMG_2D// 0000000003E4: F06C0F05 0C011201 00000006
image_sample v[22:25], [v0, v2], s[4:11], s[12:15] dmask:0xf dim:SQ_RSRC_IMG_2D// 0000000003F0: F06C0F05 0C011600 00000002
image_sample v[26:29], [v4, v2], s[4:11], s[12:15] dmask:0xf dim:SQ_RSRC_IMG_2D// 0000000003FC: F06C0F05 0C011A04 00000002
image_sample v[30:33], v[1:2], s[4:11], s[12:15] dmask:0xf dim:SQ_RSRC_IMG_2D// 000000000408: F06C0F04 0C011E01
image_sample v[34:37], [v0, v3], s[4:11], s[12:15] dmask:0xf dim:SQ_RSRC_IMG_2D// 000000000410: F06C0F05 0C012200 00000003
image_sample v[4:7], [v4, v3], s[4:11], s[12:15] dmask:0xf dim:SQ_RSRC_IMG_2D// 00000000041C: F06C0F05 0C010404 00000003
image_sample v[0:3], [v1, v3], s[4:11], s[12:15] dmask:0xf dim:SQ_RSRC_IMG_2D// 000000000428: F06C0F05 0C010001 00000003
s_cmp_eq_i32 s2, 0 // 000000000434: BF008002
s_cbranch_scc1 _L5 // 000000000438: BFA20041
s_waitcnt vmcnt(7) // 00000000043C: BF891FF7
v_add_f32_e32 v8, v8, v12 // 000000000440: 06101908
v_add_f32_e32 v9, v9, v13 // 000000000444: 06121B09
v_add_f32_e32 v10, v10, v14 // 000000000448: 06141D0A
v_add_f32_e32 v11, v11, v15 // 00000000044C: 06161F0B
s_waitcnt vmcnt(6) // 000000000450: BF891BF7
s_delay_alu instid0(VALU_DEP_4) | instskip(NEXT) | instid1(VALU_DEP_4)// 000000000454: BF870214
v_add_f32_e32 v8, v18, v8 // 000000000458: 06101112
.
.
.

您可以看到 SHADER INFO 部分仅包含一个着色器 (ShaderInfoID1),这与执行标记树匹配。除了着色器元数据之外,您还可以看到崩溃着色器反汇编的相关子集。如果崩溃是由着色器触发的页面错误引起的,RGD 将在相关反汇编行中用 [>] 前缀标记有问题的指令,并带有标记页面错误罪魁祸首嫌疑以及崩溃时执行该指令的波前数量的注释。默认情况下,该工具仅在输出文件中包含着色器反汇编的相关子集,以尽量减少噪音。在页面错误嫌疑指令周围,您会找到少量指令,以提供该指令执行的上下文。垂直的 . . . 线表示已过滤的指令。如果您确实需要查看完整的着色器反汇编,可以通过手动运行 rgd 命令行工具并将 AMD GPU 崩溃转储 (.rgd) 文件作为输入,并使用 --all-disassembly 命令行选项来实现(有关更多信息,请运行 rgd -h 查看 rgd 命令行工具帮助手册)。

如何开始使用硬件崩溃分析

  1. 请确保您已安装最新版本的 AMD Software: Adrenalin Edition™(25.3.1 或更高版本)。
  2. 下载 RGD v1.4 或更高版本以及 AMD Radeon™ Developer Panel (RDP) v3.3 或更高版本:这两个工具都是 AMD Radeon™ Developer Tool Suite 的一部分,可以使用 此链接 下载。
  3. 在通过 RDP 启用崩溃分析时,请确保启用了硬件崩溃分析设置。在配备独立 GPU 的系统上运行时,默认情况下将启用此选项。APU 的支持将在未来的版本中添加。有关 RGD 和硬件崩溃分析的更多信息,请参阅 RGD 产品文档

明确排除和未来功能

为了使该工具能够检索您 GPU 崩溃案例的其他低级信息,需要完成一些工作。首先,您必须确保在 Radeon Developer Panel (RDP) 的崩溃分析选项卡中选中了硬件崩溃分析复选框(默认情况下已选中)。此外,由于此版本工具侧重于有问题的着色器,因此 GPU 崩溃显然需要由着色器执行的硬件块触发。如果 GPU 崩溃发生在其他地方,则执行树标记将不关联任何着色器,您将无法获得新硬件崩溃分析模式的优势。但是,如果您的崩溃案例得到 RGD 的支持,您可以依靠“标准”(RGD v1.3)信息,无论硬件崩溃分析功能是否适用于您的崩溃案例。

另外,请注意 RGD 目前在此新模式下仅提供低级信息。诸如崩溃着色器的高级或中间源代码之类的信息不包含在内。我们希望在未来的版本公告中与您分享有关这些令人兴奋的功能的更新——敬请关注!

Amit Ben-Moshe's avatar

Amit Ben-Moshe

Amit Ben-Moshe 是 AMD 的杰出工程师。他的发帖内容代表他个人的观点,可能不代表 AMD 的立场、策略或观点。第三方网站链接仅为方便起见提供,除非明确说明,否则 AMD 对这些链接网站的内容概不负责,也不暗示任何认可。

相关新闻和技术文章

© . This site is unofficial and not affiliated with AMD.