зеркало из https://github.com/AvaloniaUI/angle.git
Capture/Replay: Allow starting capture at an unknown frame
This CL adds a new way to set the start frame of a capture. It adds a new environment variable called ANGLE_CAPTURE_TRIGGER that, when set, will be used instead of frame start and end. By setting ANGLE_CAPTURE_TRIGGER to a non-zero value, ANGLE will capture that many frames when the value changes. For example, on Android, we can set it with: adb shell setprop debug.angle.capture.trigger 20 When we reach the target content, set the value back to zero: adb shell setprop debug.angle.capture.trigger 0 and ANGLE will start capturing 20 frames. Currently only hooked up for Android, but should be possible to support on other platforms. Test: Capture application frames using trigger Bug: angleproject:4949 Change-Id: I469ef5c48feb78c85b8cda2fefd5df59e495bbe2 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2347858 Commit-Queue: Cody Northrop <cnorthrop@google.com> Reviewed-by: Jamie Madill <jmadill@chromium.org> Reviewed-by: Manh Nguyen <nguyenmh@google.com>
This commit is contained in:
Родитель
48d951e22d
Коммит
a7cbb3f06f
|
@ -167,6 +167,25 @@ as the GLES driver for your application.
|
|||
$ out/Release/capture_replay_sample
|
||||
```
|
||||
|
||||
### Starting capture at an arbitrary frame
|
||||
In some scenarios, you don't know which frame you want to start on. You'll only know when target
|
||||
content is being rendered. For that we've added a trigger that can allow starting the capture at
|
||||
any time.
|
||||
|
||||
To use it, set the following environment variable, in addition to all the setup steps above. Set
|
||||
the trigger value equal to the number of frames you'd like to capture.
|
||||
```
|
||||
adb shell setprop debug.angle.capture.trigger 20
|
||||
```
|
||||
When this value is set, `ANGLE_CAPTURE_FRAME_START` and `ANGLE_CAPTURE_FRAME_END` will be ignored.
|
||||
|
||||
While your content is rendering, wait until you arrive at the scene you'd like to capture. Then
|
||||
set the value back to zero:
|
||||
```
|
||||
adb shell setprop debug.angle.capture.trigger 0
|
||||
```
|
||||
ANGLE will detect this change and start recording the requested number of frames.
|
||||
|
||||
## Testing
|
||||
|
||||
### Regression Testing Architecture
|
||||
|
|
|
@ -51,6 +51,7 @@ constexpr char kEnabledVarName[] = "ANGLE_CAPTURE_ENABLED";
|
|||
constexpr char kOutDirectoryVarName[] = "ANGLE_CAPTURE_OUT_DIR";
|
||||
constexpr char kFrameStartVarName[] = "ANGLE_CAPTURE_FRAME_START";
|
||||
constexpr char kFrameEndVarName[] = "ANGLE_CAPTURE_FRAME_END";
|
||||
constexpr char kCaptureTriggerVarName[] = "ANGLE_CAPTURE_TRIGGER";
|
||||
constexpr char kCaptureLabel[] = "ANGLE_CAPTURE_LABEL";
|
||||
constexpr char kCompression[] = "ANGLE_CAPTURE_COMPRESSION";
|
||||
constexpr char kSerializeStateEnabledVarName[] = "ANGLE_CAPTURE_SERIALIZE_STATE";
|
||||
|
@ -67,6 +68,7 @@ constexpr char kAndroidCaptureEnabled[] = "debug.angle.capture.enabled";
|
|||
constexpr char kAndroidOutDir[] = "debug.angle.capture.out_dir";
|
||||
constexpr char kAndroidFrameStart[] = "debug.angle.capture.frame_start";
|
||||
constexpr char kAndroidFrameEnd[] = "debug.angle.capture.frame_end";
|
||||
constexpr char kAndroidCaptureTrigger[] = "debug.angle.capture.trigger";
|
||||
constexpr char kAndroidCaptureLabel[] = "debug.angle.capture.label";
|
||||
constexpr char kAndroidCompression[] = "debug.angle.capture.compression";
|
||||
|
||||
|
@ -125,6 +127,13 @@ void PrimeAndroidEnvironmentVariables()
|
|||
setenv(kFrameEndVarName, frameEnd.c_str(), 1);
|
||||
}
|
||||
|
||||
std::string captureTrigger = AndroidGetEnvFromProp(kAndroidCaptureTrigger);
|
||||
if (!captureTrigger.empty())
|
||||
{
|
||||
INFO() << "Capture trigger read " << captureTrigger << " from " << kAndroidCaptureTrigger;
|
||||
setenv(kCaptureTriggerVarName, captureTrigger.c_str(), 1);
|
||||
}
|
||||
|
||||
std::string captureLabel = AndroidGetEnvFromProp(kAndroidCaptureLabel);
|
||||
if (!captureLabel.empty())
|
||||
{
|
||||
|
@ -182,6 +191,15 @@ std::string GetDefaultOutDirectory()
|
|||
#endif // defined(ANGLE_PLATFORM_ANDROID)
|
||||
}
|
||||
|
||||
std::string GetCaptureTrigger()
|
||||
{
|
||||
#if defined(ANGLE_PLATFORM_ANDROID)
|
||||
return AndroidGetEnvFromProp(kAndroidCaptureTrigger);
|
||||
#else
|
||||
return std::string();
|
||||
#endif // defined(ANGLE_PLATFORM_ANDROID)
|
||||
}
|
||||
|
||||
struct FmtCapturePrefix
|
||||
{
|
||||
FmtCapturePrefix(gl::ContextID contextIdIn, const std::string &captureLabelIn)
|
||||
|
@ -3356,7 +3374,8 @@ FrameCapture::FrameCapture()
|
|||
mFrameEnd(10),
|
||||
mClientArraySizes{},
|
||||
mReadBufferSize(0),
|
||||
mHasResourceType{}
|
||||
mHasResourceType{},
|
||||
mCaptureTrigger(0)
|
||||
{
|
||||
reset();
|
||||
|
||||
|
@ -3398,6 +3417,19 @@ FrameCapture::FrameCapture()
|
|||
mFrameEnd = atoi(endFromEnv.c_str());
|
||||
}
|
||||
|
||||
std::string captureTriggerFromEnv = angle::GetEnvironmentVar(kCaptureTriggerVarName);
|
||||
if (!captureTriggerFromEnv.empty())
|
||||
{
|
||||
mCaptureTrigger = atoi(captureTriggerFromEnv.c_str());
|
||||
|
||||
// If the trigger has been populated, ignore the other frame range variables by setting them
|
||||
// to unreasonable values. This isn't perfect, but it is effective.
|
||||
// TODO (anglebug.com/4949): Improve this, possibly by moving away from default start frame.
|
||||
mFrameStart = mFrameEnd = std::numeric_limits<uint32_t>::max();
|
||||
INFO() << "Capture trigger detected, overriding mFrameStart and mFrameEnd to "
|
||||
<< mFrameStart;
|
||||
}
|
||||
|
||||
std::string labelFromEnv = angle::GetEnvironmentVar(kCaptureLabel);
|
||||
if (!labelFromEnv.empty())
|
||||
{
|
||||
|
@ -4065,8 +4097,43 @@ void FrameCapture::captureMappedBufferSnapshot(const gl::Context *context, const
|
|||
(void)buffer->unmap(context, &dontCare);
|
||||
}
|
||||
|
||||
void FrameCapture::checkForCaptureTrigger()
|
||||
{
|
||||
// If the capture trigger has not been set, move on
|
||||
if (mCaptureTrigger == 0)
|
||||
return;
|
||||
|
||||
// Otherwise, poll the value for a change
|
||||
std::string captureTriggerStr = GetCaptureTrigger();
|
||||
if (captureTriggerStr.empty())
|
||||
return;
|
||||
|
||||
// If the value has changed, use the original value as the frame count
|
||||
// TODO (anglebug.com/4949): Improve capture at unknown frame time. It is good to
|
||||
// avoid polling if the feature is not enabled, but not entirely intuitive to set
|
||||
// a value to zero when you want to trigger it.
|
||||
uint32_t captureTrigger = atoi(captureTriggerStr.c_str());
|
||||
if (captureTrigger != mCaptureTrigger)
|
||||
{
|
||||
// Start mid-execution capture for the next frame
|
||||
mFrameStart = mFrameIndex + 1;
|
||||
|
||||
// Use the original trigger value as the frame count
|
||||
mFrameEnd = mFrameStart + (mCaptureTrigger - 1);
|
||||
|
||||
INFO() << "Capture triggered at frame " << mFrameStart << " for " << mCaptureTrigger
|
||||
<< " frames";
|
||||
|
||||
// Stop polling
|
||||
mCaptureTrigger = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void FrameCapture::onEndFrame(const gl::Context *context)
|
||||
{
|
||||
// On Android, we can trigger a capture during the run
|
||||
checkForCaptureTrigger();
|
||||
|
||||
// Note that we currently capture before the start frame to collect shader and program sources.
|
||||
if (!mFrameCalls.empty() && mFrameIndex >= mFrameStart)
|
||||
{
|
||||
|
|
|
@ -302,6 +302,7 @@ class FrameCapture final : angle::NonCopyable
|
|||
~FrameCapture();
|
||||
|
||||
void captureCall(const gl::Context *context, CallCapture &&call);
|
||||
void checkForCaptureTrigger();
|
||||
void onEndFrame(const gl::Context *context);
|
||||
void onDestroyContext(const gl::Context *context);
|
||||
void onMakeCurrent(const egl::Surface *drawSurface);
|
||||
|
@ -368,6 +369,11 @@ class FrameCapture final : angle::NonCopyable
|
|||
// Cache a shadow copy of texture level data
|
||||
TextureLevels mCachedTextureLevels;
|
||||
TextureLevelDataMap mCachedTextureLevelData;
|
||||
|
||||
// If you don't know which frame you want to start capturing at, use the capture trigger.
|
||||
// Initialize it to the number of frames you want to capture, and then clear the value to 0 when
|
||||
// you reach the content you want to capture. Currently only available on Android.
|
||||
uint32_t mCaptureTrigger;
|
||||
};
|
||||
|
||||
template <typename CaptureFuncT, typename... ArgsT>
|
||||
|
|
Загрузка…
Ссылка в новой задаче