Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support multiple simultaneous API capture managers #1536

Conversation

jzulauf-lunarg
Copy link
Contributor

Split common and api specific options from isA to refsA relationship.

For single API sessions should be exactly equivalent.

This is a first piece of multiple API support needed for pending feature development.

Issues to be resolved:
Settings Arbitration: different API invocations of the layer may have different settings. Determining where are complete set of options are (without having to repeat them in every JSON) is one challenge. Resolving which setting "wins" (first, last, some priority heuristic). Settings side effects (like whether an StateTracker is create) need to be address if later invocations can change settings.

A number of interfaces became "public" to support this. The other choice is friendship between the various CaptureManagers, thoughts?

Also, concerns about performance or maintainability.

@ci-tester-lunarg
Copy link

CI gfxreconstruct build queued with queue ID 179237.

@CLAassistant
Copy link

CLAassistant commented May 3, 2024

CLA assistant check
All committers have signed the CLA.

@ci-tester-lunarg
Copy link

CI gfxreconstruct build # 4103 running.

@ci-tester-lunarg
Copy link

CI gfxreconstruct build # 4103 failed.

Copy link
Contributor Author

@jzulauf-lunarg jzulauf-lunarg left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added some comment for reviewers.

@@ -51,12 +51,11 @@ std::mutex CaptureManager::ThreadData::count
format::ThreadId CaptureManager::ThreadData::thread_count_ = 0;
std::unordered_map<uint64_t, format::ThreadId> CaptureManager::ThreadData::id_map_;

uint32_t CaptureManager::instance_count_ = 0;
CaptureManager* CaptureManager::singleton_;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note the change of terminology from "instance" to "singleton" throughout the PR. The singleton pattern implemented maps many API instances to the same CaptureManager singletons, thus calling the "singletons" "instances" seems quite confusing, given that a CreateInstance call may correlate to 0 or 1 CaptureManager creations, and DestroyInstance may correlate to 0 or 1 CaptureManager destructions.

@@ -89,8 +88,8 @@ format::ThreadId CaptureManager::ThreadData::GetThreadId()
return id;
}

CaptureManager::CaptureManager(format::ApiFamilyId api_family) :
api_family_(api_family), force_file_flush_(false), timestamp_filename_(true),
CaptureManager::CaptureManager() :
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The CaptureManager changes from being a base class to a referenced common class. All API specific capture managers access the common functionality through a referenced instance of the common class.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add this comment to the source itself.

// Initialize logging to report only errors (to stderr).
util::Log::Settings stderr_only_log_settings;
stderr_only_log_settings.min_severity = util::Log::kErrorSeverity;
stderr_only_log_settings.output_errors_to_stderr = true;
util::Log::Init(stderr_only_log_settings);

// WIP WIP -- FIRST WINS for settings
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since the current implementation doesn't support multiple disparate API's being captured, the "first wins" settings limitation doesn't impact current functionality, but needs to be resolved for actual multi API support (which is need for specific future use cases).

WIP comment is to attract reviewers attention, to be changed to NOTE or TODO prior to commit.

GFXRECON_ASSERT(inserted.second);
manager_it = inserted.first;

// WIP NOTE moved here from CaptureTracker::Initialize... DRY'r than putting it into the API specific
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Folks with a better understand of why StateTracker objects are lazily created please comment. Would it be reasonable to always create an empty state tracker, even if unused, s.t. eventual interactions between multiple capture managers settings don't lead to some inconsistent state?

GFXRECON_LOG_DEBUG("CaptureManager::CreateInstance(): Current instance count is %u", instance_count_);

return success;
}

void CaptureManager::DestroyInstance(std::function<const CaptureManager*()> GetInstanceFunc)
void CaptureManager::DestroyInstance(ApiCaptureManagerBase* api_capture_manager)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The destruction function is now captured at CreateInstance time. The "delete on last" logic is implemented here in the common class.

