AMD Radeon™ GPU Analyzer
Radeon GPU Analyzer 是一款用于 DirectX®、Vulkan®、SPIR-V™、OpenGL® 和 OpenCL™ 的离线编译器和性能分析工具。
新的 DirectX 12 模式(-s dx12)与旧的 DirectX 11 模式(-s dx11,先前命名为-s hlsl)之间的关键区别在于,DirectX 12 模式使用实时驱动程序,并遵循与实际 DirectX 12 应用程序相同的编译路径。因此,它能够生成最接近实际情况的反汇编和硬件资源使用统计信息,从而做出更好的性能优化决策。
要编译 DirectX 12 图形管道,除了 HLSL 源文件外,还需要向工具提供以下输入:
.gpso 文件:对于计算管道,HLSL 源代码和有效的 root signature 足以成功编译管道。但对于图形而言,还需要 D3D12 图形管道状态的一个子集。如果没有这些额外数据,RGA 将无法正确设置着色器的管道状态,这将导致编译失败。RGA 所需的图形管道状态子集定义在一个自定义的 .gpso 文件中,格式如下:# schemaVersion1.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 文件看起来会像这样:
# schemaVersion1.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 许可证约束。