跳至内容

帮助手册

The Radeon™ GPU Detective

Radeon GPU Detective (RGD) 是一款帮助开发者进行 GPU 崩溃事后分析的工具。该工具允许开发者生成和分析 AMD GPU 崩溃转储,并生成有助于缩小崩溃根本原因搜索范围的信息。该工具生成的崩溃分析报告中包含的一些信息:

  • 崩溃期间执行的每个命令缓冲区的执行标记,指向渲染通道和绘制调用。

  • 对于被识别为由页面错误引起的崩溃,将提供有问题的虚拟地址以及驻留在相关地址范围内的所有资源的有关信息。

系统要求

  • 操作系统:Windows® 10 或 11。

  • GPU:RDNA™2 (RX 6000 系列)、RDNA™3 (RX 7000 系列) 或 RDNA™ 4 (RX 9000 系列) 卡。

  • 驱动程序:支持崩溃分析的 Radeon Adrenalin™ 驱动程序。

  • 您将需要一个导致 GPU 崩溃的游戏或其他应用程序(目前该工具支持 **Direct3D 12** 或 **Vulkan** API)。

  • 为了充分利用该工具,应用程序应

  • 在渲染通道周围使用字符串标记: - D3D12:使用 AMD GPU Services (AGS) 库 - 与 RGP 支持的相同。

    • Vulkan:使用 VK_EXT_debug_utils 扩展 - 函数 vkCmdBeginDebugUtilsLabelEXTvkCmdEndDebugUtilsLabelEXT

  • 为 GPU 资源(堆、缓冲区、纹理)命名,因为这些字符串会出现在崩溃分析摘要文件中,并且在发生页面错误时有助于识别相关资源: - D3D12:使用 ID3D12Object::SetName()

    • Vulkan:使用 VK_EXT_debug_utils 扩展 - 函数 vkSetDebugUtilsObjectNameEXT

使用工具

生成 AMD GPU 崩溃转储

有关如何捕获 AMD GPU 崩溃转储文件(.rgd 文件)并生成崩溃分析摘要文件(文本/JSON),请参阅 快速入门指南

崩溃分析摘要文件

RGD 命令行工具 (rgd.exe) 可以解析 AMD GPU 崩溃转储文件(.rgd 文件),并生成文本或 JSON 格式的崩溃分析报告文件。文本和 JSON 摘要文件包含相同的信息,但表示方式不同。JSON 格式可用于自动化处理崩溃报告。为简单起见,此处将引用人类可读的文本输出。

RGD 崩溃分析文本摘要文件使用 UTF-8 编码,并使用一些 Unicode 字符打印执行标记树,因此请确保使用支持该格式的文本编辑器,例如 Microsoft® Visual Studio Code。

RGD 崩溃分析输出文件默认包含以下信息:

  • 有关崩溃分析摘要文件和会话的元数据

  • 系统信息(CPU、GPU、驱动程序、操作系统等)。

  • 崩溃期间处于活动状态的每个命令缓冲区的执行标记树,指向渲染通道和绘制调用。

  • 进行中的标记摘要(类似于执行标记树,但没有层级结构,仅包含崩溃期间正在进行的执行标记)。

  • 页面错误摘要(针对被确定为由页面错误引起的崩溃。否则,工具会明确说明未观察到页面错误)。

以下是关于崩溃分析文件内容的更多详细信息:

崩溃分析文件信息

此部分标题为 CRASH ANALYSIS FILE,包含当前摘要报告和崩溃进程的信息。

  • 输入崩溃转储文件名:生成此文件的 .rgd 文件的完整路径。

  • 输入崩溃转储文件创建时间:崩溃转储 (.rgd) 文件的创建时间。

  • 使用的 RGD CLI 版本:用于生成此摘要文件的 RGD 命令行工具版本。

  • 崩溃分析文件格式版本:当前文件的架构版本。

  • 崩溃进程 ID:崩溃应用程序的进程 ID。

  • 崩溃的可执行文件完整路径:崩溃应用程序可执行文件的完整路径。

  • API:崩溃应用程序使用的 API(DirectX 12 或 Vulkan)。

  • PDB 文件(仅限 DX12):用于生成崩溃分析摘要报告的 PDB 文件列表。

  • 硬件崩溃分析:捕获崩溃转储时是否启用了硬件崩溃分析功能。

系统信息

此部分标题为 SYSTEM INFO,包含有关崩溃发生的系统的的信息:

  • 操作系统信息

  • 图形驱动程序信息

  • 活动的驱动程序实验列表

  • 已安装CPU的详细信息

  • 已安装GPU的详细信息

崩溃分析的驱动程序实验

RGD v1.3 支持一项强大的新功能,称为驱动程序实验,它允许您切换某些驱动程序功能和优化,从而在不修改源代码或配置的情况下更改应用程序的行为。这是通过控制 Radeon Adrenalin 驱动程序低级行为的驱动程序实验来完成的。这些实验控制着光线追踪或网格着色器支持、编译器优化等功能,对于调试 GPU 崩溃非常有用。

AMD GPU 崩溃转储(.rgd 文件)会记录崩溃分析会话期间活动的驱动程序实验列表,以便您始终了解应用程序崩溃时的驱动程序配置。RGD 的崩溃分析输出摘要文本文件将在“系统信息”部分显示活动的驱动程序实验列表。此信息也可在 RGD 的机器可读 JSON 输出文件中获得。有关此功能的更多详细信息,请参阅 快速入门指南

有关每个支持实验的详细描述,请参阅 RDP 文档的驱动程序实验部分

以下是活动的驱动程序实验示例:

===========
SYSTEM INFO
===========
Driver info
===========
...
Experiments : total of 4 Driver Experiments were active while capturing the AMD GPU crash dump:
1. Disable sampler feedback support
2. Disable raytracing support
3. Disable variable rate shading
4. Hull shader wave size: Force 32 threads per wave

进行中的标记

此部分标题为 MARKERS IN PROGRESS包含崩溃期间处于活动状态的每个命令缓冲区的执行标记信息。以下是此部分内容的示例:

Command Buffer ID: 0x617
========================
Frame 362 CL0/DownSamplePS/Draw [5 repeating occurrences]
Frame 362 CL0/DownSamplePS/Barrier
Frame 362 CL0/Bloom/BlurPS/Barrier
Frame 362 CL0/Bloom/BlurPS/Draw [2 repeating occurrences]

请注意,标记层级由 / 分隔,形成类似于文件系统层级结构的“路径”,例如 marker/marker/draw_call

执行标记树

此部分标题为 EXECUTION MARKER TREE,包含一个描述崩溃期间处于活动状态的每个命令缓冲区的标记状态的树。

用户提供的标记字符串将用 "" 括起来。由 AMD 组件自动生成的其他标记将按原样显示,不带 ""

以下是执行标记树的示例:

Command Buffer ID: 0x617 (Queue type: Direct)
=============================================
[>] "Frame 362 CL0"
├─[X] "Depth + Normal + Motion Vector PrePass"
├─[X] "Shadow Cascade Pass"
├─[X] "TLAS Build"
├─[X] "Classify tiles"
├─[X] "Trace shadows"
├─[X] ----------Barrier----------
├─[X] "Denoise shadows"
├─[X] "GltfPbrPass::DrawBatchList"
├─[X] "Skydome Proc"
├─[X] "GltfPbrPass::DrawBatchList"
├─[>] "DownSamplePS"
│ ├─[X] ----------Barrier----------
│ ├─[>] Draw(VertexCount=3, InstanceCount=1)
│ ├─[>] Draw(VertexCount=3, InstanceCount=1)
│ ├─[>] Draw(VertexCount=3, InstanceCount=1)
│ ├─[>] Draw(VertexCount=3, InstanceCount=1)
│ ├─[>] Draw(VertexCount=3, InstanceCount=1)
│ └─[>] ----------Barrier----------
├─[>] "Bloom"
│ ├─[>] "BlurPS"
│ │ ├─[>] ----------Barrier----------
│ │ ├─[>] Draw(VertexCount=3, InstanceCount=1)
│ │ ├─[>] Draw(VertexCount=3, InstanceCount=1)
│ │ └─[ ] ----------Barrier----------
│ ├─[ ] ----------Barrier----------
│ ├─[ ] Draw(VertexCount=3, InstanceCount=1)
│ ├─[ ] Draw(VertexCount=3, InstanceCount=1)
│ ├─[ ] "BlurPS"
│ ├─[ ] Draw(VertexCount=3, InstanceCount=1)
│ └─[ ] ----------Barrier----------
└─[ ] "Indirect draw simple"