@@ -1093,7 +1168,7 @@ void CaptureManager::WriteFillMemoryCmd(format::HandleId memory_id, uint64_t off

void CaptureManager::WriteCreateHeapAllocationCmd(uint64_t allocation_id, uint64_t allocation_size)
{
if ((GetCaptureMode() & kModeWrite) == kModeWrite)
if (IsCaptureModeWrite())
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Class segregation moved the definition such that it would need qualification, and since the expression needed rewrite, seemed DRY'r to encapsulate.

void CaptureManager::WriteCaptureOptions(std::string& operation_annotation)
{
CaptureSettings::TraceSettings default_settings = GetDefaultTraceSettings();
CaptureSettings::TraceSettings default_settings = default_settings_.GetTraceSettings();
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The common capture manager sets this up, getting information from the capture manager associated with the first CreateInstance... seemed simplest to cache that data away, rather than track who's on first.

@@ -374,6 +388,178 @@ class CaptureManager
} rv_annotation_info_;
};

class ApiCaptureManagerBase
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My biggest concerns here are maintainability and performance (with the additional indirection). Not sure of a different approach that would require a lookup of CaptureManager::singleton_ everywhere one of these methods is invoked.

Copy link
Contributor

@davidd-lunarg davidd-lunarg May 9, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Another possible idea for breaking apart these classes: Have the common capture manager and each API capture manager be singletons and require the calling code (e.g., in the API-specific capture manager classes, or in the generated encoder files) to know which class to call into. Then the API manager classes don't need to pass-through all the common class methods and might help promote a division of responsibilities between the common and API-specific capture managers.

The API capture managers could still store a pointer to the common capture manager for cases when they need to call into it.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The goal of the ApiCaptureManagerBase passthrough calls was to minimize the code change impact of call into the common CaptureManager. Without this, every common call would need to be changed to be prefixed by common_manager_-> which seemed needlessly noisy (diff-wise) and verbose.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Another thought on this: forcing the users of capture managers to be explicit about calling into the API capture manager or the common capture manager may help code clarity. For example, the calls to AcquireSharedApiCallLock are currently made on the API-specific capture manager classes D3D12CaptureManager or VulkanCaptureManager. This could make it not obvious that D3D12CaptureManager::AcquireSharedApiCallLock acquires a lock across all capture managers. Making the choice of capture manager explicit could help solidify the concept of global vs API-specific capture functions and promote correct usage.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems like this makes things more complicated. Especially because we're still sharing the file write locks. So now we'd be blocking on API calls and file write locks while the file write itself would be the mitigating restriction. So just having the file lock would be sufficient.

if (instance_->IsAnnotated() == true && instance_->resource_value_annotator_ == nullptr)
{
instance_->resource_value_annotator_ = std::make_unique<Dx12ResourceValueAnnotator>();
bool ret = CaptureManager::CreateInstance<D3D12CaptureManager>();
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The templated overload associates the calling classes constructor/destructor functions automagically.

@jzulauf-lunarg
Copy link
Contributor Author

@bradgrantham @davidd-lunarg -- I've added some explanatory comments. Please review so I can revise and complete to unblock the multi-api "work on a branch" there stuff that needs to be resolved after this to do multi-API correctly, but this will all forward progress, and should be functionally equivalent for the currently supported operating modes. (i.e. single API at a time)

@jzulauf-lunarg jzulauf-lunarg force-pushed the zulauf_breakup_capture_manager_singletons branch from f94320a to 2c5123c Compare May 6, 2024 19:53
@ci-tester-lunarg
Copy link

CI gfxreconstruct build queued with queue ID 180502.

@ci-tester-lunarg
Copy link

CI gfxreconstruct build # 4106 running.

@ci-tester-lunarg
Copy link

CI gfxreconstruct build # 4106 failed.

@jzulauf-lunarg jzulauf-lunarg force-pushed the zulauf_breakup_capture_manager_singletons branch from 2c5123c to 7ecaee7 Compare May 6, 2024 20:39
@ci-tester-lunarg
Copy link

CI gfxreconstruct build queued with queue ID 180524.

@ci-tester-lunarg
Copy link

CI gfxreconstruct build # 4107 running.

@ci-tester-lunarg
Copy link

CI gfxreconstruct build # 4107 failed.

@ci-tester-lunarg
Copy link

CI gfxreconstruct build queued with queue ID 180726.

@ci-tester-lunarg
Copy link

CI gfxreconstruct build # 4114 running.

@ci-tester-lunarg
Copy link

CI gfxreconstruct build # 4114 failed.

@jzulauf-lunarg jzulauf-lunarg force-pushed the zulauf_breakup_capture_manager_singletons branch from 7ecaee7 to 48cb40c Compare May 7, 2024 14:52
@ci-tester-lunarg
Copy link

CI gfxreconstruct build queued with queue ID 181045.

@ci-tester-lunarg
Copy link

CI gfxreconstruct build # 4115 running.

@ci-tester-lunarg
Copy link

CI gfxreconstruct build # 4115 failed.

@jzulauf-lunarg jzulauf-lunarg force-pushed the zulauf_breakup_capture_manager_singletons branch from 48cb40c to 04c935d Compare May 7, 2024 16:54
@ci-tester-lunarg
Copy link

CI gfxreconstruct build queued with queue ID 181105.

@ci-tester-lunarg
Copy link

CI gfxreconstruct build # 4149 failed.

@jzulauf-lunarg jzulauf-lunarg force-pushed the zulauf_breakup_capture_manager_singletons branch from 24bc60b to b52fbf7 Compare May 14, 2024 17:14
@ci-tester-lunarg
Copy link

CI gfxreconstruct build queued with queue ID 185214.

@jzulauf-lunarg jzulauf-lunarg marked this pull request as ready for review May 14, 2024 17:16
@jzulauf-lunarg jzulauf-lunarg force-pushed the zulauf_breakup_capture_manager_singletons branch from b52fbf7 to a385ea6 Compare May 14, 2024 17:45
@ci-tester-lunarg
Copy link

CI gfxreconstruct build queued with queue ID 185233.

@ci-tester-lunarg
Copy link

CI gfxreconstruct build # 4154 running.

@ci-tester-lunarg
Copy link

CI gfxreconstruct build # 4154 passed.

@jzulauf-lunarg
Copy link
Contributor Author

@davidd-lunarg @bradgrantham -- ready for review

using ApiCaptureManagerMap = std::unordered_map<ApiCaptureManager*, ApiInstanceRecord>;
ApiCaptureManagerMap api_capture_managers_;

CaptureSettings default_settings_;
Copy link
Contributor

@MarkY-LunarG MarkY-LunarG May 14, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You should clarify the difference here between default_settings_ and capture_settings_ in a comment.

@jzulauf-lunarg jzulauf-lunarg force-pushed the zulauf_breakup_capture_manager_singletons branch from a385ea6 to 0d0cc69 Compare May 14, 2024 21:04
@ci-tester-lunarg
Copy link

CI gfxreconstruct build queued with queue ID 185371.

@ci-tester-lunarg
Copy link

CI gfxreconstruct build # 185371 cancelled.

@jzulauf-lunarg jzulauf-lunarg force-pushed the zulauf_breakup_capture_manager_singletons branch from 0d0cc69 to f1369cb Compare May 14, 2024 22:43
@ci-tester-lunarg
Copy link

CI gfxreconstruct build queued with queue ID 185440.

@ci-tester-lunarg
Copy link

CI gfxreconstruct build # 4159 running.

@ci-tester-lunarg
Copy link

CI gfxreconstruct build # 4159 passed.

@@ -54,7 +54,7 @@ enum ApiFamilyId : uint16_t
ApiFamily_Vulkan = 1,
ApiFamily_Dxgi = 2,
ApiFamily_D3D12 = 3,
ApiFamily_AGS = 4,
ApiFamily_AGS = 4
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: this file doesn't need to be modified.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed, okay to leave trailing comma (unless clang-format complained?)

Copy link
Contributor

@bradgrantham-lunarg bradgrantham-lunarg left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Request to wrap loop in braces, echoed small nit on comma, otherwise looks great

{
capture_mode_ |= kModeWrite;

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

WriteTrackedState(file_stream_.get(), thread_data->thread_id_);
for (auto& manager : api_capture_managers_)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please wrap block in braces. Thank you!

@@ -54,7 +54,7 @@ enum ApiFamilyId : uint16_t
ApiFamily_Vulkan = 1,
ApiFamily_Dxgi = 2,
ApiFamily_D3D12 = 3,
ApiFamily_AGS = 4,
ApiFamily_AGS = 4
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed, okay to leave trailing comma (unless clang-format complained?)

@jzulauf-lunarg jzulauf-lunarg force-pushed the zulauf_breakup_capture_manager_singletons branch from f1369cb to 4e6ee08 Compare May 15, 2024 16:05
@ci-tester-lunarg
Copy link

CI gfxreconstruct build queued with queue ID 185949.

Split common and api specific options from isA to refsA relationship.
Rename CaptureManager to CommonCaptureManager
API specific capture managers inherit from ApiCaptureManager base,
class.

For single API sessions should be exactly equivalent.
@jzulauf-lunarg jzulauf-lunarg force-pushed the zulauf_breakup_capture_manager_singletons branch from 4e6ee08 to 8b1bae3 Compare May 15, 2024 16:07
@ci-tester-lunarg
Copy link

CI gfxreconstruct build queued with queue ID 185950.

@ci-tester-lunarg
Copy link

CI gfxreconstruct build # 4167 running.

@ci-tester-lunarg
Copy link

CI gfxreconstruct build # 4167 passed.

@jzulauf-lunarg jzulauf-lunarg merged commit 3d93647 into LunarG:dev May 15, 2024
8 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants