Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions android/framework/util/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
add_library(gfxrecon_util STATIC "")

add_library(perfetto STATIC ${CMAKE_CURRENT_LIST_DIR}/../../../../perfetto/sdk/perfetto.cc)

target_sources(gfxrecon_util
PRIVATE
${GFXRECON_SOURCE_DIR}/framework/util/argument_parser.h
Expand Down Expand Up @@ -66,7 +68,8 @@ target_include_directories(gfxrecon_util
${GFXRECON_SOURCE_DIR}/external/precompiled/android/include
${GFXRECON_SOURCE_DIR}/external/stb
${GFXRECON_SOURCE_DIR}/external/nlohmann/include
${GFXRECON_SOURCE_DIR}/framework)
${GFXRECON_SOURCE_DIR}/framework
${CMAKE_CURRENT_LIST_DIR}/../../../../perfetto/sdk)

target_link_libraries(gfxrecon_util
platform_specific
Expand All @@ -75,4 +78,5 @@ target_link_libraries(gfxrecon_util
spirv-reflect-static
${GFXRECON_SOURCE_DIR}/external/precompiled/android/lib/${ANDROID_ABI}/liblz4_static.a
${GFXRECON_SOURCE_DIR}/external/precompiled/android/lib/${ANDROID_ABI}/libzstd.a
z)
z
perfetto)
58 changes: 56 additions & 2 deletions framework/encode/capture_manager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,18 +43,26 @@

#include <cassert>
#include <cstdlib>
#include <format>
#include <iomanip>
#include <unordered_map>
#include <perfetto.h>

#if defined(__unix__)
extern char** environ;
#endif

PERFETTO_DEFINE_CATEGORIES(perfetto::Category("GFXR").SetDescription("Events from the graphics subsystem"));

// PERFETTO_TRACK_EVENT_STATIC_STORAGE();

GFXRECON_BEGIN_NAMESPACE(gfxrecon)
GFXRECON_BEGIN_NAMESPACE(encode)

// One based frame count.
const uint32_t kFirstFrame = 1;
const size_t kFileStreamBufferSize = 256 * 1024;
const uint32_t kFirstFrame = 1;
const size_t kFileStreamBufferSize = 256 * 1024;
static const int PERFETTO_TRACK_ID = 1234561;

std::mutex CommonCaptureManager::ThreadData::count_lock_;
format::ThreadId CommonCaptureManager::ThreadData::thread_count_ = 0;
Expand Down Expand Up @@ -110,6 +118,23 @@ CommonCaptureManager::CommonCaptureManager() :
write_assets_(false), previous_write_assets_(false), write_state_files_(false)
{}

ParameterEncoder* CommonCaptureManager::BeginTrackedApiCallCapture(format::ApiCallId call_id)
{
std::string tag = "BeginTrackedApiCallCapture 0x" + std::to_string(static_cast<uint16_t>(call_id));
char* charTag = new char[tag.length() + 1];
strcpy(charTag, tag.c_str());
if (capture_mode_ != kModeDisabled)
{
// These are potentially interesting as rather fine-grained traces.
// TRACE_EVENT_BEGIN("GFXR", charTag, perfetto::Track(1234561));
ParameterEncoder* ans = InitApiCallCapture(call_id);
// TRACE_EVENT_END("GFXR");
return ans;
}

return nullptr;
}

CommonCaptureManager::~CommonCaptureManager()
{
if (memory_tracking_mode_ == CaptureSettings::MemoryTrackingMode::kPageGuard ||
Expand All @@ -118,6 +143,11 @@ CommonCaptureManager::~CommonCaptureManager()
util::PageGuardManager::Destroy();
}

if (perfetto::Tracing::IsInitialized())
{
// TODO: appropriately flush events and shit down Perfetto.
}

util::Log::Release();
}

