-
Notifications
You must be signed in to change notification settings - Fork 327
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
Add export_replay for standalone replay with gapir. #2159
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -17,6 +17,7 @@ | |
#include "gapir/cc/context.h" | ||
#include "gapir/cc/crash_uploader.h" | ||
#include "gapir/cc/memory_manager.h" | ||
#include "gapir/cc/replay_archive.h" | ||
#include "gapir/cc/replay_connection.h" | ||
#include "gapir/cc/resource_disk_cache.h" | ||
#include "gapir/cc/resource_in_memory_cache.h" | ||
|
@@ -210,9 +211,12 @@ int main(int argc, const char* argv[]) { | |
const char* portArgStr = "0"; | ||
const char* authTokenFile = nullptr; | ||
int idleTimeoutSec = 0; | ||
const char* replayArchive = nullptr; | ||
|
||
for (int i = 1; i < argc; i++) { | ||
if (strcmp(argv[i], "--auth-token-file") == 0) { | ||
if (strcmp(argv[i], "--replay-archive") == 0) { | ||
replayArchive = argv[++i]; | ||
} else if (strcmp(argv[i], "--auth-token-file") == 0) { | ||
if (i + 1 >= argc) { | ||
GAPID_FATAL("Usage: --auth-token-file <token-string>"); | ||
} | ||
|
@@ -283,6 +287,24 @@ int main(int argc, const char* argv[]) { | |
core::Debugger::waitForAttach(); | ||
} | ||
|
||
if (replayArchive) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Now that we have a big mode-switch at the start of the replay, I would split this out into 2 methods. One that starts an "archived replay" and one that opens a connection. It is a bit weird to have a "start the program in an entirely different way" early-out in the middle of main(). |
||
core::CrashHandler crashHandler; | ||
GAPID_LOGGER_INIT(logLevel, "gapir", logPath); | ||
MemoryManager memoryManager(memorySizes); | ||
std::string payloadPath = std::string(replayArchive) + "/payload.bin"; | ||
gapir::ReplayArchive conn(payloadPath); | ||
std::unique_ptr<ResourceProvider> resourceProvider = | ||
ResourceDiskCache::create(nullptr, replayArchive); | ||
std::unique_ptr<Context> context = Context::create( | ||
&conn, crashHandler, resourceProvider.get(), &memoryManager); | ||
|
||
GAPID_INFO("Replay started"); | ||
bool ok = context->interpret(); | ||
GAPID_INFO("Replay %s", ok ? "finished successfully" : "failed"); | ||
|
||
return ok ? EXIT_SUCCESS : EXIT_FAILURE; | ||
} | ||
|
||
core::CrashHandler crashHandler; | ||
|
||
GAPID_LOGGER_INIT(logLevel, "gapir", logPath); | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
// Copyright (C) 2017 Google Inc. | ||
// | ||
// Licensed under the Apache License, Version 2.0 (the "License"); | ||
// you may not use this file except in compliance with the License. | ||
// You may obtain a copy of the License at | ||
// | ||
// http://www.apache.org/licenses/LICENSE-2.0 | ||
// | ||
// Unless required by applicable law or agreed to in writing, software | ||
// distributed under the License is distributed on an "AS IS" BASIS, | ||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
// See the License for the specific language governing permissions and | ||
// limitations under the License. | ||
|
||
package main | ||
|
||
import ( | ||
"context" | ||
"flag" | ||
"path/filepath" | ||
|
||
"github.com/google/gapid/core/app" | ||
"github.com/google/gapid/core/log" | ||
) | ||
|
||
type exportReplayVerb struct{ ExportReplayFlags } | ||
|
||
func init() { | ||
verb := &exportReplayVerb{} | ||
app.AddVerb(&app.Verb{ | ||
Name: "export_replay", | ||
ShortHelp: "Export replay vm instruction and assets.", | ||
Action: verb, | ||
}) | ||
} | ||
|
||
func (verb *exportReplayVerb) Run(ctx context.Context, flags flag.FlagSet) error { | ||
if flags.NArg() != 1 { | ||
app.Usage(ctx, "Exactly one gfx trace file expected, got %d", flags.NArg()) | ||
return nil | ||
} | ||
|
||
capture, err := filepath.Abs(flags.Arg(0)) | ||
if err != nil { | ||
log.Errf(ctx, err, "Could not find capture file: %v", flags.Arg(0)) | ||
} | ||
|
||
client, err := getGapis(ctx, verb.Gapis, verb.Gapir) | ||
if err != nil { | ||
return log.Err(ctx, err, "Failed to connect to the GAPIS server") | ||
} | ||
defer client.Close() | ||
|
||
capturePath, err := client.LoadCapture(ctx, capture) | ||
if err != nil { | ||
return log.Err(ctx, err, "Failed to load the capture file") | ||
} | ||
|
||
device, err := getDevice(ctx, client, capturePath, verb.Gapir) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
if err := client.ExportReplay(ctx, capturePath, device, verb.Out); err != nil { | ||
return log.Err(ctx, err, "Failed to export replay") | ||
} | ||
return nil | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
# Copyright (C) 2018 Google Inc. | ||
# | ||
# Licensed under the Apache License, Version 2.0 (the "License"); | ||
# you may not use this file except in compliance with the License. | ||
# You may obtain a copy of the License at | ||
# | ||
# http://www.apache.org/licenses/LICENSE-2.0 | ||
# | ||
# Unless required by applicable law or agreed to in writing, software | ||
# distributed under the License is distributed on an "AS IS" BASIS, | ||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
# See the License for the specific language governing permissions and | ||
# limitations under the License. | ||
|
||
load("@io_bazel_rules_go//go:def.bzl", "go_library") | ||
|
||
go_library( | ||
name = "go_default_library", | ||
srcs = ["archive.go"], | ||
cdeps = ["//core/cc"], | ||
cgo = True, | ||
clinkopts = [], # keep | ||
importpath = "github.com/google/gapid/core/archive", | ||
visibility = ["//visibility:public"], | ||
) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
// Copyright (C) 2018 Google Inc. | ||
// | ||
// Licensed under the Apache License, Version 2.0 (the "License"); | ||
// you may not use this file except in compliance with the License. | ||
// You may obtain a copy of the License at | ||
// | ||
// http://www.apache.org/licenses/LICENSE-2.0 | ||
// | ||
// Unless required by applicable law or agreed to in writing, software | ||
// distributed under the License is distributed on an "AS IS" BASIS, | ||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
// See the License for the specific language governing permissions and | ||
// limitations under the License. | ||
|
||
package archive | ||
|
||
/* | ||
#include <stdlib.h> | ||
#include "core/cc/archive.h" | ||
*/ | ||
import "C" | ||
import "unsafe" | ||
|
||
// Archive contains assets. | ||
type Archive = *C.archive | ||
|
||
// New creates an archive. | ||
func New(name string) Archive { | ||
cstr := C.CString(name) | ||
defer C.free(unsafe.Pointer(cstr)) | ||
return C.archive_create(cstr) | ||
} | ||
|
||
// Dispose flush and close the underlying archive. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. flushes and closes |
||
func (a Archive) Dispose() { | ||
C.archive_destroy(a) | ||
} | ||
|
||
// Write writes key-value pair to the archive. | ||
func (a Archive) Write(key string, value []byte) bool { | ||
cstr := C.CString(key) | ||
defer C.free(unsafe.Pointer(cstr)) | ||
csize := C.size_t(len(value)) | ||
return C.archive_write(a, cstr, unsafe.Pointer(&value[0]), csize) != 0 | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
/* | ||
* Copyright (C) 2018 Google Inc. | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
|
||
#include "replay_archive.h" | ||
|
||
#include <grpc++/grpc++.h> | ||
#include <fstream> | ||
#include <memory> | ||
|
||
#include "gapir/replay_service/service.grpc.pb.h" | ||
|
||
namespace gapir { | ||
|
||
std::unique_ptr<ReplayArchive::Payload> ReplayArchive::getPayload() { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ReplayConnection::Payload? Not sure which one is better. |
||
std::fstream input(mFileprefix, std::ios::in | std::ios::binary); | ||
std::unique_ptr<replay_service::Payload> payload(new replay_service::Payload); | ||
payload->ParseFromIstream(&input); | ||
return std::unique_ptr<Payload>(new Payload(std::move(payload))); | ||
} | ||
|
||
std::unique_ptr<ReplayArchive::Resources> ReplayArchive::getResources( | ||
std::unique_ptr<ResourceRequest> req) { | ||
return nullptr; | ||
} | ||
bool ReplayArchive::sendReplayFinished() { return true; } | ||
bool ReplayArchive::sendCrashDump(const std::string& filepath, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We should be writing out the crash dump here. (And logging it's location). |
||
const void* crash_data, uint32_t crash_size) { | ||
return true; | ||
} | ||
bool ReplayArchive::sendPostData(std::unique_ptr<Posts> posts) { return true; } | ||
bool ReplayArchive::sendNotification(uint64_t id, uint32_t severity, | ||
uint32_t api_index, uint64_t label, | ||
const std::string& msg, const void* data, | ||
uint32_t data_size) { | ||
return true; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We should log any notifications that we got here. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. GAPIR already write those to log. |
||
} | ||
} // namespace gapir |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
/* | ||
* Copyright (C) 2018 Google Inc. | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
|
||
#ifndef GAPIR_REPLAY_ARCHIVE_H | ||
#define GAPIR_REPLAY_ARCHIVE_H | ||
|
||
#include "core/cc/archive.h" | ||
#include "replay_connection.h" | ||
namespace gapir { | ||
|
||
// ReplayArchive implements ReplayConnection for exported replays. | ||
class ReplayArchive : public ReplayConnection { | ||
public: | ||
ReplayArchive(const std::string& fileprefix) | ||
: ReplayConnection(nullptr), mFileprefix(fileprefix) {} | ||
// Read payload from disk. | ||
virtual std::unique_ptr<Payload> getPayload() override; | ||
|
||
// We are reading from disk, so the following methods are not implemented. | ||
virtual std::unique_ptr<Resources> getResources( | ||
std::unique_ptr<ResourceRequest> req) override; | ||
virtual bool sendReplayFinished() override; | ||
virtual bool sendCrashDump(const std::string& filepath, | ||
const void* crash_data, | ||
uint32_t crash_size) override; | ||
virtual bool sendPostData(std::unique_ptr<Posts> posts) override; | ||
virtual bool sendNotification(uint64_t id, uint32_t severity, | ||
uint32_t api_index, uint64_t label, | ||
const std::string& msg, const void* data, | ||
uint32_t data_size) override; | ||
|
||
private: | ||
std::string mFileprefix; | ||
}; | ||
|
||
} // namespace gapir | ||
|
||
#endif // GAPIR_REPLAY_ARCHIVE_H |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -781,3 +781,8 @@ func (a API) QueryIssues( | |
} | ||
return res.([]replay.Issue), nil | ||
} | ||
|
||
// ExportReplayRequest returns request type for standalone replay. | ||
func (a API) ExportReplayRequest() replay.Request { | ||
return issuesRequest{} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We really should have a new type of request, instead of using |
||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if (i + 1 >= argc) {
GAPID_FATAL(....
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
And I think 'using archive' and 'connecting to gapis' are mutual exclusive, using both at the same time might be invalid (at least for this CL, and same to options like: port, idle-timeout-sec), so probably we should document this somewhere.