Skip to content

Commit

Permalink
Enable trimming to queue submission range
Browse files Browse the repository at this point in the history
Enable trimming based on a range of queue submissions--vkQueueSubmit for
Vulkan, ExecuteCommandLists for DX12. Trimming is activated immediately
before the first submission and deactivated immediately after the last
submission in the range(s) specified.
  • Loading branch information
davidd-lunarg committed Jul 19, 2023
1 parent 6ce17a4 commit cbc1313
Show file tree
Hide file tree
Showing 7 changed files with 150 additions and 31 deletions.
99 changes: 76 additions & 23 deletions framework/encode/capture_manager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -92,8 +92,9 @@ CaptureManager::CaptureManager(format::ApiFamilyId api_family) :
api_family_(api_family), force_file_flush_(false), timestamp_filename_(true),
memory_tracking_mode_(CaptureSettings::MemoryTrackingMode::kPageGuard), page_guard_align_buffer_sizes_(false),
page_guard_track_ahb_memory_(false), page_guard_unblock_sigsegv_(false), page_guard_signal_handler_watcher_(false),
page_guard_memory_mode_(kMemoryModeShadowInternal), trim_enabled_(false), trim_current_range_(0),
current_frame_(kFirstFrame), capture_mode_(kModeWrite), previous_hotkey_state_(false),
page_guard_memory_mode_(kMemoryModeShadowInternal), trim_enabled_(false),
trim_boundary_(CaptureSettings::TrimBoundary::kUnknown), trim_current_range_(0), current_frame_(kFirstFrame),
queue_submit_count_(0), capture_mode_(kModeWrite), previous_hotkey_state_(false),
previous_runtime_trigger_state_(CaptureSettings::RuntimeTriggerState::kNotUsed), debug_layer_(false),
debug_device_lost_(false), screenshot_prefix_(""), screenshots_enabled_(false), disable_dxr_(false),
accel_struct_padding_(0), iunknown_wrapping_(false), force_command_serialization_(false), queue_zero_only_(false),
Expand Down Expand Up @@ -321,15 +322,22 @@ bool CaptureManager::Initialize(std::string base_filename, const CaptureSettings
}
else
{
GFXRECON_ASSERT(trace_settings.trim_boundary != CaptureSettings::TrimBoundary::kUnknown);

// Override default kModeWrite capture mode.
trim_enabled_ = true;
trim_enabled_ = true;
trim_boundary_ = trace_settings.trim_boundary;

// Determine if trim starts at the first frame
// Check if trim ranges were specified.
if (!trace_settings.trim_ranges.empty())
{
GFXRECON_ASSERT((trim_boundary_ == CaptureSettings::TrimBoundary::kFrames) ||
(trim_boundary_ == CaptureSettings::TrimBoundary::kQueueSubmits));

trim_ranges_ = trace_settings.trim_ranges;

if (trim_ranges_[0].first == current_frame_)
// Determine if trim starts at the first frame
if ((trim_boundary_ == CaptureSettings::TrimBoundary::kFrames) && (trim_ranges_[0].first == current_frame_))
{
// When capturing from the first frame, state tracking only needs to be enabled if there is more than
// one capture range.
Expand All @@ -345,10 +353,13 @@ bool CaptureManager::Initialize(std::string base_filename, const CaptureSettings
capture_mode_ = kModeTrack;
}
}
// Check if trim is enabled by hot-key trigger at the first frame
// Check if trim is enabled by hot-key trigger at the first frame.
else if (!trace_settings.trim_key.empty() ||
trace_settings.runtime_capture_trigger != CaptureSettings::RuntimeTriggerState::kNotUsed)
{
// Capture key/trigger only support frames as trim boundaries.
GFXRECON_ASSERT(trim_boundary_ == CaptureSettings::TrimBoundary::kFrames);

trim_key_ = trace_settings.trim_key;
trim_key_frames_ = trace_settings.trim_key_frames;
previous_runtime_trigger_state_ = trace_settings.runtime_capture_trigger;
Expand All @@ -369,7 +380,10 @@ bool CaptureManager::Initialize(std::string base_filename, const CaptureSettings
}
else
{
capture_mode_ = kModeTrack;
// if/else blocks above should have covered all "else" cases from the parent conditional.
GFXRECON_ASSERT(false);
trim_boundary_ = CaptureSettings::TrimBoundary::kUnknown;
capture_mode_ = kModeTrack;
}
}

Expand Down Expand Up @@ -592,11 +606,11 @@ bool CaptureManager::RuntimeTriggerDisabled()
return result;
}

void CaptureManager::CheckContinueCaptureForWriteMode()
void CaptureManager::CheckContinueCaptureForWriteMode(uint32_t current_boundary_count)
{
if (!trim_ranges_.empty())
{
if (current_frame_ == (trim_ranges_[trim_current_range_].last + 1))
if (current_boundary_count == (trim_ranges_[trim_current_range_].last + 1))
{
// Stop recording and close file.
DeactivateTrimming();
Expand All @@ -606,16 +620,17 @@ void CaptureManager::CheckContinueCaptureForWriteMode()
++trim_current_range_;
if (trim_current_range_ >= trim_ranges_.size())
{
// No more frames to capture. Capture can be disabled and resources can be released.
trim_enabled_ = false;
capture_mode_ = kModeDisabled;
// No more trim ranges to capture. Capture can be disabled and resources can be released.
trim_enabled_ = false;
trim_boundary_ = CaptureSettings::TrimBoundary::kUnknown;
capture_mode_ = kModeDisabled;
DestroyStateTracker();
compressor_ = nullptr;
}
else if (trim_ranges_[trim_current_range_].first == current_frame_)
else if (trim_ranges_[trim_current_range_].first == current_boundary_count)
{
// Trimming was configured to capture two consecutive frames, so we need to start a new capture
// file for the current frame.
// Trimming was configured to capture two consecutive ranges, so we need to start a new capture
// file for the current range.
const auto& trim_range = trim_ranges_[trim_current_range_];
bool success = CreateCaptureFile(CreateTrimFilename(base_filename_, trim_range));
if (success)
Expand All @@ -632,7 +647,7 @@ void CaptureManager::CheckContinueCaptureForWriteMode()
}
}
else if (IsTrimHotkeyPressed() ||
((trim_key_frames_ > 0) && (current_frame_ >= (trim_key_first_frame_ + trim_key_frames_))) ||
((trim_key_frames_ > 0) && (current_boundary_count >= (trim_key_first_frame_ + trim_key_frames_))) ||
RuntimeTriggerDisabled())
{
// Stop recording and close file.
Expand All @@ -641,11 +656,11 @@ void CaptureManager::CheckContinueCaptureForWriteMode()
}
}

void CaptureManager::CheckStartCaptureForTrackMode()
void CaptureManager::CheckStartCaptureForTrackMode(uint32_t current_boundary_count)
{
if (!trim_ranges_.empty())
{
if (current_frame_ == trim_ranges_[trim_current_range_].first)
if (current_boundary_count == trim_ranges_[trim_current_range_].first)
{
const auto& trim_range = trim_ranges_[trim_current_range_];
bool success = CreateCaptureFile(CreateTrimFilename(base_filename_, trim_range));
Expand All @@ -667,7 +682,7 @@ void CaptureManager::CheckStartCaptureForTrackMode()
if (success)
{

trim_key_first_frame_ = current_frame_;
trim_key_first_frame_ = current_boundary_count;
ActivateTrimming();
}
else
Expand Down Expand Up @@ -728,19 +743,19 @@ void CaptureManager::EndFrame()

++current_frame_;

if (trim_enabled_)
if (trim_enabled_ && (trim_boundary_ == CaptureSettings::TrimBoundary::kFrames))
{
if ((capture_mode_ & kModeWrite) == kModeWrite)
{
// Currently capturing a frame range.
// Check for end of range or hotkey trigger to stop capture.
CheckContinueCaptureForWriteMode();
CheckContinueCaptureForWriteMode(current_frame_);
}
else if ((capture_mode_ & kModeTrack) == kModeTrack)
{
// Capture is not active.
// Check for start of capture frame range or hotkey trigger to start capture
CheckStartCaptureForTrackMode();
CheckStartCaptureForTrackMode(current_frame_);
}
}

Expand All @@ -751,14 +766,52 @@ void CaptureManager::EndFrame()
}
}

void CaptureManager::PreQueueSubmit()
{
++queue_submit_count_;

if (trim_enabled_ && (trim_boundary_ == CaptureSettings::TrimBoundary::kQueueSubmits))
{
if (((capture_mode_ & kModeWrite) != kModeWrite) && ((capture_mode_ & kModeTrack) == kModeTrack))
{
// Capture is not active, check for start of capture frame range.
CheckStartCaptureForTrackMode(queue_submit_count_);
}
}
}

void CaptureManager::PostQueueSubmit()
{
if (trim_enabled_ && (trim_boundary_ == CaptureSettings::TrimBoundary::kQueueSubmits))
{
if ((capture_mode_ & kModeWrite) == kModeWrite)
{
// Currently capturing a queue submit range, check for end of range.
CheckContinueCaptureForWriteMode(queue_submit_count_);
}
}
}

std::string CaptureManager::CreateTrimFilename(const std::string& base_filename, const util::UintRange& trim_range)
{
GFXRECON_ASSERT(trim_range.last >= trim_range.first);

std::string range_string = "_";

uint32_t total = trim_range.last - trim_range.first + 1;
const char* boundary_str = total > 1 ? "frames_" : "frame_";
const char* boundary_str = "";
switch (trim_boundary_)
{
case CaptureSettings::TrimBoundary::kFrames:
boundary_str = total > 1 ? "frames_" : "frame_";
break;
case CaptureSettings::TrimBoundary::kQueueSubmits:
boundary_str = total > 1 ? "queue_submits_" : "queue_submit_";
break;
default:
GFXRECON_ASSERT(false);
break;
}

range_string += boundary_str;
range_string += std::to_string(trim_range.first);
Expand Down
11 changes: 9 additions & 2 deletions framework/encode/capture_manager.h
Original file line number Diff line number Diff line change
Expand Up @@ -116,13 +116,18 @@ class CaptureManager

void EndFrame();

// Pre/PostQueueSubmit to be called immediately before and after work is submitted to the GPU by vkQueueSubmit for
// Vulkan or by ID3D12CommandQueue::ExecuteCommandLists for DX12.
void PreQueueSubmit();
void PostQueueSubmit();

bool ShouldTriggerScreenshot();

util::ScreenshotFormat GetScreenshotFormat() { return screenshot_format_; }

void CheckContinueCaptureForWriteMode();
void CheckContinueCaptureForWriteMode(uint32_t current_boundary_count);

void CheckStartCaptureForTrackMode();
void CheckStartCaptureForTrackMode(uint32_t current_boundary_count);

bool IsTrimHotkeyPressed();

Expand Down Expand Up @@ -318,12 +323,14 @@ class CaptureManager
bool page_guard_signal_handler_watcher_;
PageGuardMemoryMode page_guard_memory_mode_;
bool trim_enabled_;
CaptureSettings::TrimBoundary trim_boundary_;
std::vector<util::UintRange> trim_ranges_;
std::string trim_key_;
uint32_t trim_key_frames_;
uint32_t trim_key_first_frame_;
size_t trim_current_range_;
uint32_t current_frame_;
uint32_t queue_submit_count_;
CaptureMode capture_mode_;
bool previous_hotkey_state_;
CaptureSettings::RuntimeTriggerState previous_runtime_trigger_state_;
Expand Down
51 changes: 45 additions & 6 deletions framework/encode/capture_settings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,8 @@ GFXRECON_BEGIN_NAMESPACE(encode)
#define CAPTURE_ANDROID_TRIGGER_UPPER "CAPTURE_ANDROID_TRIGGER"
#define CAPTURE_IUNKNOWN_WRAPPING_LOWER "capture_iunknown_wrapping"
#define CAPTURE_IUNKNOWN_WRAPPING_UPPER "CAPTURE_IUNKNOWN_WRAPPING"
#define CAPTURE_QUEUE_SUBMITS_LOWER "capture_queue_submits"
#define CAPTURE_QUEUE_SUBMITS_UPPER "CAPTURE_QUEUE_SUBMITS"
#define PAGE_GUARD_COPY_ON_MAP_LOWER "page_guard_copy_on_map"
#define PAGE_GUARD_COPY_ON_MAP_UPPER "PAGE_GUARD_COPY_ON_MAP"
#define PAGE_GUARD_SEPARATE_READ_LOWER "page_guard_separate_read"
Expand Down Expand Up @@ -160,6 +162,7 @@ const char kCaptureFramesEnvVar[] = GFXRECON_ENV_VAR_
const char kCaptureTriggerEnvVar[] = GFXRECON_ENV_VAR_PREFIX CAPTURE_TRIGGER_LOWER;
const char kCaptureTriggerFramesEnvVar[] = GFXRECON_ENV_VAR_PREFIX CAPTURE_TRIGGER_FRAMES_LOWER;
const char kCaptureIUnknownWrappingEnvVar[] = GFXRECON_ENV_VAR_PREFIX CAPTURE_IUNKNOWN_WRAPPING_LOWER;
const char kCaptureQueueSubmitsEnvVar[] = GFXRECON_ENV_VAR_PREFIX CAPTURE_QUEUE_SUBMITS_LOWER;
const char kPageGuardCopyOnMapEnvVar[] = GFXRECON_ENV_VAR_PREFIX PAGE_GUARD_COPY_ON_MAP_LOWER;
const char kPageGuardSeparateReadEnvVar[] = GFXRECON_ENV_VAR_PREFIX PAGE_GUARD_SEPARATE_READ_LOWER;
const char kPageGuardPersistentMemoryEnvVar[] = GFXRECON_ENV_VAR_PREFIX PAGE_GUARD_PERSISTENT_MEMORY_LOWER;
Expand Down Expand Up @@ -220,6 +223,7 @@ const char kPageGuardSignalHandlerWatcherMaxRestoresEnvVar[] = GFXRECON_ENV_VAR_
const char kCaptureTriggerEnvVar[] = GFXRECON_ENV_VAR_PREFIX CAPTURE_TRIGGER_UPPER;
const char kCaptureTriggerFramesEnvVar[] = GFXRECON_ENV_VAR_PREFIX CAPTURE_TRIGGER_FRAMES_UPPER;
const char kCaptureIUnknownWrappingEnvVar[] = GFXRECON_ENV_VAR_PREFIX CAPTURE_IUNKNOWN_WRAPPING_UPPER;
const char kCaptureQueueSubmitsEnvVar[] = GFXRECON_ENV_VAR_PREFIX CAPTURE_QUEUE_SUBMITS_UPPER;
const char kDebugLayerEnvVar[] = GFXRECON_ENV_VAR_PREFIX DEBUG_LAYER_UPPER;
const char kDebugDeviceLostEnvVar[] = GFXRECON_ENV_VAR_PREFIX DEBUG_DEVICE_LOST_UPPER;
const char kDisableDxrEnvVar[] = GFXRECON_ENV_VAR_PREFIX DISABLE_DXR_UPPER;
Expand Down Expand Up @@ -260,6 +264,7 @@ const std::string kOptionKeyCaptureFrames = std::stri
const std::string kOptionKeyCaptureTrigger = std::string(kSettingsFilter) + std::string(CAPTURE_TRIGGER_LOWER);
const std::string kOptionKeyCaptureTriggerFrames = std::string(kSettingsFilter) + std::string(CAPTURE_TRIGGER_FRAMES_LOWER);
const std::string kOptionKeyCaptureIUnknownWrapping = std::string(kSettingsFilter) + std::string(CAPTURE_IUNKNOWN_WRAPPING_LOWER);
const std::string kOptionKeyCaptureQueueSubmits = std::string(kSettingsFilter) + std::string(CAPTURE_QUEUE_SUBMITS_LOWER);
const std::string kOptionKeyPageGuardCopyOnMap = std::string(kSettingsFilter) + std::string(PAGE_GUARD_COPY_ON_MAP_LOWER);
const std::string kOptionKeyPageGuardSeparateRead = std::string(kSettingsFilter) + std::string(PAGE_GUARD_SEPARATE_READ_LOWER);
const std::string kOptionKeyPageGuardPersistentMemory = std::string(kSettingsFilter) + std::string(PAGE_GUARD_PERSISTENT_MEMORY_LOWER);
Expand Down Expand Up @@ -331,6 +336,10 @@ void CaptureSettings::LoadRunTimeEnvVarSettings(CaptureSettings* settings)
std::string value = util::platform::GetEnv(kCaptureAndroidTriggerEnvVar);
settings->trace_settings_.runtime_capture_trigger =
ParseAndroidRunTimeTrimState(value, settings->trace_settings_.runtime_capture_trigger);
if (!settings->trace_settings_.runtime_capture_trigger.empty())
{
settings->trace_settings_.trim_boundary = TrimBoundary::kFrames;
}
}
#endif
}
Expand Down Expand Up @@ -391,6 +400,7 @@ void CaptureSettings::LoadOptionsEnvVar(OptionsMap* options)
LoadSingleOptionEnvVar(options, kCaptureFramesEnvVar, kOptionKeyCaptureFrames);
LoadSingleOptionEnvVar(options, kCaptureTriggerEnvVar, kOptionKeyCaptureTrigger);
LoadSingleOptionEnvVar(options, kCaptureTriggerFramesEnvVar, kOptionKeyCaptureTriggerFrames);
LoadSingleOptionEnvVar(options, kCaptureQueueSubmitsEnvVar, kOptionKeyCaptureQueueSubmits);

// Page guard environment variables
LoadSingleOptionEnvVar(options, kPageGuardCopyOnMapEnvVar, kOptionKeyPageGuardCopyOnMap);
Expand Down Expand Up @@ -473,11 +483,36 @@ void CaptureSettings::ProcessOptions(OptionsMap* options, CaptureSettings* setti
FindOption(options, kOptionKeyMemoryTrackingMode), settings->trace_settings_.memory_tracking_mode);

// Trimming options:
// trim ranges and trim hotkey are exclusive
// with trim key will be parsed only
// if trim ranges is empty, else it will be ignored
ParseUintRangeList(
FindOption(options, kOptionKeyCaptureFrames), &settings->trace_settings_.trim_ranges, "capture frames");
// Trim frame ranges, trim queue submit ranges, and trim frame hotkey are mutually exclusive.
// Precedence is frame ranges, queue submit ranges, then frame hotkey.
std::string trim_frames = FindOption(options, kOptionKeyCaptureFrames);
if (!trim_frames.empty())
{
ParseUintRangeList(trim_frames, &settings->trace_settings_.trim_ranges, "capture frames");
if (!settings->trace_settings_.trim_ranges.empty())
{
settings->trace_settings_.trim_boundary = TrimBoundary::kFrames;
}
}

std::string trim_queue_submits = FindOption(options, kOptionKeyCaptureQueueSubmits);
if (!trim_queue_submits.empty())
{
if (settings->trace_settings_.trim_ranges.empty())
{
ParseUintRangeList(trim_queue_submits, &settings->trace_settings_.trim_ranges, "capture queue submits");
if (!settings->trace_settings_.trim_ranges.empty())
{
settings->trace_settings_.trim_boundary = TrimBoundary::kQueueSubmits;
}
}
else
{
GFXRECON_LOG_WARNING(
"Settings Loader: Ignoring trim queue submit ranges setting as trim frame ranges has been specified.");
}
}

std::string trim_key_option = FindOption(options, kOptionKeyCaptureTrigger);
std::string trim_key_frames_option = FindOption(options, kOptionKeyCaptureTriggerFrames);
if (!trim_key_option.empty())
Expand All @@ -489,10 +524,14 @@ void CaptureSettings::ProcessOptions(OptionsMap* options, CaptureSettings* setti
{
settings->trace_settings_.trim_key_frames = ParseTrimKeyFramesString(trim_key_frames_option);
}
if (!settings->trace_settings_.trim_key.empty())
{
settings->trace_settings_.trim_boundary = TrimBoundary::kFrames;
}
}
else
{
GFXRECON_LOG_WARNING("Settings Loader: Ignore trim key setting as trim ranges has been specified.");
GFXRECON_LOG_WARNING("Settings Loader: Ignoring trim key setting as trim ranges has been specified.");
}
}

Expand Down
8 changes: 8 additions & 0 deletions framework/encode/capture_settings.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,13 @@ class CaptureSettings
kDisabled = 2
};

