diff --git a/USAGE_desktop_D3D12.md b/USAGE_desktop_D3D12.md index 3183f0f25..386059295 100644 --- a/USAGE_desktop_D3D12.md +++ b/USAGE_desktop_D3D12.md @@ -110,7 +110,7 @@ Quit after capturing frame ranges | GFXRECON_QUIT_AFTER_CAPTURE_FRAMES | BOOL | 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 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 Specific Drawcalls | GFXRECON_CAPTURE_DRAWCALLS | STRING | Specify one index or a range indices drawacalls(include dispatch) based on a ExecuteCommandList index and a CommandList index to capture. The index is 1-based. The args are one submit index, one command index, one or a range indices of draw calls, one or a range indices of bundle drawcalls(option), like "1,1,1" or "1,1,1-2" or "1,1,1-2,1". The forth arg is an option for bundle case. If the the 3rd arg is a bundle commandlist, but it doesn't set the 4th arg, it will set 1 as default. Default is: Empty string (all drawcalls are captured). +Capture Specific Drawcalls | GFXRECON_CAPTURE_DRAWCALLS | STRING | Specify one index or a range indices drawacalls(include dispatch) based on a ExecuteCommandList index and a CommandList index to capture. The index is 0-based. The args are one submit index, one command index, one or a range indices of draw calls, one or a range indices of bundle drawcalls(option), like "0,0,0" or "0,0,0-2" or "0,0,0-2,0". The forth arg is an option for bundle case. If the the 3rd arg is a bundle commandlist, but it doesn't set the 4th arg, it will set 0 as default. Default is: Empty string (all drawcalls 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 f2753508d..be0bdb43d 100644 --- a/framework/encode/capture_manager.cpp +++ b/framework/encode/capture_manager.cpp @@ -393,6 +393,11 @@ bool CommonCaptureManager::Initialize(format::ApiFamilyId api_ GFXRECON_ASSERT((trim_boundary_ == CaptureSettings::TrimBoundary::kFrames) || (trim_boundary_ == CaptureSettings::TrimBoundary::kQueueSubmits)); + if (trim_boundary_ == CaptureSettings::TrimBoundary::kQueueSubmits) + { + GFXRECON_LOG_WARNING("Trimming queue submits will be changed to 0-based."); + } + trim_ranges_ = trace_settings.trim_ranges; // Determine if trim starts at the first frame @@ -906,6 +911,8 @@ void CommonCaptureManager::EndFrame(format::ApiFamilyId api_family) void CommonCaptureManager::PreQueueSubmit(format::ApiFamilyId api_family) { + // ++ here means it's 1-based. When it changes to 0-based, it needs to move to the bottom of + // CommonCaptureManager::PostQueueSubmit and make sure trimming kQueueSubmits and kDrawcalls work correctly. ++queue_submit_count_; if (trim_enabled_ && (trim_boundary_ == CaptureSettings::TrimBoundary::kQueueSubmits)) diff --git a/framework/encode/capture_settings.cpp b/framework/encode/capture_settings.cpp index 14394e3d6..5c867acea 100644 --- a/framework/encode/capture_settings.cpp +++ b/framework/encode/capture_settings.cpp @@ -511,32 +511,25 @@ void CaptureSettings::ProcessOptions(OptionsMap* options, CaptureSettings* setti if (!trim_drawcalls.empty()) { std::vector trim_values; - ParseUintRangeList(trim_drawcalls, &trim_values, "capture drawcalls", false); + ParseUintRangeList(trim_drawcalls, &trim_values, "capture drawcalls", false, true); if (trim_values.size() == 3 || trim_values.size() == 4) { - if (trim_values[0].first != 0) + settings->trace_settings_.trim_drawcalls.submit_index = trim_values[0].first; + settings->trace_settings_.trim_drawcalls.command_index = trim_values[1].first; + settings->trace_settings_.trim_drawcalls.drawcall_indices.first = trim_values[2].first; + settings->trace_settings_.trim_drawcalls.drawcall_indices.last = trim_values[2].last; + settings->trace_settings_.trim_boundary = TrimBoundary::kDrawcalls; + + if (trim_values.size() == 4) + { + settings->trace_settings_.trim_drawcalls.bundle_drawcall_indices.first = trim_values[3].first; + settings->trace_settings_.trim_drawcalls.bundle_drawcall_indices.last = trim_values[3].last; + } + else { - settings->trace_settings_.trim_drawcalls.submit_index = trim_values[0].first; - if (trim_values[1].first != 0) - { - settings->trace_settings_.trim_drawcalls.command_index = trim_values[1].first; - if (trim_values[2].first != 0) - { - settings->trace_settings_.trim_drawcalls.drawcall_indices.first = trim_values[2].first; - settings->trace_settings_.trim_drawcalls.drawcall_indices.last = trim_values[2].last; - settings->trace_settings_.trim_boundary = TrimBoundary::kDrawcalls; - - // bundle_drawcall_indices is the 4th arg. The default it 1 if it doesn't set. - settings->trace_settings_.trim_drawcalls.bundle_drawcall_indices.first = 1; - settings->trace_settings_.trim_drawcalls.bundle_drawcall_indices.last = 1; - } - - if (trim_values.size() == 4 && trim_values[3].first != 0) - { - settings->trace_settings_.trim_drawcalls.bundle_drawcall_indices.first = trim_values[3].first; - settings->trace_settings_.trim_drawcalls.bundle_drawcall_indices.last = trim_values[3].last; - } - } + // bundle_drawcall_indices is the 4th arg. The default is 0 if it doesn't set. + settings->trace_settings_.trim_drawcalls.bundle_drawcall_indices.first = 0; + settings->trace_settings_.trim_drawcalls.bundle_drawcall_indices.last = 0; } } } @@ -876,14 +869,15 @@ util::Log::Severity CaptureSettings::ParseLogLevelString(const std::string& val void CaptureSettings::ParseUintRangeList(const std::string& value_string, std::vector* frames, const char* option_name, - bool check_overlap_range) + bool check_overlap_range, + bool allow_zero) { GFXRECON_ASSERT(frames != nullptr); if (!value_string.empty()) { std::vector frame_ranges = - util::GetUintRanges(value_string.c_str(), option_name, check_overlap_range); + util::GetUintRanges(value_string.c_str(), option_name, check_overlap_range, allow_zero); for (uint32_t i = 0; i < frame_ranges.size(); ++i) { diff --git a/framework/encode/capture_settings.h b/framework/encode/capture_settings.h index d26e8a2ab..4cd6911de 100644 --- a/framework/encode/capture_settings.h +++ b/framework/encode/capture_settings.h @@ -81,7 +81,7 @@ class CaptureSettings struct TrimDrawcalls { - // 1-based + // 0-based uint32_t submit_index{ 0 }; uint32_t command_index{ 0 }; util::UintRange drawcall_indices; @@ -198,7 +198,8 @@ class CaptureSettings static void ParseUintRangeList(const std::string& value_string, std::vector* frames, const char* option_name, - bool check_overlap_range = true); + bool check_overlap_range = true, + bool allow_zero = false); static std::string ParseTrimKeyString(const std::string& value_string); diff --git a/framework/encode/d3d12_capture_manager.cpp b/framework/encode/d3d12_capture_manager.cpp index 4564ceeaf..30079aaba 100644 --- a/framework/encode/d3d12_capture_manager.cpp +++ b/framework/encode/d3d12_capture_manager.cpp @@ -1730,8 +1730,8 @@ void D3D12CaptureManager::PreProcess_ID3D12CommandQueue_ExecuteCommandLists(ID3D if (IsTrimEnabled() && GetTrimBundary() == CaptureSettings::TrimBoundary::kDrawcalls) { - CaptureSettings::TrimDrawcalls trim_drawcalls = GetTrimDrawcalls(); - if (common_manager_->GetQueueSubmitCount() == (trim_drawcalls.submit_index - 1)) + auto trim_drawcalls = GetTrimDrawcalls(); + if (common_manager_->GetQueueSubmitCount() == trim_drawcalls.submit_index) { // before of lists and splitted std::vector cmdlists; @@ -1740,7 +1740,7 @@ void D3D12CaptureManager::PreProcess_ID3D12CommandQueue_ExecuteCommandLists(ID3D cmdlists.emplace_back(lists[i]); } - auto target_cmdlist = lists[trim_drawcalls.command_index-1]; + auto target_cmdlist = lists[trim_drawcalls.command_index]; ID3D12CommandList_Wrapper* target_wrapper = nullptr; target_cmdlist->QueryInterface(IID_IUnknown_Wrapper, reinterpret_cast(&target_wrapper)); GFXRECON_ASSERT(target_wrapper); @@ -1818,15 +1818,15 @@ void D3D12CaptureManager::OverrideID3D12CommandQueue_ExecuteCommandLists(ID3D12C bool is_complete = false; if (IsTrimEnabled() && GetTrimBundary() == CaptureSettings::TrimBoundary::kDrawcalls) { - CaptureSettings::TrimDrawcalls trim_drawcalls = GetTrimDrawcalls(); - if (common_manager_->GetQueueSubmitCount() == trim_drawcalls.submit_index) + auto trim_drawcalls = GetTrimDrawcalls(); + if ((common_manager_->GetQueueSubmitCount() - 1) == trim_drawcalls.submit_index) { common_manager_->ActivateTrimmingDrawcalls(format::ApiFamilyId::ApiFamily_D3D12); std::vector cmdlists; // target of splitted - auto target_cmdlist = lists[trim_drawcalls.command_index - 1]; + auto target_cmdlist = lists[trim_drawcalls.command_index]; ID3D12CommandList_Wrapper* target_wrapper = nullptr; target_cmdlist->QueryInterface(IID_IUnknown_Wrapper, reinterpret_cast(&target_wrapper)); GFXRECON_ASSERT(target_wrapper); @@ -3365,24 +3365,24 @@ D3D12CaptureManager::GetCommandListsForTrimDrawcalls(ID3D12CommandList_Wrapper* if (cmd_list_info->command_list_type == D3D12_COMMAND_LIST_TYPE_BUNDLE) { - if ((cmd_list_info->drawcall_count >= (trim_drawcalls.bundle_drawcall_indices.first - 1)) && - (cmd_list_info->drawcall_count < trim_drawcalls.bundle_drawcall_indices.last)) + if ((cmd_list_info->drawcall_count >= trim_drawcalls.bundle_drawcall_indices.first) && + (cmd_list_info->drawcall_count <= trim_drawcalls.bundle_drawcall_indices.last)) { split_type = graphics::dx12::Dx12DumpResourcePos::kDrawCall; } - else if (cmd_list_info->drawcall_count >= trim_drawcalls.bundle_drawcall_indices.last) + else if (cmd_list_info->drawcall_count > trim_drawcalls.bundle_drawcall_indices.last) { split_type = graphics::dx12::Dx12DumpResourcePos::kAfterDrawCall; } } else { - if ((cmd_list_info->drawcall_count >= (trim_drawcalls.drawcall_indices.first - 1)) && - (cmd_list_info->drawcall_count < trim_drawcalls.drawcall_indices.last)) + if ((cmd_list_info->drawcall_count >= trim_drawcalls.drawcall_indices.first) && + (cmd_list_info->drawcall_count <= trim_drawcalls.drawcall_indices.last)) { split_type = graphics::dx12::Dx12DumpResourcePos::kDrawCall; } - else if (cmd_list_info->drawcall_count >= trim_drawcalls.drawcall_indices.last) + else if (cmd_list_info->drawcall_count > trim_drawcalls.drawcall_indices.last) { split_type = graphics::dx12::Dx12DumpResourcePos::kAfterDrawCall; } diff --git a/framework/util/options.cpp b/framework/util/options.cpp index e706a848c..33ffee09d 100644 --- a/framework/util/options.cpp +++ b/framework/util/options.cpp @@ -34,7 +34,8 @@ GFXRECON_BEGIN_NAMESPACE(gfxrecon) GFXRECON_BEGIN_NAMESPACE(util) -std::vector GetUintRanges(const char* args, const char* option_name, bool check_overlap_range) +std::vector +GetUintRanges(const char* args, const char* option_name, bool check_overlap_range, bool allow_zero) { std::vector ranges; @@ -118,7 +119,7 @@ std::vector GetUintRanges(const char* args, const char* option_name, } // Check for invalid start range. - if (uint_range.first == 0) + if (!allow_zero && uint_range.first == 0) { GFXRECON_LOG_WARNING( "Ignoring invalid range \"%s\" for %s, with range start equal to zero", range.c_str(), option_name); diff --git a/framework/util/options.h b/framework/util/options.h index b38763ede..dda74e0d1 100644 --- a/framework/util/options.h +++ b/framework/util/options.h @@ -39,7 +39,8 @@ struct UintRange uint32_t last{ 0 }; }; -std::vector GetUintRanges(const char* args, const char* option_name, bool check_overlap_range = true); +std::vector +GetUintRanges(const char* args, const char* option_name, bool check_overlap_range = true, bool allow_zero = false); enum class ScreenshotFormat : uint32_t {