Skip to content

Commit ff26a7a

Browse files
authored
Adding additional info in the UI for GFXR draw calls (#622)
Highlight some important parameters of the Vulkan vkCmdDraw* commands by adding them to the node description, namely the vertex count, index count, and instance count. Minor changes: - Remove unused `current_path` parameter from `GfxrVulkanCommandHierarchyCreator::GetArgs()` - Remove unused `m_node_root_node_indices` member from `GfxrVulkanCommandHierarchyCreator`
1 parent de213ae commit ff26a7a

File tree

5 files changed

+166
-35
lines changed

5 files changed

+166
-35
lines changed

dive_core/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,7 @@ add_dependencies(${PROJECT_NAME} adreno_header)
172172
add_dependencies(${PROJECT_NAME} a6xx_py)
173173
add_dependencies(${PROJECT_NAME} freedreno_devices_header)
174174

175-
target_link_libraries(${PROJECT_NAME} PUBLIC absl::no_destructor)
175+
target_link_libraries(${PROJECT_NAME} PUBLIC absl::no_destructor absl::strings)
176176

177177
make_directory("${FREEDRENO_ISA_DIRECTORY}")
178178

dive_core/command_hierarchy.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -240,6 +240,14 @@ const char *CommandHierarchy::GetNodeDesc(uint64_t node_index) const
240240
return m_nodes.m_description[node_index].c_str();
241241
}
242242

243+
//--------------------------------------------------------------------------------------------------
244+
void CommandHierarchy::SetNodeDesc(uint64_t node_index, const std::string &desc)
245+
{
246+
DIVE_ASSERT(node_index < m_nodes.m_description.size());
247+
m_nodes.m_description[node_index] = desc;
248+
return;
249+
}
250+
243251
//--------------------------------------------------------------------------------------------------
244252
Dive::EngineType CommandHierarchy::GetSubmitNodeEngineType(uint64_t node_index) const
245253
{

dive_core/command_hierarchy.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,7 @@ class CommandHierarchy
218218

219219
NodeType GetNodeType(uint64_t node_index) const;
220220
const char *GetNodeDesc(uint64_t node_index) const;
221+
void SetNodeDesc(uint64_t node_index, const std::string &desc);
221222

222223
Dive::EngineType GetSubmitNodeEngineType(uint64_t node_index) const;
223224
uint32_t GetSubmitNodeIndex(uint64_t node_index) const;

dive_core/gfxr_vulkan_command_hierarchy.cpp

Lines changed: 114 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,12 @@
1111
limitations under the License.
1212
*/
1313

14-
#include "gfxr_vulkan_command_hierarchy.h"
15-
#include "dive_strings.h"
14+
#include "dive_core/gfxr_vulkan_command_hierarchy.h"
15+
16+
#include <iostream>
17+
18+
#include "absl/strings/numbers.h"
19+
#include "dive_core/dive_strings.h"
1620

1721
namespace Dive
1822
{
@@ -49,6 +53,33 @@ void GfxrVulkanCommandHierarchyCreator::ConditionallyAddChild(uint64_t node_inde
4953
}
5054
}
5155

56+
//--------------------------------------------------------------------------------------------------
57+
std::string GfxrVulkanCommandHierarchyCreator::GetCurrDrawCallString()
58+
{
59+
// Early return for zero instance count
60+
if (m_cur_draw_call_info.instance_count == 0)
61+
{
62+
return "";
63+
}
64+
65+
std::ostringstream s;
66+
67+
s << "(";
68+
69+
if (m_cur_draw_call_info.index_count > 0)
70+
{
71+
s << "indexCount:" << m_cur_draw_call_info.index_count << ",";
72+
}
73+
else if (m_cur_draw_call_info.vertex_count > 0)
74+
{
75+
s << "vertexCount:" << m_cur_draw_call_info.vertex_count << ",";
76+
}
77+
78+
s << "instanceCount:" << m_cur_draw_call_info.instance_count << ")";
79+
80+
return s.str();
81+
}
82+
5283
//--------------------------------------------------------------------------------------------------
5384
void GfxrVulkanCommandHierarchyCreator::OnCommand(
5485
const DiveAnnotationProcessor::VulkanCommandInfo &vk_cmd_info,
@@ -65,7 +96,7 @@ std::vector<uint64_t> &render_pass_draw_call_counts)
6596
uint64_t cmd_buffer_index = AddNode(NodeType::kGfxrVulkanBeginCommandBufferNode,
6697
vk_cmd_string_stream.str());
6798
m_cur_command_buffer_node_index = cmd_buffer_index;
68-
GetArgs(vulkan_cmd_args, m_cur_command_buffer_node_index, "");
99+
GetArgs(vulkan_cmd_args, m_cur_command_buffer_node_index);
69100
AddChild(CommandHierarchy::TopologyType::kAllEventTopology,
70101
m_cur_submit_node_index,
71102
cmd_buffer_index);
@@ -75,7 +106,7 @@ std::vector<uint64_t> &render_pass_draw_call_counts)
75106
uint64_t cmd_buffer_index = AddNode(NodeType::kGfxrVulkanEndCommandBufferNode,
76107
vk_cmd_string_stream.str());
77108

