/*
 * Copyright (C) 2019 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "src/trace_processor/importers/proto/gpu_event_parser.h"

#include <cinttypes>

#include "perfetto/ext/base/utils.h"
#include "perfetto/protozero/field.h"
#include "src/trace_processor/importers/common/args_tracker.h"
#include "src/trace_processor/importers/common/event_tracker.h"
#include "src/trace_processor/importers/common/process_tracker.h"
#include "src/trace_processor/importers/common/slice_tracker.h"
#include "src/trace_processor/importers/common/track_tracker.h"
#include "src/trace_processor/storage/trace_storage.h"
#include "src/trace_processor/types/trace_processor_context.h"

#include "protos/perfetto/common/gpu_counter_descriptor.pbzero.h"
#include "protos/perfetto/trace/android/graphics_frame_event.pbzero.h"
#include "protos/perfetto/trace/gpu/gpu_counter_event.pbzero.h"
#include "protos/perfetto/trace/gpu/gpu_log.pbzero.h"
#include "protos/perfetto/trace/gpu/gpu_render_stage_event.pbzero.h"
#include "protos/perfetto/trace/gpu/vulkan_api_event.pbzero.h"
#include "protos/perfetto/trace/gpu/vulkan_memory_event.pbzero.h"
#include "protos/perfetto/trace/interned_data/interned_data.pbzero.h"

namespace perfetto {
namespace trace_processor {

namespace {

// https://www.khronos.org/registry/vulkan/specs/1.1-extensions/man/html/VkObjectType.html
typedef enum VkObjectType {
  VK_OBJECT_TYPE_UNKNOWN = 0,
  VK_OBJECT_TYPE_INSTANCE = 1,
  VK_OBJECT_TYPE_PHYSICAL_DEVICE = 2,
  VK_OBJECT_TYPE_DEVICE = 3,
  VK_OBJECT_TYPE_QUEUE = 4,
  VK_OBJECT_TYPE_SEMAPHORE = 5,
  VK_OBJECT_TYPE_COMMAND_BUFFER = 6,
  VK_OBJECT_TYPE_FENCE = 7,
  VK_OBJECT_TYPE_DEVICE_MEMORY = 8,
  VK_OBJECT_TYPE_BUFFER = 9,
  VK_OBJECT_TYPE_IMAGE = 10,
  VK_OBJECT_TYPE_EVENT = 11,
  VK_OBJECT_TYPE_QUERY_POOL = 12,
  VK_OBJECT_TYPE_BUFFER_VIEW = 13,
  VK_OBJECT_TYPE_IMAGE_VIEW = 14,
  VK_OBJECT_TYPE_SHADER_MODULE = 15,
  VK_OBJECT_TYPE_PIPELINE_CACHE = 16,
  VK_OBJECT_TYPE_PIPELINE_LAYOUT = 17,
  VK_OBJECT_TYPE_RENDER_PASS = 18,
  VK_OBJECT_TYPE_PIPELINE = 19,
  VK_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT = 20,
  VK_OBJECT_TYPE_SAMPLER = 21,
  VK_OBJECT_TYPE_DESCRIPTOR_POOL = 22,
  VK_OBJECT_TYPE_DESCRIPTOR_SET = 23,
  VK_OBJECT_TYPE_FRAMEBUFFER = 24,
  VK_OBJECT_TYPE_COMMAND_POOL = 25,
  VK_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION = 1000156000,
  VK_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE = 1000085000,
  VK_OBJECT_TYPE_SURFACE_KHR = 1000000000,
  VK_OBJECT_TYPE_SWAPCHAIN_KHR = 1000001000,
  VK_OBJECT_TYPE_DISPLAY_KHR = 1000002000,
  VK_OBJECT_TYPE_DISPLAY_MODE_KHR = 1000002001,
  VK_OBJECT_TYPE_DEBUG_REPORT_CALLBACK_EXT = 1000011000,
  VK_OBJECT_TYPE_OBJECT_TABLE_NVX = 1000086000,
  VK_OBJECT_TYPE_INDIRECT_COMMANDS_LAYOUT_NVX = 1000086001,
  VK_OBJECT_TYPE_DEBUG_UTILS_MESSENGER_EXT = 1000128000,
  VK_OBJECT_TYPE_VALIDATION_CACHE_EXT = 1000160000,
  VK_OBJECT_TYPE_ACCELERATION_STRUCTURE_NV = 1000165000,
  VK_OBJECT_TYPE_PERFORMANCE_CONFIGURATION_INTEL = 1000210000,
  VK_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_KHR =
      VK_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE,
  VK_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION_KHR =
      VK_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION,
  VK_OBJECT_TYPE_MAX_ENUM = 0x7FFFFFFF
} VkObjectType;

}  // anonymous namespace

GpuEventParser::GpuEventParser(TraceProcessorContext* context)
    : context_(context),
      vulkan_memory_tracker_(context),
      description_id_(context->storage->InternString("description")),
      gpu_render_stage_scope_id_(
          context->storage->InternString("gpu_render_stage")),
      gpu_log_track_name_id_(context_->storage->InternString("GPU Log")),
      gpu_log_scope_id_(context_->storage->InternString("gpu_log")),
      tag_id_(context_->storage->InternString("tag")),
      log_message_id_(context->storage->InternString("message")),
      log_severity_ids_{{context_->storage->InternString("UNSPECIFIED"),
                         context_->storage->InternString("VERBOSE"),
                         context_->storage->InternString("DEBUG"),
                         context_->storage->InternString("INFO"),
                         context_->storage->InternString("WARNING"),
                         context_->storage->InternString("ERROR"),
                         context_->storage->InternString(
                             "UNKNOWN_SEVERITY") /* must be last */}},
      vk_event_track_id_(context->storage->InternString("Vulkan Events")),
      vk_event_scope_id_(context->storage->InternString("vulkan_events")),
      vk_queue_submit_id_(context->storage->InternString("vkQueueSubmit")),
      gpu_mem_total_name_id_(context->storage->InternString("GPU Memory")),
      gpu_mem_total_unit_id_(context->storage->InternString(
          std::to_string(protos::pbzero::GpuCounterDescriptor::BYTE).c_str())),
      gpu_mem_total_global_desc_id_(context->storage->InternString(
          "Total GPU memory used by the entire system")),
      gpu_mem_total_proc_desc_id_(context->storage->InternString(
          "Total GPU memory used by this process")) {}

