Skip to content

Commit

Permalink
encode: OutputStreamWriter and CommandWriter
Browse files Browse the repository at this point in the history
Introduce two new classes to extract some common code.

The OutputStreamWriter is inherited by both the capture manager and the
state tracker and provides common utilities for writing to an output
stream.

The CommandWriter is an encode utility for writing commands to an
outpust stream and it is used by both the capture manager and the state
tracker.
  • Loading branch information
antonio-lunarg committed Jan 8, 2025
1 parent 8d1633c commit 8e6c181
Show file tree
Hide file tree
Showing 17 changed files with 682 additions and 297 deletions.
3 changes: 3 additions & 0 deletions android/framework/encode/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ target_sources(gfxrecon_encode
${GFXRECON_SOURCE_DIR}/framework/encode/capture_manager.cpp
${GFXRECON_SOURCE_DIR}/framework/encode/capture_settings.h
${GFXRECON_SOURCE_DIR}/framework/encode/capture_settings.cpp
${GFXRECON_SOURCE_DIR}/framework/encode/command_writer.h
${GFXRECON_SOURCE_DIR}/framework/encode/command_writer.cpp
${GFXRECON_SOURCE_DIR}/framework/encode/custom_vulkan_encoder_commands.h
${GFXRECON_SOURCE_DIR}/framework/encode/custom_vulkan_api_call_encoders.h
${GFXRECON_SOURCE_DIR}/framework/encode/custom_vulkan_api_call_encoders.cpp
Expand All @@ -19,6 +21,7 @@ target_sources(gfxrecon_encode
${GFXRECON_SOURCE_DIR}/framework/encode/custom_vulkan_struct_handle_wrappers.cpp
${GFXRECON_SOURCE_DIR}/framework/encode/descriptor_update_template_info.h
${GFXRECON_SOURCE_DIR}/framework/encode/handle_unwrap_memory.h
${GFXRECON_SOURCE_DIR}/framework/encode/output_stream_writer.h
${GFXRECON_SOURCE_DIR}/framework/encode/parameter_buffer.h
${GFXRECON_SOURCE_DIR}/framework/encode/parameter_encoder.h
${GFXRECON_SOURCE_DIR}/framework/encode/scoped_destroy_lock.h
Expand Down
2 changes: 2 additions & 0 deletions android/framework/util/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ target_sources(gfxrecon_util
${GFXRECON_SOURCE_DIR}/framework/util/spirv_parsing_util.cpp
${GFXRECON_SOURCE_DIR}/framework/util/strings.h
${GFXRECON_SOURCE_DIR}/framework/util/strings.cpp
${GFXRECON_SOURCE_DIR}/framework/util/thread_data.h
${GFXRECON_SOURCE_DIR}/framework/util/thread_data.cpp
${GFXRECON_SOURCE_DIR}/framework/util/to_string.h
${GFXRECON_SOURCE_DIR}/framework/util/to_string.cpp
${GFXRECON_SOURCE_DIR}/framework/util/options.h
Expand Down
4 changes: 3 additions & 1 deletion framework/encode/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
###############################################################################
# Copyright (c) 2018-2022 LunarG, Inc.
# Copyright (c) 2018-2025 LunarG, Inc.
# Copyright (c) 2019-2023 Advanced Micro Devices, Inc.
# All rights reserved
#
Expand Down Expand Up @@ -36,6 +36,8 @@ target_sources(gfxrecon_encode
${CMAKE_CURRENT_LIST_DIR}/capture_manager.cpp
${CMAKE_CURRENT_LIST_DIR}/capture_settings.h
${CMAKE_CURRENT_LIST_DIR}/capture_settings.cpp
${CMAKE_CURRENT_LIST_DIR}/command_writer.h
${CMAKE_CURRENT_LIST_DIR}/command_writer.cpp
${CMAKE_CURRENT_LIST_DIR}/custom_vulkan_encoder_commands.h
${CMAKE_CURRENT_LIST_DIR}/custom_vulkan_api_call_encoders.h
${CMAKE_CURRENT_LIST_DIR}/custom_vulkan_api_call_encoders.cpp
Expand Down
37 changes: 16 additions & 21 deletions framework/encode/api_capture_manager.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*
** Copyright (c) 2018-2022 Valve Corporation
** Copyright (c) 2018-2024 LunarG, Inc.
** Copyright (c) 2018-2025 LunarG, Inc.
** Copyright (c) 2019-2023 Advanced Micro Devices, Inc. All rights reserved.
**
** Permission is hereby granted, free of charge, to any person obtaining a
Expand Down Expand Up @@ -43,16 +43,16 @@ class ApiCaptureManager
static auto AcquireExclusiveApiCallLock() { return std::move(CommonCaptureManager::AcquireExclusiveApiCallLock()); }

// Virtual interface
virtual void CreateStateTracker() = 0;
virtual void DestroyStateTracker() = 0;
virtual void WriteTrackedState(util::FileOutputStream* file_stream, format::ThreadId thread_id) = 0;
virtual void CreateStateTracker() = 0;
virtual void DestroyStateTracker() = 0;
virtual void WriteTrackedState(util::FileOutputStream* file_stream, util::ThreadData* thread_data) = 0;
virtual void WriteTrackedStateWithAssetFile(util::FileOutputStream* file_stream,
format::ThreadId thread_id,
util::ThreadData* thread_data,
util::FileOutputStream* asset_file_stream,
const std::string* asset_file_name) = 0;
const std::string* asset_file_name) = 0;
virtual void WriteAssets(util::FileOutputStream* asset_file_stream,
const std::string* asset_file_name,
format::ThreadId thread_id) = 0;
util::ThreadData* thread_data) = 0;

virtual CaptureSettings::TraceSettings GetDefaultTraceSettings();

Expand Down Expand Up @@ -212,12 +212,6 @@ class ApiCaptureManager
common_manager_->WriteEndResourceInitCmd(api_family_, device_id);
}

void WriteInitBufferCmd(
format::HandleId device_id, format::HandleId buffer_id, uint64_t offset, uint64_t size, const void* data)
{
common_manager_->WriteInitBufferCmd(api_family_, device_id, buffer_id, offset, size, data);
}

void WriteCreateHeapAllocationCmd(uint64_t allocation_id, uint64_t allocation_size)
{
common_manager_->WriteCreateHeapAllocationCmd(api_family_, allocation_id, allocation_size);
Expand All @@ -230,14 +224,15 @@ class ApiCaptureManager
common_manager_->CombineAndWriteToFile<N>(buffers);
}

CommonCaptureManager::ThreadData* GetThreadData() { return common_manager_->GetThreadData(); }
util::Compressor* GetCompressor() { return common_manager_->GetCompressor(); }
std::mutex& GetMappedMemoryLock() { return common_manager_->GetMappedMemoryLock(); }
util::Keyboard& GetKeyboard() { return common_manager_->GetKeyboard(); }
const std::string& GetScreenshotPrefix() const { return common_manager_->GetScreenshotPrefix(); }
util::ScreenshotFormat GetScreenshotFormat() { return common_manager_->GetScreenshotFormat(); }
auto GetTrimBoundary() const { return common_manager_->GetTrimBoundary(); }
auto GetTrimDrawCalls() const { return common_manager_->GetTrimDrawCalls(); }
util::ThreadData* GetThreadData() { return common_manager_->GetThreadData(); }
util::Compressor* GetCompressor() { return common_manager_->GetCompressor(); }
std::mutex& GetMappedMemoryLock() { return common_manager_->GetMappedMemoryLock(); }
util::Keyboard& GetKeyboard() { return common_manager_->GetKeyboard(); }
const std::string& GetScreenshotPrefix() const { return common_manager_->GetScreenshotPrefix(); }
util::ScreenshotFormat GetScreenshotFormat() { return common_manager_->GetScreenshotFormat(); }
auto GetTrimBoundary() const { return common_manager_->GetTrimBoundary(); }
auto GetTrimDrawCalls() const { return common_manager_->GetTrimDrawCalls(); }
CommandWriter* GetCommandWriter() { return common_manager_->GetCommandWriter(); }

protected:
const format::ApiFamilyId api_family_;
Expand Down
129 changes: 19 additions & 110 deletions framework/encode/capture_manager.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*
** Copyright (c) 2018-2022 Valve Corporation
** Copyright (c) 2018-2022 LunarG, Inc.
** Copyright (c) 2018-2025 LunarG, Inc.
** Copyright (c) 2019-2023 Advanced Micro Devices, Inc. All rights reserved.
**
** Permission is hereby granted, free of charge, to any person obtaining a
Expand Down Expand Up @@ -55,46 +55,13 @@ GFXRECON_BEGIN_NAMESPACE(encode)
const uint32_t kFirstFrame = 1;
const size_t kFileStreamBufferSize = 256 * 1024;

std::mutex CommonCaptureManager::ThreadData::count_lock_;
format::ThreadId CommonCaptureManager::ThreadData::thread_count_ = 0;
std::unordered_map<uint64_t, format::ThreadId> CommonCaptureManager::ThreadData::id_map_;

CommonCaptureManager* CommonCaptureManager::singleton_;
std::mutex CommonCaptureManager::instance_lock_;
thread_local std::unique_ptr<CommonCaptureManager::ThreadData> CommonCaptureManager::thread_data_;
CommonCaptureManager::ApiCallMutexT CommonCaptureManager::api_call_mutex_;
CommonCaptureManager* CommonCaptureManager::singleton_;
std::mutex CommonCaptureManager::instance_lock_;
thread_local std::unique_ptr<util::ThreadData> CommonCaptureManager::thread_data_;
CommonCaptureManager::ApiCallMutexT CommonCaptureManager::api_call_mutex_;

std::atomic<format::HandleId> CommonCaptureManager::unique_id_counter_{ format::kNullHandleId };

CommonCaptureManager::ThreadData::ThreadData() :
thread_id_(GetThreadId()), object_id_(format::kNullHandleId), call_id_(format::ApiCallId::ApiCall_Unknown),
block_index_(0)
{
parameter_buffer_ = std::make_unique<encode::ParameterBuffer>();
parameter_encoder_ = std::make_unique<ParameterEncoder>(parameter_buffer_.get());
}

format::ThreadId CommonCaptureManager::ThreadData::GetThreadId()
{
format::ThreadId id = 0;
uint64_t tid = util::platform::GetCurrentThreadId();

// Using a uint64_t sequence number associated with the thread ID.
std::lock_guard<std::mutex> lock(count_lock_);
auto entry = id_map_.find(tid);
if (entry != id_map_.end())
{
id = entry->second;
}
else
{
id = ++thread_count_;
id_map_.insert(std::make_pair(tid, id));
}

return id;
}

CommonCaptureManager::CommonCaptureManager() :
force_file_flush_(false), timestamp_filename_(true),
memory_tracking_mode_(CaptureSettings::MemoryTrackingMode::kPageGuard), page_guard_align_buffer_sizes_(false),
Expand Down Expand Up @@ -491,14 +458,19 @@ bool CommonCaptureManager::Initialize(format::ApiFamilyId api_
capture_mode_ = kModeDisabled;
}

if (success)
{
command_writer_ = std::make_unique<CommandWriter>(this, compressor_.get());
}

return success;
}

