Commit f251995d by Jamie Madill Committed by Commit Bot

Capture/Replay: Write capture index file.

This file will be used with multi-frame captures to share common code. Common code is global state, resource maps, and a list of frame replay functions. This should make converting a CPP replay into a functional test quite a bit simpler. The replay files will now be something like: angle_capture_context1.cpp angle_capture_context1.h angle_capture_context1_frame000.cpp angle_capture_context1_frame001.cpp ... etc Also adds a template for adding a capture/replay sample. Instructions are located in samples/BUILD.gn and docs in doc/CaptureAndReplay.md. Bug: angleproject:3611 Change-Id: I437b338fd84689d670a7d9e3e219d9334de25fd8 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/1869543 Commit-Queue: Jamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarTobin Ehlis <tobine@google.com> Reviewed-by: 's avatarCody Northrop <cnorthrop@google.com>
parent 7af2676b
...@@ -18,14 +18,10 @@ To build ANGLE with capture and replay enabled update your GN args: ...@@ -18,14 +18,10 @@ To build ANGLE with capture and replay enabled update your GN args:
angle_with_capture_by_default = true angle_with_capture_by_default = true
``` ```
Once built ANGLE will capture a frame's OpenGL calls to a CPP replay stored in the current working Once built ANGLE will capture the OpenGL ES calls to a CPP replay. By default the replay will be
directory. The capture files will be named `angle_capture_context{id}_frame{n}.cpp`. Each OpenGL stored in the current working directory. The capture files will be named according to the pattern
context has a unique Context ID to identify its proper replay files. ANGLE will write out large `angle_capture_context{id}_frame{n}.cpp`. ANGLE will additionally write out data binary blobs for
binary blobs such as Texture or Buffer data to `angle_capture_context{id}_frame{n}.angledata`. Texture or Buffer contexts to `angle_capture_context{id}_frame{n}.angledata`.
To run a CPP replay you must stitch together the source files into a GN target. The samples
framework is well-suited for implementing a CPP replay example. Alternately you could adapt an ANGLE
end-to-end test. The `angledata` files must be accessible to the replay.
## Controlling Frame Capture ## Controlling Frame Capture
...@@ -39,3 +35,35 @@ Some simple environment variables control frame capture: ...@@ -39,3 +35,35 @@ Some simple environment variables control frame capture:
* `ANGLE_CAPTURE_FRAME_END=<n>`: * `ANGLE_CAPTURE_FRAME_END=<n>`:
By default ANGLE will capture the first ten frames. This variable can override the default. By default ANGLE will capture the first ten frames. This variable can override the default.
Example: `ANGLE_CAPTURE_FRAME_END=4` Example: `ANGLE_CAPTURE_FRAME_END=4`
A good way to test out the capture is to use environment variables in conjunction with the sample
template. For example:
```
$ ANGLE_CAPTURE_FRAME_END=4 ANGLE_CAPTURE_OUT_DIR=samples/capture_replay out/Debug/simple_texture_2d
```
## Running a CPP replay
To run a CPP replay you can use a template located in
[samples/capture_and_replay](../samples/capture_and_replay). Update
[samples/BUILD.gn](../samples/BUILD.gn) to enable the `capture_replay` sample to include your replay:
```
capture_replay("my_sample") {
sources = [
"capture_replay/angle_capture_context1_frame000.cpp",
"capture_replay/angle_capture_context1_frame001.cpp",
"capture_replay/angle_capture_context1_frame002.cpp",
"capture_replay/angle_capture_context1_frame003.cpp",
"capture_replay/angle_capture_context1_frame004.cpp",
]
}
```
Then build and run your replay sample:
```
$ autoninja -C out/Debug my_sample
$ ANGLE_CAPTURE_ENABLED=0 out/Debug/my_sample
```
...@@ -55,13 +55,21 @@ template("angle_sample") { ...@@ -55,13 +55,21 @@ template("angle_sample") {
} }
angle_executable(target_name) { angle_executable(target_name) {
forward_variables_from(invoker,
[
"sources",
"cflags",
])
deps = [ deps = [
":sample_util", ":sample_util",
] ]
if (defined(invoker.data)) { if (defined(invoker.data)) {
deps += [ ":${target_name}_data" ] deps += [ ":${target_name}_data" ]
} }
sources = invoker.sources
if (defined(invoker.suppressed_configs)) {
suppressed_configs += invoker.suppressed_configs
}
} }
} }
...@@ -209,6 +217,31 @@ angle_sample("gles1_draw_texture") { ...@@ -209,6 +217,31 @@ angle_sample("gles1_draw_texture") {
] ]
} }
template("capture_replay") {
angle_sample(target_name) {
sources = invoker.sources + [
"capture_replay/CaptureReplay.cpp",
"capture_replay/angle_capture_context1.cpp",
"capture_replay/angle_capture_context1.h",
]
suppressed_configs = [ "$angle_root:constructor_and_destructor_warnings" ]
}
}
# The capture_replay sample is set up to work with a single Context.
# To use the capture replay sample fist move your capture sources into
# the capture_replay folder. Uncomment and update this target:
# capture_replay("my_sample") {
# sources = [
# "capture_replay/angle_capture_context1_frame000.cpp",
# "capture_replay/angle_capture_context1_frame001.cpp",
# "capture_replay/angle_capture_context1_frame002.cpp",
# "capture_replay/angle_capture_context1_frame003.cpp",
# "capture_replay/angle_capture_context1_frame004.cpp",
# ]
# }
group("all") { group("all") {
testonly = true testonly = true
deps = [ deps = [
......
angle_capture_context*
\ No newline at end of file
//
// Copyright 2019 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// CaptureReplay: Template for replaying a frame capture with ANGLE.
#include "SampleApplication.h"
#include "angle_capture_context1.h"
class CaptureReplaySample : public SampleApplication
{
public:
CaptureReplaySample(int argc, char **argv)
: SampleApplication("CaptureReplaySample", argc, argv, 2, 0)
{}
bool initialize() override { return true; }
void destroy() override {}
void draw() override
{
ReplayContext1Frame(kReplayFrameStart + (mCurrentFrame % kReplayFrameEnd));
mCurrentFrame++;
}
private:
uint32_t mCurrentFrame = 0;
};
int main(int argc, char **argv)
{
CaptureReplaySample app(argc, argv);
return app.run();
}
...@@ -162,6 +162,9 @@ class DataCounters final : angle::NonCopyable ...@@ -162,6 +162,9 @@ class DataCounters final : angle::NonCopyable
std::map<Counter, int> mData; std::map<Counter, int> mData;
}; };
// Used by the CPP replay to filter out unnecessary code.
using HasResourceTypeMap = angle::PackedEnumMap<ResourceIDType, bool, angle::kParamTypeCount>;
class FrameCapture final : angle::NonCopyable class FrameCapture final : angle::NonCopyable
{ {
public: public:
...@@ -187,6 +190,10 @@ class FrameCapture final : angle::NonCopyable ...@@ -187,6 +190,10 @@ class FrameCapture final : angle::NonCopyable
const CallCapture &call, const CallCapture &call,
const ParamCapture &param); const ParamCapture &param);
static void ReplayCall(gl::Context *context,
ReplayContext *replayContext,
const CallCapture &call);
bool mEnabled; bool mEnabled;
std::string mOutDirectory; std::string mOutDirectory;
std::vector<CallCapture> mCalls; std::vector<CallCapture> mCalls;
...@@ -196,10 +203,7 @@ class FrameCapture final : angle::NonCopyable ...@@ -196,10 +203,7 @@ class FrameCapture final : angle::NonCopyable
uint32_t mFrameEnd; uint32_t mFrameEnd;
gl::AttribArray<size_t> mClientArraySizes; gl::AttribArray<size_t> mClientArraySizes;
size_t mReadBufferSize; size_t mReadBufferSize;
HasResourceTypeMap mHasResourceType;
static void ReplayCall(gl::Context *context,
ReplayContext *replayContext,
const CallCapture &call);
}; };
template <typename CaptureFuncT, typename... ArgsT> template <typename CaptureFuncT, typename... ArgsT>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment