• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2019 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "src/trace_processor/importers/proto/gpu_event_parser.h"
18 
19 #include <inttypes.h>
20 
21 #include "perfetto/ext/base/utils.h"
22 #include "perfetto/protozero/field.h"
23 #include "src/trace_processor/importers/common/args_tracker.h"
24 #include "src/trace_processor/importers/common/event_tracker.h"
25 #include "src/trace_processor/importers/common/process_tracker.h"
26 #include "src/trace_processor/importers/common/slice_tracker.h"
27 #include "src/trace_processor/importers/common/track_tracker.h"
28 #include "src/trace_processor/storage/trace_storage.h"
29 #include "src/trace_processor/types/trace_processor_context.h"
30 
31 #include "protos/perfetto/common/gpu_counter_descriptor.pbzero.h"
32 #include "protos/perfetto/trace/android/graphics_frame_event.pbzero.h"
33 #include "protos/perfetto/trace/gpu/gpu_counter_event.pbzero.h"
34 #include "protos/perfetto/trace/gpu/gpu_log.pbzero.h"
35 #include "protos/perfetto/trace/gpu/gpu_render_stage_event.pbzero.h"
36 #include "protos/perfetto/trace/gpu/vulkan_api_event.pbzero.h"
37 #include "protos/perfetto/trace/gpu/vulkan_memory_event.pbzero.h"
38 #include "protos/perfetto/trace/interned_data/interned_data.pbzero.h"
39 
40 namespace perfetto {
41 namespace trace_processor {
42 
43 namespace {
44 
45 // https://www.khronos.org/registry/vulkan/specs/1.1-extensions/man/html/VkObjectType.html
46 typedef enum VkObjectType {
47   VK_OBJECT_TYPE_UNKNOWN = 0,
48   VK_OBJECT_TYPE_INSTANCE = 1,
49   VK_OBJECT_TYPE_PHYSICAL_DEVICE = 2,
50   VK_OBJECT_TYPE_DEVICE = 3,
51   VK_OBJECT_TYPE_QUEUE = 4,
52   VK_OBJECT_TYPE_SEMAPHORE = 5,
53   VK_OBJECT_TYPE_COMMAND_BUFFER = 6,
54   VK_OBJECT_TYPE_FENCE = 7,
55   VK_OBJECT_TYPE_DEVICE_MEMORY = 8,
56   VK_OBJECT_TYPE_BUFFER = 9,
57   VK_OBJECT_TYPE_IMAGE = 10,
58   VK_OBJECT_TYPE_EVENT = 11,
59   VK_OBJECT_TYPE_QUERY_POOL = 12,
60   VK_OBJECT_TYPE_BUFFER_VIEW = 13,
61   VK_OBJECT_TYPE_IMAGE_VIEW = 14,
62   VK_OBJECT_TYPE_SHADER_MODULE = 15,
63   VK_OBJECT_TYPE_PIPELINE_CACHE = 16,
64   VK_OBJECT_TYPE_PIPELINE_LAYOUT = 17,
65   VK_OBJECT_TYPE_RENDER_PASS = 18,
66   VK_OBJECT_TYPE_PIPELINE = 19,
67   VK_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT = 20,
68   VK_OBJECT_TYPE_SAMPLER = 21,
69   VK_OBJECT_TYPE_DESCRIPTOR_POOL = 22,
70   VK_OBJECT_TYPE_DESCRIPTOR_SET = 23,
71   VK_OBJECT_TYPE_FRAMEBUFFER = 24,
72   VK_OBJECT_TYPE_COMMAND_POOL = 25,
73   VK_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION = 1000156000,
74   VK_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE = 1000085000,
75   VK_OBJECT_TYPE_SURFACE_KHR = 1000000000,
76   VK_OBJECT_TYPE_SWAPCHAIN_KHR = 1000001000,
77   VK_OBJECT_TYPE_DISPLAY_KHR = 1000002000,
78   VK_OBJECT_TYPE_DISPLAY_MODE_KHR = 1000002001,
79   VK_OBJECT_TYPE_DEBUG_REPORT_CALLBACK_EXT = 1000011000,
80   VK_OBJECT_TYPE_OBJECT_TABLE_NVX = 1000086000,
81   VK_OBJECT_TYPE_INDIRECT_COMMANDS_LAYOUT_NVX = 1000086001,
82   VK_OBJECT_TYPE_DEBUG_UTILS_MESSENGER_EXT = 1000128000,
83   VK_OBJECT_TYPE_VALIDATION_CACHE_EXT = 1000160000,
84   VK_OBJECT_TYPE_ACCELERATION_STRUCTURE_NV = 1000165000,
85   VK_OBJECT_TYPE_PERFORMANCE_CONFIGURATION_INTEL = 1000210000,
86   VK_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_KHR =
87       VK_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE,
88   VK_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION_KHR =
89       VK_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION,
90   VK_OBJECT_TYPE_MAX_ENUM = 0x7FFFFFFF
91 } VkObjectType;
92 
93 }  // anonymous namespace
94 
GpuEventParser(TraceProcessorContext * context)95 GpuEventParser::GpuEventParser(TraceProcessorContext* context)
96     : context_(context),
97       vulkan_memory_tracker_(context),
98       description_id_(context->storage->InternString("description")),
99       gpu_render_stage_scope_id_(
100           context->storage->InternString("gpu_render_stage")),
101       gpu_log_track_name_id_(context_->storage->InternString("GPU Log")),
102       gpu_log_scope_id_(context_->storage->InternString("gpu_log")),
103       tag_id_(context_->storage->InternString("tag")),
104       log_message_id_(context->storage->InternString("message")),
105       log_severity_ids_{{context_->storage->InternString("UNSPECIFIED"),
106                          context_->storage->InternString("VERBOSE"),
107                          context_->storage->InternString("DEBUG"),
108                          context_->storage->InternString("INFO"),
109                          context_->storage->InternString("WARNING"),
110                          context_->storage->InternString("ERROR"),
111                          context_->storage->InternString(
112                              "UNKNOWN_SEVERITY") /* must be last */}},
113       vk_event_track_id_(context->storage->InternString("Vulkan Events")),
114       vk_event_scope_id_(context->storage->InternString("vulkan_events")),
115       vk_queue_submit_id_(context->storage->InternString("vkQueueSubmit")) {}
116 
ParseGpuCounterEvent(int64_t ts,ConstBytes blob)117 void GpuEventParser::ParseGpuCounterEvent(int64_t ts, ConstBytes blob) {
118   protos::pbzero::GpuCounterEvent::Decoder event(blob.data, blob.size);
119 
120   protos::pbzero::GpuCounterDescriptor::Decoder descriptor(
121       event.counter_descriptor());
122   // Add counter spec to ID map.
123   for (auto it = descriptor.specs(); it; ++it) {
124     protos::pbzero::GpuCounterDescriptor_GpuCounterSpec::Decoder spec(*it);
125     if (!spec.has_counter_id()) {
126       PERFETTO_ELOG("Counter spec missing counter id");
127       context_->storage->IncrementStats(stats::gpu_counters_invalid_spec);
128       continue;
129     }
130     if (!spec.has_name()) {
131       context_->storage->IncrementStats(stats::gpu_counters_invalid_spec);
132       continue;
133     }
134 
135     auto counter_id = spec.counter_id();
136     auto name = spec.name();
137     if (gpu_counter_track_ids_.find(counter_id) ==
138         gpu_counter_track_ids_.end()) {
139       auto desc = spec.description();
140 
141       StringId unit_id = kNullStringId;
142       if (spec.has_numerator_units() || spec.has_denominator_units()) {
143         char buffer[1024];
144         base::StringWriter unit(buffer, sizeof(buffer));
145         for (auto numer = spec.numerator_units(); numer; ++numer) {
146           if (unit.pos()) {
147             unit.AppendChar(':');
148           }
149           unit.AppendInt(*numer);
150         }
151         char sep = '/';
152         for (auto denom = spec.denominator_units(); denom; ++denom) {
153           unit.AppendChar(sep);
154           unit.AppendInt(*denom);
155           sep = ':';
156         }
157         unit_id = context_->storage->InternString(unit.GetStringView());
158       }
159 
160       auto name_id = context_->storage->InternString(name);
161       auto desc_id = context_->storage->InternString(desc);
162       auto track_id = context_->track_tracker->CreateGpuCounterTrack(
163           name_id, 0 /* gpu_id */, desc_id, unit_id);
164       gpu_counter_track_ids_.emplace(counter_id, track_id);
165       if (spec.has_groups()) {
166         for (auto group = spec.groups(); group; ++group) {
167           tables::GpuCounterGroupTable::Row row;
168           row.group_id = *group;
169           row.track_id = track_id;
170           context_->storage->mutable_gpu_counter_group_table()->Insert(row);
171         }
172       } else {
173         tables::GpuCounterGroupTable::Row row;
174         row.group_id = protos::pbzero::GpuCounterDescriptor::UNCLASSIFIED;
175         row.track_id = track_id;
176         context_->storage->mutable_gpu_counter_group_table()->Insert(row);
177       }
178     } else {
179       // Either counter spec was repeated or it came after counter data.
180       PERFETTO_ELOG("Duplicated counter spec found. (counter_id=%d, name=%s)",
181                     counter_id, name.ToStdString().c_str());
182       context_->storage->IncrementStats(stats::gpu_counters_invalid_spec);
183     }
184   }
185 
186   for (auto it = event.counters(); it; ++it) {
187     protos::pbzero::GpuCounterEvent_GpuCounter::Decoder counter(*it);
188     if (counter.has_counter_id() &&
189         (counter.has_int_value() || counter.has_double_value())) {
190       auto counter_id = counter.counter_id();
191       // Check missing counter_id
192       if (gpu_counter_track_ids_.find(counter_id) ==
193           gpu_counter_track_ids_.end()) {
194         char buffer[64];
195         base::StringWriter writer(buffer, sizeof(buffer));
196         writer.AppendString("gpu_counter(");
197         writer.AppendUnsignedInt(counter_id);
198         writer.AppendString(")");
199         auto name_id = context_->storage->InternString(writer.GetStringView());
200 
201         TrackId track = context_->track_tracker->CreateGpuCounterTrack(
202             name_id, 0 /* gpu_id */);
203         gpu_counter_track_ids_.emplace(counter_id, track);
204         context_->storage->IncrementStats(stats::gpu_counters_missing_spec);
205       }
206       if (counter.has_int_value()) {
207         context_->event_tracker->PushCounter(
208             ts, counter.int_value(), gpu_counter_track_ids_[counter_id]);
209       } else {
210         context_->event_tracker->PushCounter(
211             ts, counter.double_value(), gpu_counter_track_ids_[counter_id]);
212       }
213     }
214   }
215 }
216 
GetFullStageName(const protos::pbzero::GpuRenderStageEvent_Decoder & event) const217 const StringId GpuEventParser::GetFullStageName(
218     const protos::pbzero::GpuRenderStageEvent_Decoder& event) const {
219   size_t stage_id = static_cast<size_t>(event.stage_id());
220   StringId stage_name;
221 
222   if (stage_id < gpu_render_stage_ids_.size()) {
223     stage_name = gpu_render_stage_ids_[stage_id].first;
224   } else {
225     char buffer[64];
226     snprintf(buffer, sizeof(buffer), "render stage(%zu)", stage_id);
227     stage_name = context_->storage->InternString(buffer);
228   }
229   return stage_name;
230 }
231 
232 /**
233  * Create a GPU render stage track based
234  * GpuRenderStageEvent.Specifications.Description.
235  */
InsertGpuTrack(const protos::pbzero::GpuRenderStageEvent_Specifications_Description_Decoder & hw_queue)236 void GpuEventParser::InsertGpuTrack(
237     const protos::pbzero::
238         GpuRenderStageEvent_Specifications_Description_Decoder& hw_queue) {
239   StringId track_name = context_->storage->InternString(hw_queue.name());
240   if (gpu_hw_queue_counter_ >= gpu_hw_queue_ids_.size() ||
241       !gpu_hw_queue_ids_[gpu_hw_queue_counter_].has_value()) {
242     tables::GpuTrackTable::Row track(track_name);
243     track.scope = gpu_render_stage_scope_id_;
244     track.description = context_->storage->InternString(hw_queue.description());
245     if (gpu_hw_queue_counter_ >= gpu_hw_queue_ids_.size()) {
246       gpu_hw_queue_ids_.emplace_back(
247           context_->track_tracker->InternGpuTrack(track));
248     } else {
249       // If a gpu_render_stage_event is received before the specification, it is
250       // possible that the slot has already been allocated.
251       gpu_hw_queue_ids_[gpu_hw_queue_counter_] =
252           context_->track_tracker->InternGpuTrack(track);
253     }
254   } else {
255     // If a gpu_render_stage_event is received before the specification, a track
256     // will be automatically generated.  In that case, update the name and
257     // description.
258     auto track_id = gpu_hw_queue_ids_[gpu_hw_queue_counter_];
259     if (track_id.has_value()) {
260       auto row = context_->storage->mutable_gpu_track_table()
261                      ->id()
262                      .IndexOf(track_id.value())
263                      .value();
264       context_->storage->mutable_gpu_track_table()->mutable_name()->Set(
265           row, track_name);
266       context_->storage->mutable_gpu_track_table()->mutable_description()->Set(
267           row, context_->storage->InternString(hw_queue.description()));
268     } else {
269       tables::GpuTrackTable::Row track(track_name);
270       track.scope = gpu_render_stage_scope_id_;
271       track.description =
272           context_->storage->InternString(hw_queue.description());
273     }
274   }
275   ++gpu_hw_queue_counter_;
276 }
FindDebugName(int32_t vk_object_type,uint64_t vk_handle) const277 base::Optional<std::string> GpuEventParser::FindDebugName(
278     int32_t vk_object_type,
279     uint64_t vk_handle) const {
280   auto map = debug_marker_names_.find(vk_object_type);
281   if (map == debug_marker_names_.end()) {
282     return base::nullopt;
283   }
284 
285   auto name = map->second.find(vk_handle);
286   if (name == map->second.end()) {
287     return base::nullopt;
288   } else {
289     return name->second;
290   }
291 }
292 
ParseGpuRenderStageEvent(int64_t ts,ConstBytes blob)293 void GpuEventParser::ParseGpuRenderStageEvent(int64_t ts, ConstBytes blob) {
294   protos::pbzero::GpuRenderStageEvent::Decoder event(blob.data, blob.size);
295 
296   if (event.has_specifications()) {
297     protos::pbzero::GpuRenderStageEvent_Specifications::Decoder spec(
298         event.specifications().data, event.specifications().size);
299     for (auto it = spec.hw_queue(); it; ++it) {
300       protos::pbzero::GpuRenderStageEvent_Specifications_Description::Decoder
301           hw_queue(*it);
302       if (hw_queue.has_name()) {
303         InsertGpuTrack(hw_queue);
304       }
305     }
306     for (auto it = spec.stage(); it; ++it) {
307       protos::pbzero::GpuRenderStageEvent_Specifications_Description::Decoder
308           stage(*it);
309       if (stage.has_name()) {
310         gpu_render_stage_ids_.emplace_back(std::make_pair(
311             context_->storage->InternString(stage.name()),
312             context_->storage->InternString(stage.description())));
313       }
314     }
315   }
316 
317   auto args_callback = [this, &event](ArgsTracker::BoundInserter* inserter) {
318     size_t stage_id = static_cast<size_t>(event.stage_id());
319     if (stage_id < gpu_render_stage_ids_.size()) {
320       auto description = gpu_render_stage_ids_[stage_id].second;
321       if (description != kNullStringId) {
322         inserter->AddArg(description_id_, Variadic::String(description));
323       }
324     }
325     for (auto it = event.extra_data(); it; ++it) {
326       protos::pbzero::GpuRenderStageEvent_ExtraData_Decoder datum(*it);
327       StringId name_id = context_->storage->InternString(datum.name());
328       StringId value = context_->storage->InternString(
329           datum.has_value() ? datum.value() : base::StringView());
330       inserter->AddArg(name_id, Variadic::String(value));
331     }
332   };
333 
334   if (event.has_event_id()) {
335     TrackId track_id;
336     uint32_t hw_queue_id = static_cast<uint32_t>(event.hw_queue_id());
337     if (hw_queue_id < gpu_hw_queue_ids_.size() &&
338         gpu_hw_queue_ids_[hw_queue_id].has_value()) {
339       track_id = gpu_hw_queue_ids_[hw_queue_id].value();
340     } else {
341       // If the event has a hw_queue_id that does not have a Specification,
342       // create a new track for it.
343       char buf[128];
344       base::StringWriter writer(buf, sizeof(buf));
345       writer.AppendLiteral("Unknown GPU Queue ");
346       if (hw_queue_id > 1024) {
347         // We don't expect this to happen, but just in case there is a corrupt
348         // packet, make sure we don't allocate a ridiculous amount of memory.
349         hw_queue_id = 1024;
350         context_->storage->IncrementStats(
351             stats::gpu_render_stage_parser_errors);
352         PERFETTO_ELOG("Invalid hw_queue_id.");
353       } else {
354         writer.AppendInt(event.hw_queue_id());
355       }
356       StringId track_name =
357           context_->storage->InternString(writer.GetStringView());
358       tables::GpuTrackTable::Row track(track_name);
359       track.scope = gpu_render_stage_scope_id_;
360       track_id = context_->track_tracker->InternGpuTrack(track);
361       gpu_hw_queue_ids_.resize(hw_queue_id + 1);
362       gpu_hw_queue_ids_[hw_queue_id] = track_id;
363     }
364 
365     auto render_target_name =
366         FindDebugName(VK_OBJECT_TYPE_FRAMEBUFFER, event.render_target_handle());
367     auto render_target_name_id = render_target_name.has_value()
368                                      ? context_->storage->InternString(
369                                            render_target_name.value().c_str())
370                                      : kNullStringId;
371     auto render_pass_name =
372         FindDebugName(VK_OBJECT_TYPE_RENDER_PASS, event.render_pass_handle());
373     auto render_pass_name_id =
374         render_pass_name.has_value()
375             ? context_->storage->InternString(render_pass_name.value().c_str())
376             : kNullStringId;
377     auto command_buffer_name = FindDebugName(VK_OBJECT_TYPE_COMMAND_BUFFER,
378                                              event.command_buffer_handle());
379     auto command_buffer_name_id = command_buffer_name.has_value()
380                                       ? context_->storage->InternString(
381                                             command_buffer_name.value().c_str())
382                                       : kNullStringId;
383 
384     tables::GpuSliceTable::Row row;
385     row.ts = ts;
386     row.track_id = track_id;
387     row.name = GetFullStageName(event);
388     row.dur = static_cast<int64_t>(event.duration());
389     row.context_id = static_cast<int64_t>(event.context());
390     row.render_target = static_cast<int64_t>(event.render_target_handle());
391     row.render_target_name = render_target_name_id;
392     row.render_pass = static_cast<int64_t>(event.render_pass_handle());
393     row.render_pass_name = render_pass_name_id;
394     row.command_buffer = static_cast<int64_t>(event.command_buffer_handle());
395     row.command_buffer_name = command_buffer_name_id;
396     row.submission_id = event.submission_id();
397     row.hw_queue_id = hw_queue_id;
398 
399     context_->slice_tracker->ScopedGpu(row, args_callback);
400   }
401 }
402 
UpdateVulkanMemoryAllocationCounters(UniquePid upid,const VulkanMemoryEvent::Decoder & event)403 void GpuEventParser::UpdateVulkanMemoryAllocationCounters(
404     UniquePid upid,
405     const VulkanMemoryEvent::Decoder& event) {
406   StringId track_str_id = kNullStringId;
407   TrackId track = kInvalidTrackId;
408   auto allocation_scope = VulkanMemoryEvent::SCOPE_UNSPECIFIED;
409   uint32_t memory_type = std::numeric_limits<uint32_t>::max();
410   switch (event.source()) {
411     case VulkanMemoryEvent::SOURCE_DRIVER:
412       allocation_scope = static_cast<VulkanMemoryEvent::AllocationScope>(
413           event.allocation_scope());
414       if (allocation_scope == VulkanMemoryEvent::SCOPE_UNSPECIFIED)
415         return;
416       switch (event.operation()) {
417         case VulkanMemoryEvent::OP_CREATE:
418           vulkan_driver_memory_counters_[allocation_scope] +=
419               event.memory_size();
420           break;
421         case VulkanMemoryEvent::OP_DESTROY:
422           vulkan_driver_memory_counters_[allocation_scope] -=
423               event.memory_size();
424           break;
425         case VulkanMemoryEvent::OP_UNSPECIFIED:
426         case VulkanMemoryEvent::OP_BIND:
427         case VulkanMemoryEvent::OP_DESTROY_BOUND:
428         case VulkanMemoryEvent::OP_ANNOTATIONS:
429           return;
430       }
431       track_str_id = vulkan_memory_tracker_.FindAllocationScopeCounterString(
432           allocation_scope);
433       track = context_->track_tracker->InternProcessCounterTrack(track_str_id,
434                                                                  upid);
435       context_->event_tracker->PushCounter(
436           event.timestamp(), vulkan_driver_memory_counters_[allocation_scope],
437           track);
438       break;
439 
440     case VulkanMemoryEvent::SOURCE_DEVICE_MEMORY:
441       memory_type = static_cast<uint32_t>(event.memory_type());
442       switch (event.operation()) {
443         case VulkanMemoryEvent::OP_CREATE:
444           vulkan_device_memory_counters_allocate_[memory_type] +=
445               event.memory_size();
446           break;
447         case VulkanMemoryEvent::OP_DESTROY:
448           vulkan_device_memory_counters_allocate_[memory_type] -=
449               event.memory_size();
450           break;
451         case VulkanMemoryEvent::OP_UNSPECIFIED:
452         case VulkanMemoryEvent::OP_BIND:
453         case VulkanMemoryEvent::OP_DESTROY_BOUND:
454         case VulkanMemoryEvent::OP_ANNOTATIONS:
455           return;
456       }
457       track_str_id = vulkan_memory_tracker_.FindMemoryTypeCounterString(
458           memory_type,
459           VulkanMemoryTracker::DeviceCounterType::kAllocationCounter);
460       track = context_->track_tracker->InternProcessCounterTrack(track_str_id,
461                                                                  upid);
462       context_->event_tracker->PushCounter(
463           event.timestamp(),
464           vulkan_device_memory_counters_allocate_[memory_type], track);
465       break;
466 
467     case VulkanMemoryEvent::SOURCE_BUFFER:
468     case VulkanMemoryEvent::SOURCE_IMAGE:
469       memory_type = static_cast<uint32_t>(event.memory_type());
470       switch (event.operation()) {
471         case VulkanMemoryEvent::OP_BIND:
472           vulkan_device_memory_counters_bind_[memory_type] +=
473               event.memory_size();
474           break;
475         case VulkanMemoryEvent::OP_DESTROY_BOUND:
476           vulkan_device_memory_counters_bind_[memory_type] -=
477               event.memory_size();
478           break;
479         case VulkanMemoryEvent::OP_UNSPECIFIED:
480         case VulkanMemoryEvent::OP_CREATE:
481         case VulkanMemoryEvent::OP_DESTROY:
482         case VulkanMemoryEvent::OP_ANNOTATIONS:
483           return;
484       }
485       track_str_id = vulkan_memory_tracker_.FindMemoryTypeCounterString(
486           memory_type, VulkanMemoryTracker::DeviceCounterType::kBindCounter);
487       track = context_->track_tracker->InternProcessCounterTrack(track_str_id,
488                                                                  upid);
489       context_->event_tracker->PushCounter(
490           event.timestamp(), vulkan_device_memory_counters_bind_[memory_type],
491           track);
492       break;
493     case VulkanMemoryEvent::SOURCE_UNSPECIFIED:
494     case VulkanMemoryEvent::SOURCE_DEVICE:
495       return;
496   }
497 }
498 
ParseVulkanMemoryEvent(PacketSequenceStateGeneration * sequence_state,ConstBytes blob)499 void GpuEventParser::ParseVulkanMemoryEvent(
500     PacketSequenceStateGeneration* sequence_state,
501     ConstBytes blob) {
502   using protos::pbzero::InternedData;
503   VulkanMemoryEvent::Decoder vulkan_memory_event(blob.data, blob.size);
504   tables::VulkanMemoryAllocationsTable::Row vulkan_memory_event_row;
505   vulkan_memory_event_row.source = vulkan_memory_tracker_.FindSourceString(
506       static_cast<VulkanMemoryEvent::Source>(vulkan_memory_event.source()));
507   vulkan_memory_event_row.operation =
508       vulkan_memory_tracker_.FindOperationString(
509           static_cast<VulkanMemoryEvent::Operation>(
510               vulkan_memory_event.operation()));
511   vulkan_memory_event_row.timestamp = vulkan_memory_event.timestamp();
512   vulkan_memory_event_row.upid =
513       context_->process_tracker->GetOrCreateProcess(vulkan_memory_event.pid());
514   if (vulkan_memory_event.has_device())
515     vulkan_memory_event_row.device =
516         static_cast<int64_t>(vulkan_memory_event.device());
517   if (vulkan_memory_event.has_device_memory())
518     vulkan_memory_event_row.device_memory =
519         static_cast<int64_t>(vulkan_memory_event.device_memory());
520   if (vulkan_memory_event.has_heap())
521     vulkan_memory_event_row.heap = vulkan_memory_event.heap();
522   if (vulkan_memory_event.has_memory_type())
523     vulkan_memory_event_row.memory_type = vulkan_memory_event.memory_type();
524   if (vulkan_memory_event.has_caller_iid()) {
525     vulkan_memory_event_row.function_name =
526         vulkan_memory_tracker_
527             .GetInternedString<InternedData::kFunctionNamesFieldNumber>(
528                 sequence_state,
529                 static_cast<uint64_t>(vulkan_memory_event.caller_iid()));
530   }
531   if (vulkan_memory_event.has_object_handle())
532     vulkan_memory_event_row.object_handle =
533         static_cast<int64_t>(vulkan_memory_event.object_handle());
534   if (vulkan_memory_event.has_memory_address())
535     vulkan_memory_event_row.memory_address =
536         static_cast<int64_t>(vulkan_memory_event.memory_address());
537   if (vulkan_memory_event.has_memory_size())
538     vulkan_memory_event_row.memory_size =
539         static_cast<int64_t>(vulkan_memory_event.memory_size());
540   if (vulkan_memory_event.has_allocation_scope())
541     vulkan_memory_event_row.scope =
542         vulkan_memory_tracker_.FindAllocationScopeString(
543             static_cast<VulkanMemoryEvent::AllocationScope>(
544                 vulkan_memory_event.allocation_scope()));
545 
546   UpdateVulkanMemoryAllocationCounters(vulkan_memory_event_row.upid.value(),
547                                        vulkan_memory_event);
548 
549   auto* allocs = context_->storage->mutable_vulkan_memory_allocations_table();
550   VulkanAllocId id = allocs->Insert(vulkan_memory_event_row).id;
551 
552   if (vulkan_memory_event.has_annotations()) {
553     auto inserter = context_->args_tracker->AddArgsTo(id);
554 
555     for (auto it = vulkan_memory_event.annotations(); it; ++it) {
556       protos::pbzero::VulkanMemoryEventAnnotation::Decoder annotation(*it);
557 
558       auto key_id =
559           vulkan_memory_tracker_
560               .GetInternedString<InternedData::kVulkanMemoryKeysFieldNumber>(
561                   sequence_state, static_cast<uint64_t>(annotation.key_iid()));
562 
563       if (annotation.has_int_value()) {
564         inserter.AddArg(key_id, Variadic::Integer(annotation.int_value()));
565       } else if (annotation.has_double_value()) {
566         inserter.AddArg(key_id, Variadic::Real(annotation.double_value()));
567       } else if (annotation.has_string_iid()) {
568         auto string_id =
569             vulkan_memory_tracker_
570                 .GetInternedString<InternedData::kVulkanMemoryKeysFieldNumber>(
571                     sequence_state,
572                     static_cast<uint64_t>(annotation.string_iid()));
573 
574         inserter.AddArg(key_id, Variadic::String(string_id));
575       }
576     }
577   }
578 }
579 
ParseGpuLog(int64_t ts,ConstBytes blob)580 void GpuEventParser::ParseGpuLog(int64_t ts, ConstBytes blob) {
581   protos::pbzero::GpuLog::Decoder event(blob.data, blob.size);
582 
583   tables::GpuTrackTable::Row track(gpu_log_track_name_id_);
584   track.scope = gpu_log_scope_id_;
585   TrackId track_id = context_->track_tracker->InternGpuTrack(track);
586 
587   auto args_callback = [this, &event](ArgsTracker::BoundInserter* inserter) {
588     if (event.has_tag()) {
589       inserter->AddArg(
590           tag_id_,
591           Variadic::String(context_->storage->InternString(event.tag())));
592     }
593     if (event.has_log_message()) {
594       inserter->AddArg(log_message_id_,
595                        Variadic::String(context_->storage->InternString(
596                            event.log_message())));
597     }
598   };
599 
600   auto severity = static_cast<size_t>(event.severity());
601   StringId severity_id =
602       severity < log_severity_ids_.size()
603           ? log_severity_ids_[static_cast<size_t>(event.severity())]
604           : log_severity_ids_[log_severity_ids_.size() - 1];
605 
606   tables::GpuSliceTable::Row row;
607   row.ts = ts;
608   row.track_id = track_id;
609   row.name = severity_id;
610   row.dur = 0;
611   context_->slice_tracker->ScopedGpu(row, args_callback);
612 }
613 
ParseVulkanApiEvent(int64_t ts,ConstBytes blob)614 void GpuEventParser::ParseVulkanApiEvent(int64_t ts, ConstBytes blob) {
615   protos::pbzero::VulkanApiEvent::Decoder vk_event(blob.data, blob.size);
616   if (vk_event.has_vk_debug_utils_object_name()) {
617     protos::pbzero::VulkanApiEvent_VkDebugUtilsObjectName::Decoder event(
618         vk_event.vk_debug_utils_object_name());
619     debug_marker_names_[event.object_type()][event.object()] =
620         event.object_name().ToStdString();
621   }
622   if (vk_event.has_vk_queue_submit()) {
623     protos::pbzero::VulkanApiEvent_VkQueueSubmit::Decoder event(
624         vk_event.vk_queue_submit());
625     // Once flow table is implemented, we can create a nice UI that link the
626     // vkQueueSubmit to GpuRenderStageEvent.  For now, just add it as in a GPU
627     // track so that they can appear close to the render stage slices.
628     tables::GpuTrackTable::Row track(vk_event_track_id_);
629     track.scope = vk_event_scope_id_;
630     TrackId track_id = context_->track_tracker->InternGpuTrack(track);
631     tables::GpuSliceTable::Row row;
632     row.ts = ts;
633     row.dur = static_cast<int64_t>(event.duration_ns());
634     row.track_id = track_id;
635     row.name = vk_queue_submit_id_;
636     if (event.has_vk_command_buffers()) {
637       row.command_buffer = static_cast<int64_t>(*event.vk_command_buffers());
638     }
639     row.submission_id = event.submission_id();
640     auto args_callback = [this, &event](ArgsTracker::BoundInserter* inserter) {
641       inserter->AddArg(context_->storage->InternString("pid"),
642                        Variadic::Integer(event.pid()));
643       inserter->AddArg(context_->storage->InternString("tid"),
644                        Variadic::Integer(event.tid()));
645     };
646     context_->slice_tracker->ScopedGpu(row, args_callback);
647   }
648 }
649 
650 }  // namespace trace_processor
651 }  // namespace perfetto
652