enum class TrimBoundary
{
kUnknown,
kFrames,
kQueueSubmits,
};

const static char kDefaultCaptureFileName[];

struct ResourveValueAnnotationInfo
Expand All @@ -85,6 +92,7 @@ class CaptureSettings
std::string screenshot_dir;
std::vector<util::UintRange> screenshot_ranges;
util::ScreenshotFormat screenshot_format;
TrimBoundary trim_boundary{ TrimBoundary::kUnknown };
std::vector<util::UintRange> trim_ranges;
std::string trim_key;
uint32_t trim_key_frames{ 0 };
Expand Down
4 changes: 4 additions & 0 deletions framework/encode/d3d12_capture_manager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1650,12 +1650,16 @@ void D3D12CaptureManager::PreProcess_ID3D12CommandQueue_ExecuteCommandLists(ID3D
}
}
}

PreQueueSubmit();
}

void D3D12CaptureManager::PostProcess_ID3D12CommandQueue_ExecuteCommandLists(ID3D12CommandQueue_Wrapper* wrapper,
UINT num_lists,
ID3D12CommandList* const* lists)
{
PostQueueSubmit();

if ((GetCaptureMode() & kModeTrack) == kModeTrack)
{
state_tracker_->TrackExecuteCommandLists(wrapper, num_lists, lists);
Expand Down
Loading

0 comments on commit cbc1313

Please sign in to comment.