将 Radeon™ GPU Analyzer 与 DirectX®12 图形结合使用

首次发布时间:
Amit Ben-Moshe's avatar
Amit Ben-Moshe

新的 DirectX 12 模式(-s dx12)与旧的 DirectX 11 模式(-s dx11,先前命名为-s hlsl)之间的关键区别在于,DirectX 12 模式使用实时驱动程序,并遵循与实际 DirectX 12 应用程序相同的编译路径。因此,它能够生成最接近实际情况的反汇编和硬件资源使用统计信息,从而做出更好的性能优化决策。

要编译 DirectX 12 图形管道,除了 HLSL 源文件外,还需要向工具提供以下输入:

  • Root signature:Root signature 可以在 HLSL 源代码中定义,也可以提供预编译的二进制文件,如我们 之前的文章所述。
  • .gpso 文件:对于计算管道,HLSL 源代码和有效的 root signature 足以成功编译管道。但对于图形而言,还需要 D3D12 图形管道状态的一个子集。如果没有这些额外数据,RGA 将无法正确设置着色器的管道状态,这将导致编译失败。RGA 所需的图形管道状态子集定义在一个自定义的 .gpso 文件中,格式如下:
终端窗口
# schemaVersion
1.0
# InputLayoutNumElements: Number of D3D12_INPUT_ELEMENT_DESC elements in the D3D12_INPUT_LAYOUT_DESC structure.
# Must match the following "InputLayout" section.
2
# InputLayout
# { SemanticName, SemanticIndex, Format, InputSlot, AlignedByteOffset, InputSlotClass, InstanceDataStepRate }
{ "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 },
{ "COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 12, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 }
# PrimitiveTopologyType: The D3D12_PRIMITIVE_TOPOLOGY_TYPE value to be used when creating the PSO.
D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE
# NumRenderTargets: The number of formats in the upcoming RTVFormats section.
1
# RTVFormats: An array of DXGI_FORMAT-typed values for the render target formats.
# The number of items in the array should match the above NumRenderTargets section.
{ DXGI_FORMAT_R8G8B8A8_UNORM }

您可以通过运行:rga -s dx12 —gpso-template “输出文件的完整路径” 来生成一个模板 .gpso 文件,然后手动编辑以匹配您的管道。

示例

在接下来的示例中,我们将使用 Microsoft 的 DirectX Graphics Samples 中的 *D3D12HelloTriangle* 示例。该管道包含两个非常简单的着色器,均在 shaders.hlsl 中定义:VSMain 是顶点着色器,PSMain 是像素着色器。

让我们先生成一个模板 .gpso 文件。

rga -s dx12 —gpso-template C:\shaders\hellotriangle.gpso

现在,我们将修改文件的内容以匹配我们的源代码。让我们看一下 D3D12HelloTriangle.cpp 文件,其中可以找到输入布局定义。

// Define the vertex input layout.
D3D12_INPUT_ELEMENT_DESC inputElementDescs[] =
{
{ "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 },
{ "COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 12, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 }
};

让我们将两个输入布局行复制到 InputLayout 部分,并将 InputLayoutNumElements 值调整为 2。

接下来,再次查看 .cpp 文件,可以看到只有一个渲染目标,格式为 DXGI_FORMAT_R8G8B8A8_UNORM

psoDesc.NumRenderTargets = 1;
psoDesc.RTVFormats[0] = DXGI_FORMAT_R8G8B8A8_UNORM;

我们相应地更新 **NumRenderTargets** 和 **RTVFormats** 部分,这样最终的 .gpso 文件看起来会像这样:

# schemaVersion
1.0
# InputLayoutNumElements: Number of D3D12_INPUT_ELEMENT_DESC elements in the D3D12_INPUT_LAYOUT_DESC structure.
# Must match the following "InputLayout" section.
2
# InputLayout
# { SemanticName, SemanticIndex, Format, InputSlot, AlignedByteOffset, InputSlotClass, InstanceDataStepRate }
{ "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 },
{ "COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 12, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 }
# PrimitiveTopologyType: The D3D12_PRIMITIVE_TOPOLOGY_TYPE value to be used when creating the PSO.
D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE
# NumRenderTargets: The number of formats in the upcoming RTVFormats section.
1
# RTVFormats: An array of DXGI_FORMAT-typed values for the render target formats.
# The number of items in the array should match the above NumRenderTargets section.
{ DXGI_FORMAT_R8G8B8A8_UNORM }

现在,我们只需使用以下命令运行 RGA 命令行工具:

终端窗口
rga -s dx12 --vs C:\shaders\shaders.hlsl --ps C:\shaders\shaders.hlsl --vs-model "vs_6_0" --ps-model "ps_6_0"
--vs-entry VSMain --ps-entry PSMain --isa C:\output\isa.txt --rs-bin C:\RootSignatures\hellotriangle.rs.fxo
--gpso C:\shaders\hellotriangle.gpso

其中 —rs-bin 指向预编译的 root signature 二进制文件。有关 RGA 中 root signature 的更多信息,请参阅 我们之前的文章

由于顶点和像素着色器都在同一个文件中定义并使用相同的着色器模型,我们可以使用 —all-hlsl—all-model 选项使命令稍微不那么冗长。

终端窗口
rga -s dx12 --all-hlsl C:\shaders\shaders.hlsl --all-model "6_0" --vs-entry VSMain --ps-entry PSMain
--isa C:\output\isa.txt --rs-bin C:\RootSignatures\hellotriangle.rs.fxo --gpso C:\shaders\hellotriangle.gpso

就是这样。成功构建后,我们会在输出文件夹中获得反汇编。

; -------- Disassembly --------------------
shader main
asic(GFX10)
type(PS)
sgpr_count(6)
vgpr_count(8)
wave_size(64)
s_inst_prefetch 0x0003 // 000000000000: BFA00003
s_mov_b32 m0, s2 // 000000000004: BEFC0302
v_interp_p1_f32 v2, v0, attr0.x // 000000000008: C8080000
v_interp_p1_f32 v3, v0, attr0.y // 00000000000C: C80C0100
v_interp_p1_f32 v4, v0, attr0.z // 000000000010: C8100200
v_interp_p1_f32 v0, v0, attr0.w // 000000000014: C8000300
v_interp_p2_f32 v2, v1, attr0.x // 000000000018: C8090001
v_interp_p2_f32 v3, v1, attr0.y // 00000000001C: C80D0101
v_interp_p2_f32 v4, v1, attr0.z // 000000000020: C8110201
v_interp_p2_f32 v0, v1, attr0.w // 000000000024: C8010301
v_cvt_pkrtz_f16_f32 v2, v2, v3 // 000000000028: 5E040702
v_cvt_pkrtz_f16_f32 v3, v4, v0 // 00000000002C: 5E060104
exp mrt0, v2, v2, v3, v3 done compr vm // 000000000030: F8001C0F 00000302
s_endpgm // 000000000038: BF810000
s_code_end // 00000000003C: BF9F0000

除了生成反汇编的 —isa 选项外,您还可以使用 -a 选项为管道中的每个着色器生成硬件资源使用统计信息,或者使用 —livereg 选项根据生成的反汇编创建实时 VGPR 分析报告。

有关可用选项的更多信息,请运行 rga -s dx12 -h

致谢

此处使用的代码示例来自 Microsoft 的 DirectX Graphics Samples,版权归 Microsoft 2015 所有,并受 MIT 许可证约束。

资源

Amit Ben-Moshe's avatar

Amit Ben-Moshe

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

相关新闻和技术文章

相关视频

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