78-
GetArgs(vulkan_cmd_args, cmd_buffer_index, "");
109+
GetArgs(vulkan_cmd_args, cmd_buffer_index);
79110
AddChild(CommandHierarchy::TopologyType::kAllEventTopology,
80111
m_cur_command_buffer_node_index,
81112
cmd_buffer_index);
@@ -87,7 +118,7 @@ std::vector<uint64_t> &render_pass_draw_call_counts)
87118
uint64_t
88119
begin_debug_utils_label_cmd_index = AddNode(NodeType::kGfxrBeginDebugUtilsLabelCommandNode,
89120
label_name.c_str());
90-
GetArgs(vulkan_cmd_args, begin_debug_utils_label_cmd_index, "");
121+
GetArgs(vulkan_cmd_args, begin_debug_utils_label_cmd_index);
91122
ConditionallyAddChild(begin_debug_utils_label_cmd_index);
92123
m_cur_parent_node_index_stack.push(begin_debug_utils_label_cmd_index);
93124
}
@@ -104,10 +135,23 @@ std::vector<uint64_t> &render_pass_draw_call_counts)
104135
else if (vulkan_cmd_name.find("vkCmdDraw") != std::string::npos ||
105136
vulkan_cmd_name.find("vkCmdDispatch") != std::string::npos)
106137
{
138+
m_cur_draw_call_info = {};
139+
107140
uint64_t vk_cmd_index = AddNode(NodeType::kGfxrVulkanDrawCommandNode,
108141
vk_cmd_string_stream.str());
109-
GetArgs(vulkan_cmd_args, vk_cmd_index, "");
142+
GetArgs(vulkan_cmd_args, vk_cmd_index);
110143
ConditionallyAddChild(vk_cmd_index);
144+
145+
if (vulkan_cmd_name.find("vkCmdDraw") != std::string::npos)
146+
{
147+
std::string extra_info = GetCurrDrawCallString();
148+
if (!extra_info.empty())
149+
{
150+
// Update the draw node description with info obtained from its args
151+
vk_cmd_string_stream << extra_info;
152+
m_command_hierarchy.SetNodeDesc(vk_cmd_index, vk_cmd_string_stream.str());
153+
}
154+
}
111155
}
112156
else if (vulkan_cmd_name.find("vkCmdBeginRenderPass") != std::string::npos)
113157
{
@@ -119,15 +163,15 @@ std::vector<uint64_t> &render_pass_draw_call_counts)
119163
vk_cmd_string_stream << ", Draw Call Count: " << draw_call_count;
120164
uint64_t vk_cmd_index = AddNode(NodeType::kGfxrVulkanBeginRenderPassCommandNode,
121165
vk_cmd_string_stream.str());
122-
GetArgs(vulkan_cmd_args, vk_cmd_index, "");
166+
GetArgs(vulkan_cmd_args, vk_cmd_index);
123167
ConditionallyAddChild(vk_cmd_index);
124168
m_cur_parent_node_index_stack.push(vk_cmd_index);
125169
}
126170
else if (vulkan_cmd_name.find("vkCmdEndRenderPass") != std::string::npos)
127171
{
128172
uint64_t vk_cmd_index = AddNode(NodeType::kGfxrVulkanEndRenderPassCommandNode,
129173
vk_cmd_string_stream.str());
130-
GetArgs(vulkan_cmd_args, vk_cmd_index, "");
174+
GetArgs(vulkan_cmd_args, vk_cmd_index);
131175
ConditionallyAddChild(vk_cmd_index);
132176
if (!m_cur_parent_node_index_stack.empty())
133177
{
@@ -139,7 +183,7 @@ std::vector<uint64_t> &render_pass_draw_call_counts)
139183
{
140184
uint64_t vk_cmd_index = AddNode(NodeType::kGfxrVulkanCommandNode,
141185
vk_cmd_string_stream.str());
142-
GetArgs(vulkan_cmd_args, vk_cmd_index, "");
186+
GetArgs(vulkan_cmd_args, vk_cmd_index);
143187
ConditionallyAddChild(vk_cmd_index);
144188
}
145189
}
@@ -238,15 +282,12 @@ uint64_t GfxrVulkanCommandHierarchyCreator::AddNode(NodeType type, std::string &
238282
uint64_t local_node_index = m_node_children[CommandHierarchy::kAllEventTopology].size();
239283
m_dive_indices_to_local_indices_map[node_index] = local_node_index;
240284
m_node_children[CommandHierarchy::kAllEventTopology].resize(local_node_index + 1);
241-
m_node_root_node_indices[CommandHierarchy::kAllEventTopology].resize(local_node_index + 1);
242285
}
243286
else
244287
{
245288
DIVE_ASSERT(m_node_children[CommandHierarchy::kAllEventTopology].size() == node_index);
246289
m_node_children[CommandHierarchy::kAllEventTopology].resize(
247290
m_node_children[CommandHierarchy::kAllEventTopology].size() + 1);
248-
m_node_root_node_indices[CommandHierarchy::kAllEventTopology].resize(
249-
m_node_root_node_indices[CommandHierarchy::kAllEventTopology].size() + 1);
250291
}
251292