执行标记状态由以下符号表示:

  • [X] 已完成

  • [>] 进行中

  • [#] 着色器进行中

  • [ ] 未开始

状态(未开始、进行中、已完成)是根据 GPU 驱动程序从命令列表中获取并经过 GPU 流水线各个阶段执行的命令确定的,这不仅仅包括着色器的执行。这意味着即使在它们之间存在障碍,进一步的通道和绘制调用也可能在开始执行着色器之前显示为 in progress

当通道和绘制调用标记显示为 in progress(或 shader in flight)时:

  • 如果它们旨在并行执行(例如,将 3D 对象绘制到 G 缓冲区),那么它们在崩溃时可能确实处于进行中状态,并且任何一个都可能是导致崩溃的原因。

  • 如果它们已知串行执行且它们之间存在障碍(例如,屏幕空间后处理通道),那么第一个 in progress(或 shader in flight)标记很可能是正在执行其着色器的那个,当时发生了崩溃。

执行标记树功能

  • 线程组计数适用于计算调度。

  • 队列类型设置为“Direct”表示图形队列,“Compute”表示计算队列。

  • 顶点和实例计数适用于绘制调用。

  • 索引和实例计数适用于索引绘制调用。

  • 在文本摘要输出中,障碍物会用虚线打印,以在障碍物集之间进行视觉分隔。

  • 当使用启用了 hardware_crash_analysis 功能的硬件捕获崩溃转储时,会添加一个新的标记状态 shader in flight

树结构和内容也可以通过 RDP 选项(或直接运行 RGD 命令行工具时使用命令行选项)进行配置:

  • 选中“显示执行标记源”复选框(或使用 --marker-src 命令行选项),以显示指定标记来源组件的后缀(例如,对于源自崩溃应用程序源代码的用户标记,可能是 [App])。

  • 选中“展开所有执行标记节点”复选框(或使用 --expand-markers 命令行选项),以展开所有节点。请注意,RGD 会折叠所有子节点均处于完成状态的节点,以消除噪音并提高树的可读性。

页面错误摘要

如果崩溃被确定是由页面错误引起的,本节将列出发生页面错误的有问题的虚拟地址 (VA)。否则,将明确说明未检测到页面错误。

除了有问题的 VA 之外,本节还将提供有关曾经驻留在该地址的任何资源的有关信息,或明确说明在崩溃应用程序的生命周期内从未有资源驻留在该地址。

如果崩溃被检测为由页面错误引起,并且资源确实在崩溃应用程序的生命周期内驻留在相关 VA 中,则还将添加以下部分:

资源时间线

资源时间线按时间顺序列出了相关事件(例如 CreateMakeResidentDestroy),这些事件适用于在崩溃应用程序的生命周期内曾经驻留在相关 VA 中的所有资源。

以下是资源时间线的示例:

Timestamp Event type Resource type Resource identifier Resource size Resource name
--------- ---------- ------------- ------------------- ------------- -------------
00:00:00.7989056 Create Buffer 0xfcf3bdca0000014f 671088640 (640.00 MB) VidMemBuffer
00:00:00.8009888 Bind Buffer 0xfcf3bdca0000014f 671088640 (640.00 MB) VidMemBuffer
00:00:00.8009888 Make Resident Buffer 0xfcf3bdca0000014f 671088640 (640.00 MB) VidMemBuffer
00:00:06.2607520 Destroy Buffer 0xfcf3bdca0000014f 671088640 (640.00 MB) VidMemBuffer

Resource timeline 部分的字段是:

  • 时间戳:自崩溃分析会话开始以来的事件时间戳,格式为 HH:MM:SS.Ticks

  • 事件类型:事件的类型(例如 Create、MakeResident 和 Destroy)。

  • 资源类型:资源的类型(例如 buffer 或 image)。

  • 资源标识符:资源 ID(与 RMV 中该资源的 ID 相同)。

  • 资源大小:资源的大小。

  • 资源名称:资源的名称(假设资源已由开发人员使用 ID3D12Object::SetName() for DX12 memory objects 或使用 vkSetDebugUtilsObjectNameEXT() for Vulkan memory objects 命名)。

相关资源

在崩溃应用程序的生命周期内曾经驻留在受影响 VA 中的每个资源也将在 Associated resources 部分列出。此部分将为您提供更多详细信息,用于识别可能导致页面错误的有关资源。

以下是 Associated resources 部分中 Image 的示例:

Resource id: 0x5a49f0600000a7f
Type: Image
Name: Postprocessing render target 4
Virtual address:
0x236c00000 [size: 16810352 (16.03 MB), parent address + offset: 0x236c00000 + 0x0, preferred heap: Local (GPU memory, CPU-visible)]
Commit type: COMMITTED
Attributes:
Create flags: PREFER_SWIZZLE_EQUATIONS | FIXED_TILE_SWIZZLE (24576)
Usage flags: SHADER_READ | SHADER_WRITE | RESOLVE_DESTINATION | COLOR_TARGET (27)
Image type: 2D
Dimensions <x, y, z>: 1920 x 1080 x 1
Swizzle pattern: XYZW
Image format: X16Y16Z16W16_FLOAT
Mip levels: 1
Slices: 1
Sample count: 1
Fragment count: 1
Tiling type: Optimal
Resource timeline:
00:00:09.4618368 : Create
00:00:09.4622336 : Bind into 0x236c00000
00:00:09.4622336 : Make Resident into 0x236c00000
00:00:09.4634816 : Destroy
  • Attributes 部分对于不同的资源类型会有所不同(例如,buffer 没有 Image format 属性)。

  • 正如您所见,每个资源还会有自己的 resource timeline 字段,其中仅列出适用于该特定资源的事件。

硬件崩溃分析

RGD v1.4 带来了一项强大的新功能:硬件崩溃分析。启用后,RGD 会收集 GPU 硬件状态在崩溃时的低级信息,并通过有意义的洞察来丰富崩溃分析(.rgd)输出文件中呈现的信息。

进行中着色器的新执行标记

通过硬件崩溃分析,添加了一个新的执行标记状态 shader in flight。RGD 会将正在进行的 wavefront 与执行标记相关联,并标记在崩溃期间具有正在运行的 wavefront 的节点,并用 [#] 符号标记该节点。

以下是一个 DX12 崩溃应用程序的执行标记树示例,启用了硬件崩溃分析和着色器 DXC 调试信息:

Command Buffer ID: 0x10cc (Queue type: Direct)
==============================================
[>] "Frame 1060 CL0"
├─[X] ----------Barrier----------
├─[X] "Depth + Normal + Motion Vector PrePass"
├─[X] ----------Barrier----------
├─[X] ----------Barrier----------
├─[X] "Shadow Cascade Pass"
├─[X] "TLAS Build"
├─[X] ----------Barrier----------
├─[X] "Classify tiles"
├─[X] "Trace shadows"
├─[X] ----------Barrier----------
├─[X] ----------Barrier----------
├─[X] "Denoise shadows"
├─[X] ----------Barrier----------
├─[X] ----------Barrier----------
├─[X] "GltfPbrPass::DrawBatchList"
├─[X] "Skydome Proc"
├─[X] "GltfPbrPass::DrawBatchList"
├─[X] ----------Barrier----------
├─[>] "DownSamplePS"
│ ├─[X] ----------Barrier----------
│ ├─[#] Draw(VertexCount=3, InstanceCount=1) <-- has a correlated running wave <SHADER INFO section ID: ShaderInfoID1, Entry point: mainPS, Source file: DownSamplePS.hlsl, API stage: Pixel, API PSO hash: 0xe3204f6b7ea39e98>
│ ├─[>] ----------Barrier----------
│ ├─[>] ----------Barrier----------
│ ├─[#] Draw(VertexCount=3, InstanceCount=1) <-- has a correlated running wave <SHADER INFO section ID: ShaderInfoID1, Entry point: mainPS, Source file: DownSamplePS.hlsl, API stage: Pixel, API PSO hash: 0xe3204f6b7ea39e98>
│ ├─[>] ----------Barrier----------
│ ├─[>] ----------Barrier----------
│ ├─[#] Draw(VertexCount=3, InstanceCount=1) <-- has a correlated running wave <SHADER INFO section ID: ShaderInfoID1, Entry point: mainPS, Source file: DownSamplePS.hlsl, API stage: Pixel, API PSO hash: 0xe3204f6b7ea39e98>
│ ├─[>] ----------Barrier----------
│ ├─[>] ----------Barrier----------
│ ├─[#] Draw(VertexCount=3, InstanceCount=1) <-- has a correlated running wave <SHADER INFO section ID: ShaderInfoID1, Entry point: mainPS, Source file: DownSamplePS.hlsl, API stage: Pixel, API PSO hash: 0xe3204f6b7ea39e98>
│ ├─[>] ----------Barrier----------
│ ├─[>] ----------Barrier----------
│ ├─[#] Draw(VertexCount=3, InstanceCount=1) <-- has a correlated running wave <SHADER INFO section ID: ShaderInfoID1, Entry point: mainPS, Source file: DownSamplePS.hlsl, API stage: Pixel, API PSO hash: 0xe3204f6b7ea39e98>
│ └─[>] ----------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----------
│ ├─[ ] "BlurPS"
│ ├─[ ] ----------Barrier----------
│ ├─[ ] Draw(VertexCount=3, InstanceCount=1)
│ ├─[ ] ----------Barrier----------
│ ├─[ ] "BlurPS"
│ ├─[ ] ----------Barrier----------
│ ├─[ ] Draw(VertexCount=3, InstanceCount=1)
│ ├─[ ] ----------Barrier----------
│ ├─[ ] "BlurPS"
│ ├─[ ] ----------Barrier----------
│ ├─[ ] Draw(VertexCount=3, InstanceCount=1)
│ └─[ ] ----------Barrier----------
└─[ ] "Indirect draw simple"

以下是一个 Vulkan 崩溃应用程序的执行标记树示例,启用了硬件崩溃分析:

Command Buffer ID: 0xea9c (Queue type: Direct)
===============================================
[>] "Frame 12003 Graphics CB"
└─[>] "Vk_Renderer::draw"
├─[X] "Vk_Renderer::draw::Skybox"
├─[X] "Vk_Renderer::draw::Shadow"
├─[X] "Vk_Renderer::draw::Raytracing"
├─[>] "Vk_Renderer::draw::Mesh"
│ ├─[X] "Draw Light Spheres"
│ ├─[>] "Vk_Renderer::DrawObjectsPBR"
│ │ ├─[X] DrawIndexed(IndexCount=2304, InstanceCount=1)
│ │ ├─[X] DrawIndexed(IndexCount=2304, InstanceCount=1)
│ │ ├─[#] DrawIndexed(IndexCount=2304, InstanceCount=1) <-- has a correlated running wave <SHADER INFO section IDs: {ShaderInfoID1, ShaderInfoID2}>
│ │ ├─[#] DrawIndexed(IndexCount=2304, InstanceCount=1) <-- has a correlated running wave <SHADER INFO section IDs: {ShaderInfoID1, ShaderInfoID2}>
│ │ │
⁞ ⁞ ⁞ (7 consecutive occurrences of in progress nodes)
│ │ │
│ │ ├─[#] DrawIndexed(IndexCount=6, InstanceCount=1) <-- has a correlated running wave <SHADER INFO section IDs: {ShaderInfoID1, ShaderInfoID2}>
│ │ ├─[#] DrawIndexed(IndexCount=6, InstanceCount=1) <-- has a correlated running wave <SHADER INFO section IDs: {ShaderInfoID1, ShaderInfoID2}>
│ │ ├─[ ] DrawIndexed(IndexCount=6, InstanceCount=1)
│ │ ├─[ ] DrawIndexed(IndexCount=6, InstanceCount=1)
│ │ └─[ ] DrawIndexedIndirectMulti
│ ├─[ ] DrawIndexed(IndexCount=6, InstanceCount=1)
│ ├─[ ] DrawIndexed(IndexCount=6, InstanceCount=1)
│ └─[ ] "Vk_Renderer::draw::mesh_shader"
├─[ ] "Vk_Renderer::draw::Bloom"
└─[ ] "Vk_Renderer::draw::Fullscreen"

崩溃着色器的详细信息

对于每个用 [#]shader in flight)注释的标记节点:

  • 将提供一个唯一的关联 SHADER INFO 部分 ID、API PSO 哈希和相关着色器的 API 阶段。

  • 当提供 PDB 搜索路径并且包含调试信息的文件成功与相应的正在进行的着色器关联时,还将提供着色器的入口点和源文件。

  • 如果一个以上的正在进行的着色器与同一个执行标记相关联,则仅提供一个唯一的关联 SHADER INFO 部分 ID 列表。

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

SHADER INFO

此部分标题为 SHADER INFO,包含有关崩溃时正在进行中的着色器的低级信息。

  • SHADER INFO 部分将列出崩溃时正在进行中的每个着色器的以下信息: - Shader Info ID:着色器信息的任意标识符。

  • API 阶段:给定着色器的 API 阶段。

  • API PSO 哈希:唯一标识用于创建着色器的 API 管道状态对象 (PSO) 的哈希值。

  • API 着色器哈希:唯一标识着色器的哈希值。

  • 文件名:[仅限 DX12] 着色器定义的源文件名(如果可用),例如 "DownSamplePS.hlsl"。

  • 入口点名称:[仅限 DX12] 着色器的入口点名称(如果可用),例如 "mainPS"。

  • 着色器 IO 和资源绑定:[仅限 DX12] 关于着色器的输入/输出和资源使用情况的信息(如果可用)。

  • HLSL 源代码:[仅限 DX12] 着色器的 HLSL 源代码(如果可用)。

  • 反汇编:显示被一个或多个 wavefront 在崩溃时执行的指令/s 的合并指针的着色器反汇编。

以下是着色器信息的示例:

===========
SHADER INFO
===========
Shader info ID : ShaderInfoID1
API stage : Pixel
API PSO hash : 0xe3204f6b7ea39e98
API shader hash : 0x9447bd598a9ffcb7022a22c95d0031c4 (high: 0x9447bd598a9ffcb7, low: 0x22a22c95d0031c4)
Entry point name: N/A (requires debug information, recompile shader with "-Zi -Qembed_debug'", '-Zi -Qsource_in_debug_module' or '-Zs')
Source file : N/A (requires debug information, recompile shader with "-Zi -Qembed_debug'", '-Zi -Qsource_in_debug_module' or '-Zs')
Shader IO and resource bindings
===============================
N/A (requires debug information, recompile shader with "-Zi -Qembed_debug'", '-Zi -Qsource_in_debug_module' or '-Zs')
HLSL source code
================
N/A (requires debug information, recompile shader with "-Zi -Qembed_debug'", '-Zi' or '-Zs')
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 将在相关反汇编行中用 > 前缀标记有问题的指令,并提供一个注释,标记页面错误罪魁祸首嫌疑和当时执行该指令的 wavefront 数量。默认情况下,该工具仅在输出文件中包含相关子集的着色器反汇编,以尽量减少噪音。在页面错误嫌疑指令周围,您会找到少量指令,以提供该指令执行的上下文。垂直的 ... 线表示已过滤的指令。如果您确实需要查看完整的着色器反汇编,可以通过手动运行 rgd 命令行工具并将 AMD GPU 崩溃转储 (.rgd) 文件作为输入,并使用 —all-disassembly 命令行选项来实现(有关更多信息,请运行 rgd -h 查看 rgd 命令行工具帮助手册)。

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

DXC 调试信息

通过 DXC 调试信息支持,Microsoft® 的 DirectX Shader Compiler (DXC) 生成的调试信息用于增强崩溃分析输出文件,提供有关有问题的底层着色器的有用信息。

支持的格式

DXC 可以生成以下格式的调试信息,RGD 支持所有这些格式:

  1. 嵌入式(-Zi -Qembed_debug):调试信息嵌入在包含已编译着色器的同一文件中。
  2. 单独(-Zi -Qsource_in_debug_module -Fd ):调试信息存储在单独的 PDB 文件中。
  3. 小型 (Slim)(-Zs -Fd ):最小的 PDB 文件,仅包含底层源代码和编译选项。

用法

如何使用 DXC 调试信息改进 RGD 输出?

  1. 确保在 Radeon Developer Panel (RDP) 中启用了硬件崩溃分析

  2. 配置调试信息文件搜索路径

    • RDP 中列出的所有 PDB 搜索路径在捕获崩溃转储期间将被记录在 AMD GPU 崩溃转储(.rgd)文件中,并在 RGD 命令行解析该文件时自动使用。

    • 如果相关路径仅在分析过程中稍后才可知晓,您可以使用 —pdb-path 命令行选项来确保 rgd 命令行工具能够找到并使用包含调试信息的文件。

RDP 中的配置

您可以使用 RDP 中的“着色器调试信息搜索路径”用户界面配置调试信息文件搜索路径。这使得 RGD 在崩溃分析期间能够找到相关的调试信息文件。

崩溃报告中的新信息

当有调试信息可用时,崩溃分析报告将包含:

  • 文件名入口点名称,指向有问题的着色器。

  • 着色器 IO 和资源绑定,详细说明输入、输出和资源使用情况。

  • 着色器的HLSL 源代码,并突出显示相关部分。

以下是可用调试信息的 SHADER INFO 示例:

===========
SHADER INFO
===========
Shader info ID : ShaderInfoID1
API stage : Pixel
API PSO hash : 0xe3204f6b7ea39e98
API shader hash : 0x9447bd598a9ffcb7022a22c95d0031c4 (high: 0x9447bd598a9ffcb7, low: 0x22a22c95d0031c4)
File name : DownSamplePS.hlsl
Entry point name: mainPS
Shader IO and resource bindings
===============================
;
; Input signature:
;
; Name Index Mask Register SysValue Format Used
; -------------------- ----- ------ -------- -------- ------- ------
; TEXCOORD 0 xy 0 NONE float xy
;
;
; Output signature:
;
; Name Index Mask Register SysValue Format Used
; -------------------- ----- ------ -------- -------- ------- ------
; SV_Target 0 xyzw 0 TARGET float xyzw
;
; shader debug name: 1396690ed550686e26be113392120f5b.pdb
; shader hash: 1396690ed550686e26be113392120f5b
;
; Pipeline Runtime Information:
;
;PSVRuntimeInfo:
; Pixel Shader
; DepthOutput=0
; SampleFrequency=0
; MinimumExpectedWaveLaneCount: 0
; MaximumExpectedWaveLaneCount: 4294967295
; UsesViewID: false
; SigInputElements: 1
; SigOutputElements: 1
; SigPatchConstOrPrimElements: 0
; SigInputVectors: 1
; SigOutputVectors[0]: 1
; SigOutputVectors[1]: 0
; SigOutputVectors[2]: 0
; SigOutputVectors[3]: 0
;
;
; Input signature:
;
; Name Index InterpMode DynIdx
; -------------------- ----- ---------------------- ------
; TEXCOORD 0 linear
;
; Output signature:
;
; Name Index InterpMode DynIdx
; -------------------- ----- ---------------------- ------
; SV_Target 0
;
; Buffer Definitions:
;
; cbuffer cbPerFrame
; {
;
; struct cbPerFrame
; {
;
; float2 u_invSize; ; Offset: 0
; int u_mipLevel; ; Offset: 8
;
; } cbPerFrame; ; Offset: 0 Size: 12
;
; }
;
;
; Resource Bindings:
;
; Name Type Format Dim ID HLSL Bind Count
; ------------------------------ ---------- ------- ----------- ------- -------------- ------
; cbPerFrame cbuffer NA NA CB0 cb0 1
; samLinearMirror sampler NA NA S0 s0 1
; inputTex texture f32 2d T0 t0 1
;
;
; ViewId state:
;
; Number of inputs: 2, outputs: 4
; Outputs dependent on ViewId: { }
; Inputs contributing to computation of Outputs:
; output 0 depends on inputs: { 0, 1 }
; output 1 depends on inputs: { 0, 1 }
; output 2 depends on inputs: { 0, 1 }
; output 3 depends on inputs: { 0, 1 }
;
HLSL source code
================
// Copyright(c) 2025 Advanced Micro Devices, Inc.All rights reserved.
//
//--------------------------------------------------------------------------------------
// Constant Buffer
//--------------------------------------------------------------------------------------
cbuffer cbPerFrame : register(b0)
{
float2 u_invSize;
int u_mipLevel;
}
//--------------------------------------------------------------------------------------
// I/O Structures
//--------------------------------------------------------------------------------------
struct VERTEX
{
float2 vTexcoord : TEXCOORD;
};
//--------------------------------------------------------------------------------------
// Texture definitions
//--------------------------------------------------------------------------------------
Texture2D inputTex :register(t0);
SamplerState samLinearMirror :register(s0);
//--------------------------------------------------------------------------------------
// Main function
//--------------------------------------------------------------------------------------
static float2 offsets[9] = {
float2( 1, 1), float2( 0, 1), float2(-1, 1),
float2( 1, 0), float2( 0, 0), float2(-1, 0),
float2( 1,-1), float2( 0,-1), float2(-1,-1)
};
float4 mainPS(VERTEX Input) : SV_Target
{
// gaussian like downsampling
float4 color = float4(0,0,0,0);
if (u_mipLevel==0)
{
for(int i=0;i<9;i++)
color += log(max(inputTex.Sample(samLinearMirror, Input.vTexcoord + (2 * u_invSize * offsets[i])), float4(0.01, 0.01, 0.01, 0.01) ));
return exp(color / 9.0f);
}
else
{
for(int i=0;i<9;i++)
color += inputTex.Sample(samLinearMirror, Input.vTexcoord + (2 * u_invSize * offsets[i]) );
return color / 9.0f;
}
}

请注意,虽然 HLSL 源代码包含在输出文件中,但目前 RDNA 指令与对应的高层源代码行之间没有关联。我们正在与编译器团队积极合作,以实现此功能,并期待在未来的版本中分享更新。

解释结果

解释崩溃分析摘要报告时通常有 3 种可能的情况:

检测到页面错误?VA 有相关资源?含义
尝试访问已销毁/释放的资源(或类似情况)。
否(表示从未有资源驻留在该 VA 中)超出边界访问或尝试访问垃圾数据。
挂起(使用标记进行缩小范围)。

详细说明:

  1. 如果检测到页面错误并找到相关资源,则可能意味着 bug 是由于在资源释放或从内存中逐出后对其进行访问。不正确的(过时或索引错误的)描述符是可能的原因。此时,检查每个资源的生命周期将是个好主意。

    • 当资源生命周期以 Destroy 事件结束时,表示 GPU 在资源被 D3D12 Release() 调用或 Vulkan 等效调用(如 vkDestroyImage() 调用)释放后访问了该资源。

    • 当资源生命周期以 Evict 事件结束时,表示 GPU 在资源被 D3D12 Evict() 调用逐出后访问了该资源。

    • 当资源生命周期不包含 MakeResident 事件时,表示该资源是在非驻留状态下创建的。

  2. 如果检测到页面错误但未找到相关资源,则可能意味着 GPU(例如,着色器)尝试访问不正确的内存地址,这可能表明地址计算或索引存在 bug。

  3. 未检测到页面错误时,这可能意味着崩溃与内存访问无关,而是其他类型的不同问题,例如因超时(执行时间过长)或无限循环导致的着色器挂起。

v1.5 的范围

RGD 设计用于捕获 Windows 上的GPU 崩溃。如果 GPU 故障(如内存页面错误或着色器中的无限循环)导致 GPU 驱动程序在预定时间内(Windows 默认值为 2 秒)不响应操作系统,操作系统将检测到这一点并尝试重启或移除设备。此机制也称为“TDR”(Timeout Detection and Recovery),在本文档范围内,我们将其视为GPU 崩溃

从功能用户角度来看,当发生 GPU 崩溃时,屏幕可能会闪烁或变黑几秒钟,然后会显示“AMD Bug Report Tool”窗口。

在崩溃的应用程序代码中,D3D12 或 DXGI 函数(如 IDXGISwapChain::Present())将返回错误代码,例如 DXGI_ERROR_DEVICE_RESETDXGI_ERROR_DEVICE_REMOVEDDXGI_ERROR_DEVICE_HUNGDXGI_ERROR_DRIVER_INTERNAL_ERROR,此时 D3D12 Device 对象将无法使用。同样,Vulkan 函数(如 vkAcquireNextImageKHR)将返回错误代码,例如 VK_ERROR_DEVICE_LOST

请注意,RGD **不会检测纯 CPU 崩溃**(例如,CPU 空指针解引用或整数除以零)。您需要为此使用 CPU 调试器。请使用 Microsoft Visual Studio 等 CPU 调试机制来调查此类情况。

**错误使用 D3D12 或 Vulkan** 的渲染代码也可能纯粹在 CPU 上失败,而无法到达图形驱动程序或 GPU。因此,此类崩溃不会被 RGD 捕获。它们通常会导致返回 DXGI_ERROR_INVALID_CALL 错误代码,并且通常由 D3D12 调试层检测到。

对于 DX12 应用程序,硬件崩溃分析功能现已支持调试信息。有关更多详细信息,请参阅 hardware_crash_analysis 部分。

在调试任何 D3D12 应用程序中的问题时,请首先**启用 D3D12 调试层**,并确保在使用 RGD 等更高级工具之前没有任何错误(最好也没有警告)报告。在调试器下运行应用程序时,调试层的输出会打印到 Visual Studio 的“输出”面板中。否则,可以使用 DebugView 工具捕获,该工具是 Sysinternals 工具集的一部分,可从 Microsoft® 在线免费获取。

在 Unreal Engine 中,您可以使用 -d3ddebug 命令行参数启用它。

在 Vulkan 编程时,请启用 **Vulkan 验证层**,并检查是否没有与您正在调查的 bug 相关的错误或警告报告。

RGD 使用技巧

  • **在 RGD 之前启用 D3D12 调试层 / Vulkan 验证层**。验证层可以捕获某些甚至未到达 GPU 驱动程序或 GPU 本身的错误,并且不会被工具检测到。这样做可以为您节省大量时间。

  • **Unreal Engine 已支持我们的标记。**您只需使用可执行文件的 Development 版本,并在“Engine.ini”文件中启用变量 D3D12.EmitRgpFrameMarkers=1

  • 插入更精细的标记:如果 RGD 显示的执行标记未能提供有关崩溃区域的足够精确的信息,您可以将更精细的标记插入到渲染代码中,围绕某些渲染通道,甚至单个绘图调用,并在它们的字符串中包含额外的信息,例如材质、着色器或特定对象的名称。使用 RGD 显示的 in progress 标记作为可能需要更多标记的指南。

  • 尝试启用崩溃分析的 DRED:如果您的代码实现了使用 WriteBufferImmediate() 或 Device Removed Extended Data (DRED) API 来报告 GPU 崩溃的自定义功能,RGD 也可以与它一起使用。在 RDP 中启用“崩溃分析”可以使这些自定义面包屑标记更加准确。为此,请按照捕获 GPU 崩溃转储的相同步骤操作。这将确保在运行您的应用程序时,驱动程序中的崩溃分析模式处于启用状态。

  • 在 Vulkan 中,RGD 也支持旧的设备扩展 VK_EXT_debug_marker,但它现在已弃用,取而代之的是 VK_EXT_debug_utils 实例扩展。

  • 尝试使用驱动程序实验进行崩溃分析:如果您怀疑驱动程序启用的某些优化或功能可能导致崩溃,您可以尝试使用驱动程序实验来禁用它们。这可以帮助您缩小查找崩溃原因的范围。

已知问题和解决方法

  • RGD **不捕获 PIX 标记**(PIXBeginEventPIXEndEvent)。要查看渲染通道周围的标记层次结构,您需要使用 AGS 库中的标记,直接使用(agsDriverExtensionsDX12_PushMarkeragsDriverExtensionsDX12_PopMarker)或使用此包随附的 PIX 标记的替换头文件,该头文件会自动使用它们。否则,您只会看到一个平坦的绘图调用列表。这与 RGP 的要求相同。有关更多信息,请参阅 RGP 文档(“用户调试标记”章节)。

  • RGD **仅捕获推-拉范围**。AGS 库中的点标记(agsDriverExtensionsDX12_SetMarker)会被 RGD 忽略,Vulkan 中的点标记(vkCmdInsertDebugUtilsLabelEXT)也会被忽略。

  • 在当前版本的 RGD 中,**跨命令列表边界的标记**(在一个命令列表中开始,在另一个命令列表中结束)处理不当,并且可能不会在 RGD 输出中显示。

  • 建议在**驱动程序安装**后重新启动系统。在未重新启动系统的情况下进行全新驱动程序安装后执行 RGD 工作流,可能会生成无效的崩溃转储文件。

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