Expand Down Expand Up @@ -771,6 +801,7 @@ void CommonCaptureManager::CheckStartCaptureForTrackMode(format::ApiFamilyId api
{
if (!trim_ranges_.empty())
{
TRACE_EVENT_BEGIN("GFXR", "!trim_ranges_.empty() branch", perfetto::Track(PERFETTO_TRACK_ID));
if (current_boundary_count == trim_ranges_[trim_current_range_].first)
{
const auto& trim_range = trim_ranges_[trim_current_range_];
Expand All @@ -786,16 +817,22 @@ void CommonCaptureManager::CheckStartCaptureForTrackMode(format::ApiFamilyId api
capture_mode_ = kModeDisabled;
}
}
TRACE_EVENT_END("GFXR", perfetto::Track(PERFETTO_TRACK_ID));
}
else if (IsTrimHotkeyPressed() || RuntimeTriggerEnabled())
{
TRACE_EVENT_BEGIN("GFXR", "CreateCaptureFile", perfetto::Track(PERFETTO_TRACK_ID));
bool success =
CreateCaptureFile(api_family, util::filepath::InsertFilenamePostfix(base_filename_, "_trim_trigger"));
TRACE_EVENT_END("GFXR", perfetto::Track(PERFETTO_TRACK_ID));

if (success)
{
TRACE_EVENT_BEGIN("GFXR", "ActivateTrimming", perfetto::Track(PERFETTO_TRACK_ID));

trim_key_first_frame_ = current_boundary_count;
ActivateTrimming();
TRACE_EVENT_END("GFXR", perfetto::Track(PERFETTO_TRACK_ID));
}
else
{
Expand All @@ -808,6 +845,8 @@ void CommonCaptureManager::CheckStartCaptureForTrackMode(format::ApiFamilyId api
// Check to see if an asset dumping has been requested outside of capture range
if (use_asset_file_ && (RuntimeWriteAssetsEnabled() || write_assets_) && capture_mode_ == kModeTrack)
{

TRACE_EVENT_BEGIN("GFXR", "RuntimeWriteAssetsEnabled() branch", perfetto::Track(PERFETTO_TRACK_ID));
capture_mode_ |= kModeWrite;

auto thread_data = GetThreadData();
Expand All @@ -825,6 +864,7 @@ void CommonCaptureManager::CheckStartCaptureForTrackMode(format::ApiFamilyId api

capture_mode_ = kModeTrack;
write_assets_ = false;
TRACE_EVENT_END("GFXR", perfetto::Track(PERFETTO_TRACK_ID));
}
}

Expand Down Expand Up @@ -873,7 +913,9 @@ void CommonCaptureManager::WriteFrameMarker(format::MarkerType marker_type)
void CommonCaptureManager::EndFrame(format::ApiFamilyId api_family)
{
// Write an end-of-frame marker to the capture file.
TRACE_EVENT_BEGIN("GFXR", "WriteFrameMarker", perfetto::Track(PERFETTO_TRACK_ID));
WriteFrameMarker(format::MarkerType::kEndMarker);
TRACE_EVENT_END("GFXR", perfetto::Track(PERFETTO_TRACK_ID));

++current_frame_;

Expand All @@ -883,25 +925,33 @@ void CommonCaptureManager::EndFrame(format::ApiFamilyId api_family)
{
// Currently capturing a frame range.
// Check for end of range or hotkey trigger to stop capture.
TRACE_EVENT_BEGIN("GFXR", "CheckContinueCaptureForWriteMode", perfetto::Track(PERFETTO_TRACK_ID));
CheckContinueCaptureForWriteMode(api_family, current_frame_);
TRACE_EVENT_END("GFXR", perfetto::Track(PERFETTO_TRACK_ID));
}
else if ((capture_mode_ & kModeTrack) == kModeTrack)
{
// Capture is not active.
// Check for start of capture frame range or hotkey trigger to start capture
TRACE_EVENT_BEGIN("GFXR", "CheckStartCaptureForTrackMode", perfetto::Track(PERFETTO_TRACK_ID));
CheckStartCaptureForTrackMode(api_family, current_frame_);
TRACE_EVENT_END("GFXR", perfetto::Track(PERFETTO_TRACK_ID));
}
}

if (IsCaptureModeWrite() && write_state_files_)
{
TRACE_EVENT_BEGIN("GFXR", "WriteFrameStateFile", perfetto::Track(PERFETTO_TRACK_ID));
WriteFrameStateFile();
TRACE_EVENT_END("GFXR", perfetto::Track(PERFETTO_TRACK_ID));
}

// Flush after presents to help avoid capture files with incomplete final blocks.
if (file_stream_.get() != nullptr)
{
TRACE_EVENT_BEGIN("GFXR", "file_stream_->Flush", perfetto::Track(PERFETTO_TRACK_ID));
file_stream_->Flush();
TRACE_EVENT_END("GFXR", perfetto::Track(PERFETTO_TRACK_ID));
}

// Terminate process if this was the last trim range and the user has asked to do so
Expand Down Expand Up @@ -1156,15 +1206,19 @@ void CommonCaptureManager::ActivateTrimming()
{
capture_mode_ |= kModeWrite;

TRACE_EVENT_BEGIN("GFXR", "GetThreadData", perfetto::Track(PERFETTO_TRACK_ID));
auto thread_data = GetThreadData();
assert(thread_data != nullptr);
TRACE_EVENT_END("GFXR", perfetto::Track(PERFETTO_TRACK_ID));

if (!write_state_files_)
{
for (auto& manager : api_capture_managers_)
{
TRACE_EVENT_BEGIN("GFXR", "WriteTrackedState", perfetto::Track(PERFETTO_TRACK_ID));
manager.first->WriteTrackedState(
file_stream_.get(), thread_data->thread_id_, use_asset_file_ ? asset_file_stream_.get() : nullptr);
TRACE_EVENT_END("GFXR", perfetto::Track(PERFETTO_TRACK_ID));
}
}
}
Expand Down
10 changes: 1 addition & 9 deletions framework/encode/capture_manager.h
Original file line number Diff line number Diff line change
Expand Up @@ -71,15 +71,7 @@ class CommonCaptureManager
return &thread_data->handle_unwrap_memory_;
}

ParameterEncoder* BeginTrackedApiCallCapture(format::ApiCallId call_id)
{
if (capture_mode_ != kModeDisabled)
{
return InitApiCallCapture(call_id);
}

return nullptr;
}
ParameterEncoder* BeginTrackedApiCallCapture(format::ApiCallId call_id);

ParameterEncoder* BeginApiCallCapture(format::ApiCallId call_id)
{
Expand Down
58 changes: 58 additions & 0 deletions framework/encode/vulkan_capture_manager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@

#include "encode/struct_pointer_encoder.h"
#include "encode/vulkan_capture_manager.h"
#include "encode/capture_manager.h"

#include "encode/vulkan_handle_wrapper_util.h"
#include "encode/vulkan_state_writer.h"
Expand All @@ -45,6 +46,9 @@

#include <cassert>
#include <unordered_set>
#include <perfetto.h>

PERFETTO_DEFINE_CATEGORIES(perfetto::Category("GFXR").SetDescription("Events from the graphics subsystem"));

#if defined(__linux__) && !defined(__ANDROID__)
#if defined(VK_USE_PLATFORM_XCB_KHR)
Expand All @@ -61,6 +65,7 @@ GFXRECON_BEGIN_NAMESPACE(encode)

VulkanCaptureManager* VulkanCaptureManager::singleton_ = nullptr;
VulkanLayerTable VulkanCaptureManager::vulkan_layer_table_;
static const int PERFETTO_TRACK_ID = 1234561;

bool VulkanCaptureManager::CreateInstance()
{
Expand All @@ -73,6 +78,22 @@ bool VulkanCaptureManager::CreateInstance()
VK_VERSION_MINOR(VK_HEADER_VERSION_COMPLETE),
VK_VERSION_PATCH(VK_HEADER_VERSION_COMPLETE));

if (!perfetto::Tracing::IsInitialized())
{
perfetto::TracingInitArgs args;
args.backends |= perfetto::kInProcessBackend;
args.backends |= perfetto::kSystemBackend;
perfetto::Tracing::Initialize(args);
perfetto::TrackEvent::Register();

GFXRECON_LOG_INFO("Init perfetto in VulkanCaptureManager");

int trackId = PERFETTO_TRACK_ID;
auto trackDesc = perfetto::Track(trackId).Serialize();
trackDesc.set_name("GFXR capture");
perfetto::TrackEvent::SetTrackDescriptor(perfetto::Track(trackId), trackDesc);
}

return result;
}

Expand Down Expand Up @@ -2415,27 +2436,58 @@ void VulkanCaptureManager::PostProcess_vkGetDeviceGroupSurfacePresentModes2EXT(
}
}

void VulkanCaptureManager::PostProcess_vkQueuePresentKHR(VkResult result,
VkQueue queue,
const VkPresentInfoKHR* pPresentInfo)
{
if (IsCaptureModeTrack() && ((result == VK_SUCCESS) || (result == VK_SUBOPTIMAL_KHR)))
{
assert((state_tracker_ != nullptr) && (pPresentInfo != nullptr));
TRACE_EVENT_BEGIN("GFXR", "TrackSemaphoreSignalState", perfetto::Track(PERFETTO_TRACK_ID));
state_tracker_->TrackSemaphoreSignalState(
pPresentInfo->waitSemaphoreCount, pPresentInfo->pWaitSemaphores, 0, nullptr);
TRACE_EVENT_END("GFXR", perfetto::Track(PERFETTO_TRACK_ID));

TRACE_EVENT_BEGIN("GFXR", "TrackPresentedImages", perfetto::Track(PERFETTO_TRACK_ID));
state_tracker_->TrackPresentedImages(
pPresentInfo->swapchainCount, pPresentInfo->pSwapchains, pPresentInfo->pImageIndices, queue);
TRACE_EVENT_END("GFXR", perfetto::Track(PERFETTO_TRACK_ID));
}
TRACE_EVENT_BEGIN("GFXR", "EndFrame", perfetto::Track(PERFETTO_TRACK_ID));
EndFrame();
TRACE_EVENT_END("GFXR", perfetto::Track(PERFETTO_TRACK_ID));
}

void VulkanCaptureManager::PreProcess_vkQueueSubmit(VkQueue queue,
uint32_t submitCount,
const VkSubmitInfo* pSubmits,
VkFence fence)
{
TRACE_EVENT_BEGIN("GFXR", "params", perfetto::Track(PERFETTO_TRACK_ID));
GFXRECON_UNREFERENCED_PARAMETER(queue);
GFXRECON_UNREFERENCED_PARAMETER(submitCount);
GFXRECON_UNREFERENCED_PARAMETER(pSubmits);
GFXRECON_UNREFERENCED_PARAMETER(fence);
TRACE_EVENT_END("GFXR", perfetto::Track(PERFETTO_TRACK_ID));

// This must be done before QueueSubmitWriteFillMemoryCmd is called
// and tracked mapped memory regions are resetted
if (IsCaptureModeTrack())
{
TRACE_EVENT_BEGIN("GFXR", "TrackSubmission", perfetto::Track(PERFETTO_TRACK_ID));
state_tracker_->TrackSubmission(submitCount, pSubmits);
TRACE_EVENT_END("GFXR", perfetto::Track(PERFETTO_TRACK_ID));
}

TRACE_EVENT_BEGIN("GFXR", "QueueSubmitWriteFillMemoryCmd", perfetto::Track(PERFETTO_TRACK_ID));
QueueSubmitWriteFillMemoryCmd();
TRACE_EVENT_END("GFXR", perfetto::Track(PERFETTO_TRACK_ID));

TRACE_EVENT_BEGIN("GFXR", "PreQueueSubmit", perfetto::Track(PERFETTO_TRACK_ID));
PreQueueSubmit();
TRACE_EVENT_END("GFXR", perfetto::Track(PERFETTO_TRACK_ID));

TRACE_EVENT_BEGIN("GFXR", "TrackTlasToBlasDependencies loop", perfetto::Track(PERFETTO_TRACK_ID));
if (IsCaptureModeTrack())
{
if (pSubmits)
Expand All @@ -2447,6 +2499,7 @@ void VulkanCaptureManager::PreProcess_vkQueueSubmit(VkQueue queue,
}
}
}
TRACE_EVENT_END("GFXR", perfetto::Track(PERFETTO_TRACK_ID));
}

void VulkanCaptureManager::PreProcess_vkQueueSubmit2(VkQueue queue,
Expand Down Expand Up @@ -2496,15 +2549,19 @@ void VulkanCaptureManager::QueueSubmitWriteFillMemoryCmd()
if (GetMemoryTrackingMode() == CaptureSettings::MemoryTrackingMode::kPageGuard ||
GetMemoryTrackingMode() == CaptureSettings::MemoryTrackingMode::kUserfaultfd)
{
TRACE_EVENT_BEGIN("GFXR", "PageGuard", perfetto::Track(PERFETTO_TRACK_ID));

util::PageGuardManager* manager = util::PageGuardManager::Get();
assert(manager != nullptr);

manager->ProcessMemoryEntries([this](uint64_t memory_id, void* start_address, size_t offset, size_t size) {
WriteFillMemoryCmd(memory_id, offset, size, start_address);
});
TRACE_EVENT_END("GFXR", perfetto::Track(PERFETTO_TRACK_ID));
}
else if (GetMemoryTrackingMode() == CaptureSettings::MemoryTrackingMode::kUnassisted)
{
TRACE_EVENT_BEGIN("GFXR", "kUnassisted", perfetto::Track(PERFETTO_TRACK_ID));
std::lock_guard<std::mutex> lock(GetMappedMemoryLock());

for (auto wrapper : mapped_memory_)
Expand All @@ -2520,6 +2577,7 @@ void VulkanCaptureManager::QueueSubmitWriteFillMemoryCmd()
// We set offset to 0, because the pointer returned by vkMapMemory already includes the offset.
WriteFillMemoryCmd(wrapper->handle_id, 0, size, wrapper->mapped_data);
}
TRACE_EVENT_END("GFXR", perfetto::Track(PERFETTO_TRACK_ID));
}
}

Expand Down
Loading