void GpuEventParser::ParseGpuCounterEvent(int64_t ts, ConstBytes blob) {
  protos::pbzero::GpuCounterEvent::Decoder event(blob.data, blob.size);

  protos::pbzero::GpuCounterDescriptor::Decoder descriptor(
      event.counter_descriptor());
  // Add counter spec to ID map.
  for (auto it = descriptor.specs(); it; ++it) {
    protos::pbzero::GpuCounterDescriptor_GpuCounterSpec::Decoder spec(*it);
    if (!spec.has_counter_id()) {
      PERFETTO_ELOG("Counter spec missing counter id");
      context_->storage->IncrementStats(stats::gpu_counters_invalid_spec);
      continue;
    }
    if (!spec.has_name()) {
      context_->storage->IncrementStats(stats::gpu_counters_invalid_spec);
      continue;
    }

    auto counter_id = spec.counter_id();
    auto name = spec.name();
    if (gpu_counter_track_ids_.find(counter_id) ==
        gpu_counter_track_ids_.end()) {
      auto desc = spec.description();

      StringId unit_id = kNullStringId;
      if (spec.has_numerator_units() || spec.has_denominator_units()) {
        char buffer[1024];
        base::StringWriter unit(buffer, sizeof(buffer));
        for (auto numer = spec.numerator_units(); numer; ++numer) {
          if (unit.pos()) {
            unit.AppendChar(':');
          }
          unit.AppendInt(*numer);
        }
        char sep = '/';
        for (auto denom = spec.denominator_units(); denom; ++denom) {
          unit.AppendChar(sep);
          unit.AppendInt(*denom);
          sep = ':';
        }
        unit_id = context_->storage->InternString(unit.GetStringView());
      }

      auto name_id = context_->storage->InternString(name);
      auto desc_id = context_->storage->InternString(desc);
      auto track_id = context_->track_tracker->CreateGpuCounterTrack(
          name_id, 0 /* gpu_id */, desc_id, unit_id);
      gpu_counter_track_ids_.emplace(counter_id, track_id);
      if (spec.has_groups()) {
        for (auto group = spec.groups(); group; ++group) {
          tables::GpuCounterGroupTable::Row row;
          row.group_id = *group;
          row.track_id = track_id;
          context_->storage->mutable_gpu_counter_group_table()->Insert(row);
        }
      } else {
        tables::GpuCounterGroupTable::Row row;
        row.group_id = protos::pbzero::GpuCounterDescriptor::UNCLASSIFIED;
        row.track_id = track_id;
        context_->storage->mutable_gpu_counter_group_table()->Insert(row);
      }
    } else {
      // Either counter spec was repeated or it came after counter data.
      PERFETTO_ELOG("Duplicated counter spec found. (counter_id=%d, name=%s)",
                    counter_id, name.ToStdString().c_str());
      context_->storage->IncrementStats(stats::gpu_counters_invalid_spec);
    }
  }

  for (auto it = event.counters(); it; ++it) {
    protos::pbzero::GpuCounterEvent_GpuCounter::Decoder counter(*it);
    if (counter.has_counter_id() &&
        (counter.has_int_value() || counter.has_double_value())) {
      auto counter_id = counter.counter_id();
      // Check missing counter_id
      if (gpu_counter_track_ids_.find(counter_id) ==
          gpu_counter_track_ids_.end()) {
        continue;
      }
      double counter_val = counter.has_int_value()
                               ? static_cast<double>(counter.int_value())
                               : counter.double_value();
      context_->event_tracker->PushCounter(ts, counter_val,
                                           gpu_counter_track_ids_[counter_id]);
    }
  }
}