252293
return node_index;
@@ -274,9 +315,46 @@ void GfxrVulkanCommandHierarchyCreator::AddChild(CommandHierarchy::TopologyType
274315
}
275316
}
276317

318+
bool GfxrVulkanCommandHierarchyCreator::ParseCurDrawCallInfo(std::string_view key,
319+
std::string_view val)
320+
{
321+
if (key == "indexCount")
322+
{
323+
uint64_t value = 0;
324+
if (!absl::SimpleAtoi(val, &value))
325+
{
326+
return false;
327+
}
328+
m_cur_draw_call_info.index_count = value;
329+
return true;
330+
}
331+
if (key == "vertexCount")
332+
{
333+
uint64_t value = 0;
334+
if (!absl::SimpleAtoi(val, &value))
335+
{
336+
return false;
337+
}
338+
m_cur_draw_call_info.vertex_count = value;
339+
return true;
340+
}
341+
if (key == "instanceCount")
342+
{
343+
uint64_t value = 0;
344+
if (!absl::SimpleAtoi(val, &value))
345+
{
346+
return false;
347+
}
348+
m_cur_draw_call_info.instance_count = value;
349+
return true;
350+
}
351+
352+
// key is unrelated to DrawCallDescInfo
353+
return true;
354+
}
355+
277356
void GfxrVulkanCommandHierarchyCreator::GetArgs(const nlohmann::ordered_json &json_args,
278-
uint64_t curr_index,
279-
const std::string &current_path)
357+
uint64_t curr_index)
280358
{
281359
// This block processes key-value pairs where keys represent field names
282360
// and values can be objects, arrays, or primitives.
@@ -294,7 +372,7 @@ void GfxrVulkanCommandHierarchyCreator::GetArgs(const nlohmann::ordered_json &js
294372
curr_index,
295373
object_node_index);
296374

297-
GetArgs(val, object_node_index, "");
375+
GetArgs(val, object_node_index);
298376
}
299377
else if (val.is_array())
300378
{
@@ -311,7 +389,7 @@ void GfxrVulkanCommandHierarchyCreator::GetArgs(const nlohmann::ordered_json &js
311389
if (element.is_object())
312390
{
313391
// If an array element is an object, recursively process it.
314-
GetArgs(element, array_node_index, "");
392+
GetArgs(element, array_node_index);
315393
}
316394
else if (element.is_array())
317395
{
@@ -323,7 +401,7 @@ void GfxrVulkanCommandHierarchyCreator::GetArgs(const nlohmann::ordered_json &js
323401
AddChild(CommandHierarchy::TopologyType::kAllEventTopology,
324402
array_node_index,
325403
nested_array_node_index);
326-
GetArgs(element, nested_array_node_index, "");
404+
GetArgs(element, nested_array_node_index);
327405
}
328406
else
329407
{
@@ -341,12 +419,26 @@ void GfxrVulkanCommandHierarchyCreator::GetArgs(const nlohmann::ordered_json &js
341419
}
342420
else
343421
{
422+
std::ostringstream s;
423+
std::string val_str;
424+
425+
s.str("");
426+
s << val;
427+
val_str = s.str();
428+
429+
s.str("");
430+
s << key << ":" << val;
431+
432+
if (!ParseCurDrawCallInfo(key, val_str))
433+
{
434+
std::cerr << "GfxrVulkanCommandHierarchyCreator::GetArgs() "
435+
<< "could not parse draw call info from: " << s.str() << std::endl;
436+
}
437+
344438
// If the value is a primitive,
345439
// create a node containing the "key:value" pair.
346-
std::ostringstream vk_cmd_arg_string_stream;
347-
vk_cmd_arg_string_stream << key << ":" << val;
348-
uint64_t vk_cmd_arg_index = AddNode(NodeType::kGfxrVulkanCommandArgNode,
349-
vk_cmd_arg_string_stream.str());
440+
441+
uint64_t vk_cmd_arg_index = AddNode(NodeType::kGfxrVulkanCommandArgNode, s.str());
350442
AddChild(CommandHierarchy::TopologyType::kAllEventTopology,
351443
curr_index,
352444
vk_cmd_arg_index);
@@ -363,7 +455,7 @@ void GfxrVulkanCommandHierarchyCreator::GetArgs(const nlohmann::ordered_json &js
363455
{
364456
// If an array element is an object or another array,
365457
// recursively process it, and associate it with the current parent node.
366-
GetArgs(element, curr_index, "");
458+
GetArgs(element, curr_index);
367459
}
368460
else
369461
{

dive_core/gfxr_vulkan_command_hierarchy.h

Lines changed: 42 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -59,15 +59,24 @@ class GfxrVulkanCommandHierarchyCreator
5959
void ClearCreatedDiveIndices() { m_dive_indices_to_local_indices_map.clear(); }
6060

6161
private:
62-
void GetArgs(const nlohmann::ordered_json &j,
63-
uint64_t curr_index,
64-
const std::string &current_path = "");
65-
void CreateTopologies();
62+
// Helper function to parse json representation of GFXR file into nodes and make calls to
63+
// AddNode() and AddChild() in hiearachical order.
64+
void GetArgs(const nlohmann::ordered_json &json_args, uint64_t curr_index);
65+
66+
void CreateTopologies();
67+
68+
// Wrapper for m_command_hierarchy.AddNode(), returns the command buffer index representing this
69+
// node's place in m_command_hierarchy.m_node_type DiveVector.
70+
//
71+
// Also may add node to m_dive_indices_to_local_indices_map and reserve space in m_node_children
72+
// for future appends
6673
uint64_t AddNode(NodeType type, std::string &&desc);
67-
void AddChild(CommandHierarchy::TopologyType type,
68-
uint64_t node_index,
69-
uint64_t child_node_index);
70-
void ConditionallyAddChild(uint64_t node_index);
74+
75+
// Updates m_node_children
76+
void AddChild(CommandHierarchy::TopologyType type,
77+
uint64_t node_index,
78+
uint64_t child_node_index);
79+
void ConditionallyAddChild(uint64_t node_index);
7180

7281
uint64_t m_cur_submit_node_index = 0;
7382
uint64_t m_cur_command_buffer_node_index = 0;
@@ -76,10 +85,31 @@ class GfxrVulkanCommandHierarchyCreator
7685
const GfxrCaptureData &m_capture_data;
7786
// This is a list of child indices per node, ie. topology info
7887
// Once parsing is complete, we will create a topology from this
79-
DiveVector<DiveVector<uint64_t>> m_node_children[CommandHierarchy::kTopologyTypeCount];
80-
DiveVector<uint64_t> m_node_root_node_indices[CommandHierarchy::kTopologyTypeCount];
81-
Topology m_topology[CommandHierarchy::kTopologyTypeCount];
82-
bool m_used_in_mixed_command_hierarchy = false;
88+
DiveVector<DiveVector<uint64_t>> m_node_children[CommandHierarchy::kTopologyTypeCount];
89+
Topology m_topology[CommandHierarchy::kTopologyTypeCount];
90+
bool m_used_in_mixed_command_hierarchy = false;
8391
std::unordered_map<uint64_t, uint64_t> m_dive_indices_to_local_indices_map;
92+
93+
// Additional info that will be displayed in the description of a draw call node
94+
struct DrawCallDescInfo
95+
{
96+
uint64_t index_count = 0;
97+
uint64_t vertex_count = 0;
98+
uint64_t instance_count = 0;
99+
};
100+
101+
// Returns false if key was recognized to correspond to a DrawCallDescInfo field but val could
102+
// not be parsed
103+
bool ParseCurDrawCallInfo(std::string_view key, std::string_view val);
104+
105+
// Forms string of drawcall info, some examples:
106+
//
107+
// vkCmdDraw: "(vertexCount=#,instanceCount=#)"
108+
// vkCmdDrawIndexed: "(indexCount=#,instanceCount=#)"
109+
// vkCmdDrawMultiEXT: "(instanceCount=#)"
110+
// vkCmdDraw* without instanceCount parameter: ""
111+
std::string GetCurrDrawCallString();
112+
113+
DrawCallDescInfo m_cur_draw_call_info;
84114
};
85115
} // namespace Dive

0 commit comments

Comments
 (0)