diff --git a/USAGE_desktop_D3D12.md b/USAGE_desktop_D3D12.md index 18acba2e6d..e06a091696 100644 --- a/USAGE_desktop_D3D12.md +++ b/USAGE_desktop_D3D12.md @@ -108,7 +108,8 @@ Capture File Name | GFXRECON_CAPTURE_FILE | STRING | Path to use when creating t Capture Specific Frames | GFXRECON_CAPTURE_FRAMES | STRING | Specify one or more comma-separated frame ranges to capture. Each range will be written to its own file. A frame range can be specified as a single value, to specify a single frame to capture, or as two hyphenated values, to specify the first and last frame to capture. Frame ranges should be specified in ascending order and cannot overlap. Note that frame numbering is 1-based (i.e. the first frame is frame 1). Example: `200,301-305` will create two capture files, one containing a single frame and one containing five frames. Default is: Empty string (all frames are captured). Quit after capturing frame ranges | GFXRECON_QUIT_AFTER_CAPTURE_FRAMES | BOOL | Setting it to `true` will force the application to terminate once all frame ranges specified by `GFXRECON_CAPTURE_FRAMES` have been captured. Hotkey Capture Trigger | GFXRECON_CAPTURE_TRIGGER | STRING | Specify a hotkey (any one of F1-F12, TAB, CONTROL) that will be used to start/stop capture. Example: `F3` will set the capture trigger to F3 hotkey. One capture file will be generated for each pair of start/stop hotkey presses. Default is: Empty string (hotkey capture trigger is disabled). -Hotkey Capture Trigger | GFXRECON_CAPTURE_TRIGGER_FRAMES | STRING | Specify a limit on the number of frames to be captured via hotkey. Example: `1` will capture exactly one frame when the trigger key is pressed. Default is: Empty string (no limit) +Hotkey Capture Trigger Frames | GFXRECON_CAPTURE_TRIGGER_FRAMES | STRING | Specify a limit on the number of frames to be captured via hotkey. Example: `1` will capture exactly one frame when the trigger key is pressed. Default is: Empty string (no limit) +Capture Specific GPU Queue Submits | GFXRECON_CAPTURE_QUEUE_SUBMITS | STRING | Specify one or more comma-separated GPU queue submit call ranges to capture. Queue submit calls are `vkQueueSubmit` for Vulkan and `ID3D12CommandQueue::ExecuteCommandLists` for DX12. Queue submit ranges work as described above in `GFXRECON_CAPTURE_FRAMES` but on GPU queue submit calls instead of frames. Default is: Empty string (all queue submits are captured). Capture File Compression Type | GFXRECON_CAPTURE_COMPRESSION_TYPE | STRING | Compression format to use with the capture file. Valid values are: `LZ4`, `ZLIB`, `ZSTD`, and `NONE`. Default is: `LZ4` Capture File Timestamp | GFXRECON_CAPTURE_FILE_TIMESTAMP | BOOL | Add a timestamp to the capture file as described by [Timestamps](#timestamps). Default is: `true` Capture File Flush After Write | GFXRECON_CAPTURE_FILE_FLUSH | BOOL | Flush output stream after each packet is written to the capture file. Default is: `false` diff --git a/USAGE_desktop_Vulkan.md b/USAGE_desktop_Vulkan.md index 137353912b..252dfe89b0 100644 --- a/USAGE_desktop_Vulkan.md +++ b/USAGE_desktop_Vulkan.md @@ -165,7 +165,8 @@ Capture File Name | GFXRECON_CAPTURE_FILE | STRING | Path to use when creating t Capture Specific Frames | GFXRECON_CAPTURE_FRAMES | STRING | Specify one or more comma-separated frame ranges to capture. Each range will be written to its own file. A frame range can be specified as a single value, to specify a single frame to capture, or as two hyphenated values, to specify the first and last frame to capture. Frame ranges should be specified in ascending order and cannot overlap. Note that frame numbering is 1-based (i.e. the first frame is frame 1). Example: `200,301-305` will create two capture files, one containing a single frame and one containing five frames. Default is: Empty string (all frames are captured). Quit after capturing frame ranges | GFXRECON_QUIT_AFTER_CAPTURE_FRAMES | BOOL | Setting it to `true` will force the application to terminate once all frame ranges specified by `GFXRECON_CAPTURE_FRAMES` have been captured. Hotkey Capture Trigger | GFXRECON_CAPTURE_TRIGGER | STRING | Specify a hotkey (any one of F1-F12, TAB, CONTROL) that will be used to start/stop capture. Example: `F3` will set the capture trigger to F3 hotkey. One capture file will be generated for each pair of start/stop hotkey presses. Default is: Empty string (hotkey capture trigger is disabled). -Hotkey Capture Trigger | GFXRECON_CAPTURE_TRIGGER_FRAMES | STRING | Specify a limit on the number of frames to be captured via hotkey. Example: `1` will capture exactly one frame when the trigger key is pressed. Default is: Empty string (no limit) +Hotkey Capture Trigger Frames | GFXRECON_CAPTURE_TRIGGER_FRAMES | STRING | Specify a limit on the number of frames to be captured via hotkey. Example: `1` will capture exactly one frame when the trigger key is pressed. Default is: Empty string (no limit) +Capture Specific GPU Queue Submits | GFXRECON_CAPTURE_QUEUE_SUBMITS | STRING | Specify one or more comma-separated GPU queue submit call ranges to capture. Queue submit calls are `vkQueueSubmit` for Vulkan and `ID3D12CommandQueue::ExecuteCommandLists` for DX12. Queue submit ranges work as described above in `GFXRECON_CAPTURE_FRAMES` but on GPU queue submit calls instead of frames. Default is: Empty string (all queue submits are captured). Capture File Compression Type | GFXRECON_CAPTURE_COMPRESSION_TYPE | STRING | Compression format to use with the capture file. Valid values are: `LZ4`, `ZLIB`, `ZSTD`, and `NONE`. Default is: `LZ4` Capture File Timestamp | GFXRECON_CAPTURE_FILE_TIMESTAMP | BOOL | Add a timestamp to the capture file as described by [Timestamps](#timestamps). Default is: `true` Capture File Flush After Write | GFXRECON_CAPTURE_FILE_FLUSH | BOOL | Flush output stream after each packet is written to the capture file. Default is: `false` diff --git a/framework/encode/capture_manager.cpp b/framework/encode/capture_manager.cpp index 8dfd02d2fd..8a10459b8c 100644 --- a/framework/encode/capture_manager.cpp +++ b/framework/encode/capture_manager.cpp @@ -93,8 +93,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), @@ -328,16 +329,23 @@ 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_boundary_ = trace_settings.trim_boundary; quit_after_frame_ranges_ = trace_settings.quit_after_frame_ranges; - // 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. @@ -353,10 +361,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; @@ -377,7 +388,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; } } @@ -600,11 +614,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(); @@ -614,16 +628,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) @@ -640,7 +655,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. @@ -649,11 +664,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)); @@ -675,7 +690,7 @@ void CaptureManager::CheckStartCaptureForTrackMode() if (success) { - trim_key_first_frame_ = current_frame_; + trim_key_first_frame_ = current_boundary_count; ActivateTrimming(); } else @@ -736,19 +751,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_); } } @@ -766,6 +781,32 @@ 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); @@ -773,7 +814,19 @@ std::string CaptureManager::CreateTrimFilename(const std::string& base_filename, 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); diff --git a/framework/encode/capture_manager.h b/framework/encode/capture_manager.h index c4f47aee37..3c4c88071b 100644 --- a/framework/encode/capture_manager.h +++ b/framework/encode/capture_manager.h @@ -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(); @@ -329,12 +334,14 @@ class CaptureManager bool page_guard_signal_handler_watcher_; PageGuardMemoryMode page_guard_memory_mode_; bool trim_enabled_; + CaptureSettings::TrimBoundary trim_boundary_; std::vector 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_; diff --git a/framework/encode/capture_settings.cpp b/framework/encode/capture_settings.cpp index d706521cb1..d6b7adbf5c 100644 --- a/framework/encode/capture_settings.cpp +++ b/framework/encode/capture_settings.cpp @@ -92,6 +92,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" @@ -163,6 +165,7 @@ const char kQuitAfterFramesEnvVar[] = 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; @@ -224,6 +227,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; @@ -265,6 +269,7 @@ const std::string kOptionKeyQuitAfterCaptureFrames = 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); @@ -336,6 +341,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 != RuntimeTriggerState::kNotUsed) + { + settings->trace_settings_.trim_boundary = TrimBoundary::kFrames; + } } #endif } @@ -397,6 +406,7 @@ void CaptureSettings::LoadOptionsEnvVar(OptionsMap* options) LoadSingleOptionEnvVar(options, kQuitAfterFramesEnvVar, kOptionKeyQuitAfterCaptureFrames); LoadSingleOptionEnvVar(options, kCaptureTriggerEnvVar, kOptionKeyCaptureTrigger); LoadSingleOptionEnvVar(options, kCaptureTriggerFramesEnvVar, kOptionKeyCaptureTriggerFrames); + LoadSingleOptionEnvVar(options, kCaptureQueueSubmitsEnvVar, kOptionKeyCaptureQueueSubmits); // Page guard environment variables LoadSingleOptionEnvVar(options, kPageGuardCopyOnMapEnvVar, kOptionKeyPageGuardCopyOnMap); @@ -479,11 +489,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()) @@ -495,10 +530,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."); } } diff --git a/framework/encode/capture_settings.h b/framework/encode/capture_settings.h index 84f52afbbe..b26d8e05a4 100644 --- a/framework/encode/capture_settings.h +++ b/framework/encode/capture_settings.h @@ -64,6 +64,13 @@ class CaptureSettings kDisabled = 2 }; + enum class TrimBoundary + { + kUnknown, + kFrames, + kQueueSubmits, + }; + const static char kDefaultCaptureFileName[]; struct ResourveValueAnnotationInfo @@ -85,6 +92,7 @@ class CaptureSettings std::string screenshot_dir; std::vector screenshot_ranges; util::ScreenshotFormat screenshot_format; + TrimBoundary trim_boundary{ TrimBoundary::kUnknown }; std::vector trim_ranges; std::string trim_key; uint32_t trim_key_frames{ 0 }; diff --git a/framework/encode/d3d12_capture_manager.cpp b/framework/encode/d3d12_capture_manager.cpp index 8e14c5e40d..4823138c7a 100644 --- a/framework/encode/d3d12_capture_manager.cpp +++ b/framework/encode/d3d12_capture_manager.cpp @@ -1652,12 +1652,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); diff --git a/framework/encode/vulkan_capture_manager.cpp b/framework/encode/vulkan_capture_manager.cpp index df7c91cf62..3eebe76db5 100644 --- a/framework/encode/vulkan_capture_manager.cpp +++ b/framework/encode/vulkan_capture_manager.cpp @@ -2188,6 +2188,8 @@ void VulkanCaptureManager::PreProcess_vkQueueSubmit(VkQueue queue, GFXRECON_UNREFERENCED_PARAMETER(fence); QueueSubmitWriteFillMemoryCmd(); + + PreQueueSubmit(); } void VulkanCaptureManager::PreProcess_vkQueueSubmit2(VkQueue queue, @@ -2201,6 +2203,8 @@ void VulkanCaptureManager::PreProcess_vkQueueSubmit2(VkQueue queue, GFXRECON_UNREFERENCED_PARAMETER(fence); QueueSubmitWriteFillMemoryCmd(); + + PreQueueSubmit(); } void VulkanCaptureManager::QueueSubmitWriteFillMemoryCmd() diff --git a/framework/encode/vulkan_capture_manager.h b/framework/encode/vulkan_capture_manager.h index 27a9b81328..0d0a473f01 100644 --- a/framework/encode/vulkan_capture_manager.h +++ b/framework/encode/vulkan_capture_manager.h @@ -899,6 +899,8 @@ class VulkanCaptureManager : public CaptureManager void PostProcess_vkQueueSubmit(VkResult result, VkQueue, uint32_t submitCount, const VkSubmitInfo* pSubmits, VkFence) { + PostQueueSubmit(); + if (((GetCaptureMode() & kModeTrack) == kModeTrack) && (result == VK_SUCCESS)) { assert((state_tracker_ != nullptr) && ((submitCount == 0) || (pSubmits != nullptr))); @@ -931,6 +933,8 @@ class VulkanCaptureManager : public CaptureManager void PostProcess_vkQueueSubmit2( VkResult result, VkQueue queue, uint32_t submitCount, const VkSubmitInfo2* pSubmits, VkFence fence) { + PostQueueSubmit(); + if (((GetCaptureMode() & kModeTrack) == kModeTrack) && (result == VK_SUCCESS)) { assert((state_tracker_ != nullptr) && ((submitCount == 0) || (pSubmits != nullptr)));