const StringId GpuEventParser::GetFullStageName(
    PacketSequenceStateGeneration* sequence_state,
    const protos::pbzero::GpuRenderStageEvent_Decoder& event) const {
  StringId stage_name;
  if (event.has_stage_iid()) {
    auto stage_iid = event.stage_iid();
    auto* decoder = sequence_state->LookupInternedMessage<
        protos::pbzero::InternedData::kGpuSpecificationsFieldNumber,
        protos::pbzero::InternedGpuRenderStageSpecification>(stage_iid);
    if (!decoder) {
      return kNullStringId;
    }
    stage_name = context_->storage->InternString(decoder->name());
  } else {
    uint64_t stage_id = static_cast<uint64_t>(event.stage_id());

    if (stage_id < gpu_render_stage_ids_.size()) {
      stage_name = gpu_render_stage_ids_[static_cast<size_t>(stage_id)].first;
    } else {
      base::StackString<64> name("render stage(%" PRIu64 ")", stage_id);
      stage_name = context_->storage->InternString(name.string_view());
    }
  }
  return stage_name;
}

/**
 * Create a GPU render stage track based
 * GpuRenderStageEvent.Specifications.Description.
 */
void GpuEventParser::InsertGpuTrack(
    const protos::pbzero::
        GpuRenderStageEvent_Specifications_Description_Decoder& hw_queue) {
  StringId track_name = context_->storage->InternString(hw_queue.name());
  if (gpu_hw_queue_counter_ >= gpu_hw_queue_ids_.size() ||
      !gpu_hw_queue_ids_[gpu_hw_queue_counter_].has_value()) {
    tables::GpuTrackTable::Row track(track_name);
    track.scope = gpu_render_stage_scope_id_;
    track.description = context_->storage->InternString(hw_queue.description());
    if (gpu_hw_queue_counter_ >= gpu_hw_queue_ids_.size()) {
      gpu_hw_queue_ids_.emplace_back(
          context_->track_tracker->InternGpuTrack(track));
    } else {
      // If a gpu_render_stage_event is received before the specification, it is
      // possible that the slot has already been allocated.
      gpu_hw_queue_ids_[gpu_hw_queue_counter_] =
          context_->track_tracker->InternGpuTrack(track);
    }
  } else {
    // If a gpu_render_stage_event is received before the specification, a track
    // will be automatically generated.  In that case, update the name and
    // description.
    auto track_id = gpu_hw_queue_ids_[gpu_hw_queue_counter_];
    if (track_id.has_value()) {
      auto row = context_->storage->mutable_gpu_track_table()
                     ->id()
                     .IndexOf(track_id.value())
                     .value();
      context_->storage->mutable_gpu_track_table()->mutable_name()->Set(
          row, track_name);
      context_->storage->mutable_gpu_track_table()->mutable_description()->Set(
          row, context_->storage->InternString(hw_queue.description()));
    } else {
      tables::GpuTrackTable::Row track(track_name);
      track.scope = gpu_render_stage_scope_id_;
      track.description =
          context_->storage->InternString(hw_queue.description());
    }
  }
  ++gpu_hw_queue_counter_;
}
std::optional<std::string> GpuEventParser::FindDebugName(
    int32_t vk_object_type,
    uint64_t vk_handle) const {
  auto map = debug_marker_names_.find(vk_object_type);
  if (map == debug_marker_names_.end()) {
    return std::nullopt;
  }

  auto name = map->second.find(vk_handle);
  if (name == map->second.end()) {
    return std::nullopt;
  } else {
    return name->second;
  }
}