CommonCaptureManager::ThreadData* CommonCaptureManager::GetThreadData()
util::ThreadData* CommonCaptureManager::GetThreadData()
{
if (!thread_data_)
{
thread_data_ = std::make_unique<ThreadData>();
thread_data_ = std::make_unique<util::ThreadData>();
}
return thread_data_.get();
}
Expand Down Expand Up @@ -834,15 +806,15 @@ void CommonCaptureManager::CheckStartCaptureForTrackMode(format::ApiFamilyId
{
capture_mode_ |= kModeWrite;

auto thread_data = GetThreadData();
assert(thread_data != nullptr);
auto* thread_data = GetThreadData();
GFXRECON_ASSERT(thread_data != nullptr);

std::unique_ptr<util::FileOutputStream> asset_file_stream = CreateAssetFile();
if (asset_file_stream)
{
for (auto& manager : api_capture_managers_)
{
manager.first->WriteAssets(asset_file_stream.get(), &asset_file_name_, thread_data->thread_id_);
manager.first->WriteAssets(asset_file_stream.get(), &asset_file_name_, thread_data);
}
}

Expand Down Expand Up @@ -1226,22 +1198,22 @@ void CommonCaptureManager::ActivateTrimming(std::shared_lock<ApiCallMutexT>& cur

capture_mode_ |= kModeWrite;

auto thread_data = GetThreadData();
assert(thread_data != nullptr);
auto* thread_data = GetThreadData();
GFXRECON_ASSERT(thread_data != nullptr);
if (use_asset_file_)
{
std::unique_ptr<util::FileOutputStream> asset_file_stream = CreateAssetFile();
for (auto& manager : api_capture_managers_)
{
manager.first->WriteTrackedStateWithAssetFile(
file_stream_.get(), thread_data->thread_id_, asset_file_stream.get(), &asset_file_name_);
file_stream_.get(), thread_data, asset_file_stream.get(), &asset_file_name_);
}
}
else
{
for (auto& manager : api_capture_managers_)
{
manager.first->WriteTrackedState(file_stream_.get(), thread_data->thread_id_);
manager.first->WriteTrackedState(file_stream_.get(), thread_data);
}
}
}
Expand Down Expand Up @@ -1507,69 +1479,6 @@ void CommonCaptureManager::WriteEndResourceInitCmd(format::ApiFamilyId api_famil
WriteToFile(&init_cmd, sizeof(init_cmd));
}

void CommonCaptureManager::WriteInitBufferCmd(format::ApiFamilyId api_family,
format::HandleId device_id,
format::HandleId buffer_id,
uint64_t offset,
uint64_t size,
const void* data)
{
if ((capture_mode_ & kModeWrite) != kModeWrite)
{
return;
}

GFXRECON_CHECK_CONVERSION_DATA_LOSS(size_t, size);

format::InitBufferCommandHeader init_cmd;
size_t header_size = sizeof(format::InitBufferCommandHeader);
const uint8_t* uncompressed_data = (static_cast<const uint8_t*>(data) + offset);
size_t uncompressed_size = static_cast<size_t>(size);

auto thread_data = GetThreadData();
assert(thread_data != nullptr);

init_cmd.meta_header.block_header.type = format::BlockType::kMetaDataBlock;
init_cmd.meta_header.meta_data_id = format::MakeMetaDataId(api_family, format::MetaDataType::kInitBufferCommand);
init_cmd.thread_id = thread_data->thread_id_;
init_cmd.device_id = device_id;
init_cmd.buffer_id = buffer_id;
init_cmd.data_size = size;

bool not_compressed = true;

if (compressor_ != nullptr)
{
size_t compressed_size =
compressor_->Compress(uncompressed_size, uncompressed_data, &thread_data->compressed_buffer_, header_size);

if ((compressed_size > 0) && (compressed_size < uncompressed_size))
{
not_compressed = false;

// We don't have a special header for compressed fill commands because the header always includes
// the uncompressed size, so we just change the type to indicate the data is compressed.
init_cmd.meta_header.block_header.type = format::BlockType::kCompressedMetaDataBlock;

// Calculate size of packet with uncompressed data size.
init_cmd.meta_header.block_header.size = format::GetMetaDataBlockBaseSize(init_cmd) + compressed_size;

// Copy header to beginning of compressed_buffer_
util::platform::MemoryCopy(thread_data->compressed_buffer_.data(), header_size, &init_cmd, header_size);

WriteToFile(thread_data->compressed_buffer_.data(), header_size + compressed_size);
}
}

if (not_compressed)
{
// Calculate size of packet with compressed data size.
init_cmd.meta_header.block_header.size = format::GetMetaDataBlockBaseSize(init_cmd) + uncompressed_size;

CombineAndWriteToFile({ { &init_cmd, header_size }, { uncompressed_data, uncompressed_size } });
}
}

void CommonCaptureManager::WriteCreateHeapAllocationCmd(format::ApiFamilyId api_family,
uint64_t allocation_id,
uint64_t allocation_size)
Expand Down
Loading

0 comments on commit 8e6c181

Please sign in to comment.