const StringId GpuEventParser::ParseRenderSubpasses(
    const protos::pbzero::GpuRenderStageEvent_Decoder& event) const {
  if (!event.has_render_subpass_index_mask()) {
    return kNullStringId;
  }
  char buf[256];
  base::StringWriter writer(buf, sizeof(buf));
  uint32_t bit_index = 0;
  bool first = true;
  for (auto it = event.render_subpass_index_mask(); it; ++it) {
    auto subpasses_bits = *it;
    do {
      if ((subpasses_bits & 1) != 0) {
        if (!first) {
          writer.AppendChar(',');
        }
        first = false;
        writer.AppendUnsignedInt(bit_index);
      }
      subpasses_bits >>= 1;
      ++bit_index;
    } while (subpasses_bits != 0);
    // Round up to the next multiple of 64.
    bit_index = ((bit_index - 1) / 64 + 1) * 64;
  }
  return context_->storage->InternString(writer.GetStringView());
}

void GpuEventParser::ParseGpuRenderStageEvent(
    int64_t ts,
    PacketSequenceStateGeneration* sequence_state,
    ConstBytes blob) {
  protos::pbzero::GpuRenderStageEvent::Decoder event(blob.data, blob.size);

  if (event.has_specifications()) {
    protos::pbzero::GpuRenderStageEvent_Specifications::Decoder spec(
        event.specifications().data, event.specifications().size);
    for (auto it = spec.hw_queue(); it; ++it) {
      protos::pbzero::GpuRenderStageEvent_Specifications_Description::Decoder
          hw_queue(*it);
      if (hw_queue.has_name()) {
        InsertGpuTrack(hw_queue);
      }
    }
    for (auto it = spec.stage(); it; ++it) {
      protos::pbzero::GpuRenderStageEvent_Specifications_Description::Decoder
          stage(*it);
      if (stage.has_name()) {
        gpu_render_stage_ids_.emplace_back(std::make_pair(
            context_->storage->InternString(stage.name()),
            context_->storage->InternString(stage.description())));
      }
    }
  }

  auto args_callback = [this, &event,
                        sequence_state](ArgsTracker::BoundInserter* inserter) {
    if (event.has_stage_iid()) {
      size_t stage_iid = static_cast<size_t>(event.stage_iid());
      auto* decoder = sequence_state->LookupInternedMessage<
          protos::pbzero::InternedData::kGpuSpecificationsFieldNumber,
          protos::pbzero::InternedGpuRenderStageSpecification>(stage_iid);
      if (decoder) {
        // TODO: Add RenderStageCategory to gpu_slice table.
        inserter->AddArg(description_id_,
                         Variadic::String(context_->storage->InternString(
                             decoder->description())));
      }
    } else if (event.has_stage_id()) {
      size_t stage_id = static_cast<size_t>(event.stage_id());
      if (stage_id < gpu_render_stage_ids_.size()) {
        auto description = gpu_render_stage_ids_[stage_id].second;
        if (description != kNullStringId) {
          inserter->AddArg(description_id_, Variadic::String(description));
        }
      }
    }
    for (auto it = event.extra_data(); it; ++it) {
      protos::pbzero::GpuRenderStageEvent_ExtraData_Decoder datum(*it);
      StringId name_id = context_->storage->InternString(datum.name());
      StringId value = context_->storage->InternString(
          datum.has_value() ? datum.value() : base::StringView());
      inserter->AddArg(name_id, Variadic::String(value));
    }
  };

  if (event.has_event_id()) {
    TrackId track_id;
    uint64_t hw_queue_id = 0;
    if (event.has_hw_queue_iid()) {
      hw_queue_id = event.hw_queue_iid();
      auto* decoder = sequence_state->LookupInternedMessage<
          protos::pbzero::InternedData::kGpuSpecificationsFieldNumber,
          protos::pbzero::InternedGpuRenderStageSpecification>(hw_queue_id);
      if (!decoder) {
        // Skip
        return;
      }
      // TODO: Add RenderStageCategory to gpu_track table.
      tables::GpuTrackTable::Row track(
          context_->storage->InternString(decoder->name()));
      track.scope = gpu_render_stage_scope_id_;
      track.description =
          context_->storage->InternString(decoder->description());
      track_id = context_->track_tracker->InternGpuTrack(track);
    } else {
      uint32_t id = static_cast<uint32_t>(event.hw_queue_id());
      if (id < gpu_hw_queue_ids_.size() && gpu_hw_queue_ids_[id].has_value()) {
        track_id = gpu_hw_queue_ids_[id].value();
      } else {
        // If the event has a hw_queue_id that does not have a Specification,
        // create a new track for it.
        char buf[128];
        base::StringWriter writer(buf, sizeof(buf));
        writer.AppendLiteral("Unknown GPU Queue ");
        if (id > 1024) {
          // We don't expect this to happen, but just in case there is a corrupt
          // packet, make sure we don't allocate a ridiculous amount of memory.
          id = 1024;
          context_->storage->IncrementStats(
              stats::gpu_render_stage_parser_errors);
          PERFETTO_ELOG("Invalid hw_queue_id.");
        } else {
          writer.AppendInt(event.hw_queue_id());
        }
        StringId track_name =
            context_->storage->InternString(writer.GetStringView());
        tables::GpuTrackTable::Row track(track_name);
        track.scope = gpu_render_stage_scope_id_;
        track_id = context_->track_tracker->InternGpuTrack(track);
        gpu_hw_queue_ids_.resize(id + 1);
        gpu_hw_queue_ids_[id] = track_id;
      }
      hw_queue_id = id;
    }

    auto render_target_name =
        FindDebugName(VK_OBJECT_TYPE_FRAMEBUFFER, event.render_target_handle());
    auto render_target_name_id = render_target_name.has_value()
                                     ? context_->storage->InternString(
                                           render_target_name.value().c_str())
                                     : kNullStringId;
    auto render_pass_name =
        FindDebugName(VK_OBJECT_TYPE_RENDER_PASS, event.render_pass_handle());
    auto render_pass_name_id =
        render_pass_name.has_value()
            ? context_->storage->InternString(render_pass_name.value().c_str())
            : kNullStringId;
    auto command_buffer_name = FindDebugName(VK_OBJECT_TYPE_COMMAND_BUFFER,
                                             event.command_buffer_handle());
    auto command_buffer_name_id = command_buffer_name.has_value()
                                      ? context_->storage->InternString(
                                            command_buffer_name.value().c_str())
                                      : kNullStringId;

    tables::GpuSliceTable::Row row;
    row.ts = ts;
    row.track_id = track_id;
    row.name = GetFullStageName(sequence_state, event);
    row.dur = static_cast<int64_t>(event.duration());
    // TODO: Create table for graphics context and lookup
    // InternedGraphicsContext.
    row.context_id = static_cast<int64_t>(event.context());
    row.render_target = static_cast<int64_t>(event.render_target_handle());
    row.render_target_name = render_target_name_id;
    row.render_pass = static_cast<int64_t>(event.render_pass_handle());
    row.render_pass_name = render_pass_name_id;
    row.render_subpasses = ParseRenderSubpasses(event);
    row.command_buffer = static_cast<int64_t>(event.command_buffer_handle());
    row.command_buffer_name = command_buffer_name_id;
    row.submission_id = event.submission_id();
    row.hw_queue_id = static_cast<int64_t>(hw_queue_id);

    context_->slice_tracker->ScopedTyped(
        context_->storage->mutable_gpu_slice_table(), row, args_callback);
  }
}

void GpuEventParser::UpdateVulkanMemoryAllocationCounters(
    UniquePid upid,
    const VulkanMemoryEvent::Decoder& event) {
  StringId track_str_id = kNullStringId;
  TrackId track = kInvalidTrackId;
  auto allocation_scope = VulkanMemoryEvent::SCOPE_UNSPECIFIED;
  uint32_t memory_type = std::numeric_limits<uint32_t>::max();
  switch (event.source()) {
    case VulkanMemoryEvent::SOURCE_DRIVER:
      allocation_scope = static_cast<VulkanMemoryEvent::AllocationScope>(
          event.allocation_scope());
      if (allocation_scope == VulkanMemoryEvent::SCOPE_UNSPECIFIED)
        return;
      switch (event.operation()) {
        case VulkanMemoryEvent::OP_CREATE:
          vulkan_driver_memory_counters_[allocation_scope] +=
              event.memory_size();
          break;
        case VulkanMemoryEvent::OP_DESTROY:
          vulkan_driver_memory_counters_[allocation_scope] -=
              event.memory_size();
          break;
        case VulkanMemoryEvent::OP_UNSPECIFIED:
        case VulkanMemoryEvent::OP_BIND:
        case VulkanMemoryEvent::OP_DESTROY_BOUND:
        case VulkanMemoryEvent::OP_ANNOTATIONS:
          return;
      }
      track_str_id = vulkan_memory_tracker_.FindAllocationScopeCounterString(
          allocation_scope);
      track = context_->track_tracker->InternProcessCounterTrack(track_str_id,
                                                                 upid);
      context_->event_tracker->PushCounter(
          event.timestamp(),
          static_cast<double>(vulkan_driver_memory_counters_[allocation_scope]),
          track);
      break;

    case VulkanMemoryEvent::SOURCE_DEVICE_MEMORY:
      memory_type = static_cast<uint32_t>(event.memory_type());
      switch (event.operation()) {
        case VulkanMemoryEvent::OP_CREATE:
          vulkan_device_memory_counters_allocate_[memory_type] +=
              event.memory_size();
          break;
        case VulkanMemoryEvent::OP_DESTROY:
          vulkan_device_memory_counters_allocate_[memory_type] -=
              event.memory_size();
          break;
        case VulkanMemoryEvent::OP_UNSPECIFIED:
        case VulkanMemoryEvent::OP_BIND:
        case VulkanMemoryEvent::OP_DESTROY_BOUND:
        case VulkanMemoryEvent::OP_ANNOTATIONS:
          return;
      }
      track_str_id = vulkan_memory_tracker_.FindMemoryTypeCounterString(
          memory_type,
          VulkanMemoryTracker::DeviceCounterType::kAllocationCounter);
      track = context_->track_tracker->InternProcessCounterTrack(track_str_id,
                                                                 upid);
      context_->event_tracker->PushCounter(
          event.timestamp(),
          static_cast<double>(
              vulkan_device_memory_counters_allocate_[memory_type]),
          track);
      break;

    case VulkanMemoryEvent::SOURCE_BUFFER:
    case VulkanMemoryEvent::SOURCE_IMAGE:
      memory_type = static_cast<uint32_t>(event.memory_type());
      switch (event.operation()) {
        case VulkanMemoryEvent::OP_BIND:
          vulkan_device_memory_counters_bind_[memory_type] +=
              event.memory_size();
          break;
        case VulkanMemoryEvent::OP_DESTROY_BOUND:
          vulkan_device_memory_counters_bind_[memory_type] -=
              event.memory_size();
          break;
        case VulkanMemoryEvent::OP_UNSPECIFIED:
        case VulkanMemoryEvent::OP_CREATE:
        case VulkanMemoryEvent::OP_DESTROY:
        case VulkanMemoryEvent::OP_ANNOTATIONS:
          return;
      }
      track_str_id = vulkan_memory_tracker_.FindMemoryTypeCounterString(
          memory_type, VulkanMemoryTracker::DeviceCounterType::kBindCounter);
      track = context_->track_tracker->InternProcessCounterTrack(track_str_id,
                                                                 upid);
      context_->event_tracker->PushCounter(
          event.timestamp(),
          static_cast<double>(vulkan_device_memory_counters_bind_[memory_type]),
          track);
      break;
    case VulkanMemoryEvent::SOURCE_UNSPECIFIED:
    case VulkanMemoryEvent::SOURCE_DEVICE:
      return;
  }
}

void GpuEventParser::ParseVulkanMemoryEvent(
    PacketSequenceStateGeneration* sequence_state,
    ConstBytes blob) {
  using protos::pbzero::InternedData;
  VulkanMemoryEvent::Decoder vulkan_memory_event(blob.data, blob.size);
  tables::VulkanMemoryAllocationsTable::Row vulkan_memory_event_row;
  vulkan_memory_event_row.source = vulkan_memory_tracker_.FindSourceString(
      static_cast<VulkanMemoryEvent::Source>(vulkan_memory_event.source()));
  vulkan_memory_event_row.operation =
      vulkan_memory_tracker_.FindOperationString(
          static_cast<VulkanMemoryEvent::Operation>(
              vulkan_memory_event.operation()));
  vulkan_memory_event_row.timestamp = vulkan_memory_event.timestamp();
  vulkan_memory_event_row.upid =
      context_->process_tracker->GetOrCreateProcess(vulkan_memory_event.pid());
  if (vulkan_memory_event.has_device())
    vulkan_memory_event_row.device =
        static_cast<int64_t>(vulkan_memory_event.device());
  if (vulkan_memory_event.has_device_memory())
    vulkan_memory_event_row.device_memory =
        static_cast<int64_t>(vulkan_memory_event.device_memory());
  if (vulkan_memory_event.has_heap())
    vulkan_memory_event_row.heap = vulkan_memory_event.heap();
  if (vulkan_memory_event.has_memory_type())
    vulkan_memory_event_row.memory_type = vulkan_memory_event.memory_type();
  if (vulkan_memory_event.has_caller_iid()) {
    vulkan_memory_event_row.function_name =
        vulkan_memory_tracker_
            .GetInternedString<InternedData::kFunctionNamesFieldNumber>(
                sequence_state,
                static_cast<uint64_t>(vulkan_memory_event.caller_iid()));
  }
  if (vulkan_memory_event.has_object_handle())
    vulkan_memory_event_row.object_handle =
        static_cast<int64_t>(vulkan_memory_event.object_handle());
  if (vulkan_memory_event.has_memory_address())
    vulkan_memory_event_row.memory_address =
        static_cast<int64_t>(vulkan_memory_event.memory_address());
  if (vulkan_memory_event.has_memory_size())
    vulkan_memory_event_row.memory_size =
        static_cast<int64_t>(vulkan_memory_event.memory_size());
  if (vulkan_memory_event.has_allocation_scope())
    vulkan_memory_event_row.scope =
        vulkan_memory_tracker_.FindAllocationScopeString(
            static_cast<VulkanMemoryEvent::AllocationScope>(
                vulkan_memory_event.allocation_scope()));

  UpdateVulkanMemoryAllocationCounters(vulkan_memory_event_row.upid.value(),
                                       vulkan_memory_event);

  auto* allocs = context_->storage->mutable_vulkan_memory_allocations_table();
  VulkanAllocId id = allocs->Insert(vulkan_memory_event_row).id;

  if (vulkan_memory_event.has_annotations()) {
    auto inserter = context_->args_tracker->AddArgsTo(id);

    for (auto it = vulkan_memory_event.annotations(); it; ++it) {
      protos::pbzero::VulkanMemoryEventAnnotation::Decoder annotation(*it);

      auto key_id =
          vulkan_memory_tracker_
              .GetInternedString<InternedData::kVulkanMemoryKeysFieldNumber>(
                  sequence_state, static_cast<uint64_t>(annotation.key_iid()));

      if (annotation.has_int_value()) {
        inserter.AddArg(key_id, Variadic::Integer(annotation.int_value()));
      } else if (annotation.has_double_value()) {
        inserter.AddArg(key_id, Variadic::Real(annotation.double_value()));
      } else if (annotation.has_string_iid()) {
        auto string_id =
            vulkan_memory_tracker_
                .GetInternedString<InternedData::kVulkanMemoryKeysFieldNumber>(
                    sequence_state,
                    static_cast<uint64_t>(annotation.string_iid()));

        inserter.AddArg(key_id, Variadic::String(string_id));
      }
    }
  }
}

void GpuEventParser::ParseGpuLog(int64_t ts, ConstBytes blob) {
  protos::pbzero::GpuLog::Decoder event(blob.data, blob.size);

  tables::GpuTrackTable::Row track(gpu_log_track_name_id_);
  track.scope = gpu_log_scope_id_;
  TrackId track_id = context_->track_tracker->InternGpuTrack(track);

  auto args_callback = [this, &event](ArgsTracker::BoundInserter* inserter) {
    if (event.has_tag()) {
      inserter->AddArg(
          tag_id_,
          Variadic::String(context_->storage->InternString(event.tag())));
    }
    if (event.has_log_message()) {
      inserter->AddArg(log_message_id_,
                       Variadic::String(context_->storage->InternString(
                           event.log_message())));
    }
  };

  auto severity = static_cast<size_t>(event.severity());
  StringId severity_id =
      severity < log_severity_ids_.size()
          ? log_severity_ids_[static_cast<size_t>(event.severity())]
          : log_severity_ids_[log_severity_ids_.size() - 1];

  tables::GpuSliceTable::Row row;
  row.ts = ts;
  row.track_id = track_id;
  row.name = severity_id;
  row.dur = 0;
  context_->slice_tracker->ScopedTyped(
      context_->storage->mutable_gpu_slice_table(), row, args_callback);
}

void GpuEventParser::ParseVulkanApiEvent(int64_t ts, ConstBytes blob) {
  protos::pbzero::VulkanApiEvent::Decoder vk_event(blob.data, blob.size);
  if (vk_event.has_vk_debug_utils_object_name()) {
    protos::pbzero::VulkanApiEvent_VkDebugUtilsObjectName::Decoder event(
        vk_event.vk_debug_utils_object_name());
    debug_marker_names_[event.object_type()][event.object()] =
        event.object_name().ToStdString();
  }
  if (vk_event.has_vk_queue_submit()) {
    protos::pbzero::VulkanApiEvent_VkQueueSubmit::Decoder event(
        vk_event.vk_queue_submit());
    // Once flow table is implemented, we can create a nice UI that link the
    // vkQueueSubmit to GpuRenderStageEvent.  For now, just add it as in a GPU
    // track so that they can appear close to the render stage slices.
    tables::GpuTrackTable::Row track(vk_event_track_id_);
    track.scope = vk_event_scope_id_;
    TrackId track_id = context_->track_tracker->InternGpuTrack(track);
    tables::GpuSliceTable::Row row;
    row.ts = ts;
    row.dur = static_cast<int64_t>(event.duration_ns());
    row.track_id = track_id;
    row.name = vk_queue_submit_id_;
    if (event.has_vk_command_buffers()) {
      row.command_buffer = static_cast<int64_t>(*event.vk_command_buffers());
    }
    row.submission_id = event.submission_id();
    auto args_callback = [this, &event](ArgsTracker::BoundInserter* inserter) {
      inserter->AddArg(context_->storage->InternString("pid"),
                       Variadic::Integer(event.pid()));
      inserter->AddArg(context_->storage->InternString("tid"),
                       Variadic::Integer(event.tid()));
    };
    context_->slice_tracker->ScopedTyped(
        context_->storage->mutable_gpu_slice_table(), row, args_callback);
  }
}

void GpuEventParser::ParseGpuMemTotalEvent(int64_t ts, ConstBytes blob) {
  protos::pbzero::GpuMemTotalEvent::Decoder gpu_mem_total(blob.data, blob.size);

  TrackId track = kInvalidTrackId;
  const uint32_t pid = gpu_mem_total.pid();
  if (pid == 0) {
    // Pid 0 is used to indicate the global total
    track = context_->track_tracker->InternGlobalCounterTrack(
        gpu_mem_total_name_id_, {}, gpu_mem_total_unit_id_,
        gpu_mem_total_global_desc_id_);
  } else {
    // Process emitting the packet can be different from the pid in the event.
    UniqueTid utid = context_->process_tracker->UpdateThread(pid, pid);
    UniquePid upid = context_->storage->thread_table().upid()[utid].value_or(0);
    track = context_->track_tracker->InternProcessCounterTrack(
        gpu_mem_total_name_id_, upid, gpu_mem_total_unit_id_,
        gpu_mem_total_proc_desc_id_);
  }
  context_->event_tracker->PushCounter(
      ts, static_cast<double>(gpu_mem_total.size()), track);
}

}  // namespace trace_processor
}  // namespace perfetto
