blob: 3d5569053cdb2651985ef103ee084cedccf28f3a [file] [log] [blame]
// Copyright (C) 2016 The Android Open Source Project
//
// 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 (
"flag"
"fmt"
"io"
"path/filepath"
"android.googlesource.com/platform/tools/gpu/framework/app"
"android.googlesource.com/platform/tools/gpu/framework/log"
"android.googlesource.com/platform/tools/gpu/gapid/atom"
"android.googlesource.com/platform/tools/gpu/gapid/service"
"android.googlesource.com/platform/tools/gpu/gapid/service/path"
)
type dumpFlags struct {
flag.FlagSet
gapisFlags
includeExtras bool
includeObservations bool
rawValues bool
}
func init() {
verb := &app.Verb{
Name: "dump",
ShortHelp: "Dump a textual representation of a .gfxtrace file",
}
dumpFlags := dumpFlags{}
dumpFlags.gapisFlags.bind(verb)
verb.Flags.BoolVar(&dumpFlags.includeExtras, "extras", false, "if true then extras are also dumped.")
verb.Flags.BoolVar(&dumpFlags.includeObservations, "observations", false, "if true then the bytes of every observation are also dumped.")
verb.Flags.BoolVar(&dumpFlags.rawValues, "raw-values", false, "if true then the value of constants, instead of their names, will be dumped.")
verb.Run = func(ctx log.Context, flags flag.FlagSet) error {
dumpFlags.FlagSet = flags
return doDump(ctx, dumpFlags)
}
app.AddVerb(verb)
}
func dumpMemory(ctx log.Context, client service.Service, stdout io.Writer, capture *path.Capture, o atom.Observation, i int) error {
memoryPath := capture.Atoms().Index(uint64(i)).MemoryAfter(0, o.Range.Base, o.Range.Size)
memory, err := client.Get(ctx, memoryPath)
if err != nil {
return fmt.Errorf("Failed to acquire the capture's memory: %v", err)
}
memoryInfo := memory.(*service.MemoryInfo)
fmt.Fprintf(stdout, "%v\n", memoryInfo.Data)
return nil
}
func doDump(ctx log.Context, flags dumpFlags) error {
if flags.NArg() != 1 {
app.Usage(ctx, "Exactly one gfx trace file expected, got %d", flags.NArg())
return nil
}
filepath, err := filepath.Abs(flags.Arg(0))
if err != nil {
return fmt.Errorf("Could not find capture file '%s': %v", flags.Arg(0), err)
}
client, err := getGapis(ctx, flags.gapisFlags, gapirFlags{})
if err != nil {
return fmt.Errorf("Failed to connect to the GAPIS server: %v", err)
}
defer client.Close(ctx)
schema, err := client.GetSchema(ctx)
if err != nil {
return fmt.Errorf("Failed to load the schema: %v", err)
}
capture, err := client.LoadCapture(ctx, filepath)
if err != nil {
return fmt.Errorf("Failed to load the capture file '%v': %v", filepath, err)
}
boxedAtoms, err := client.Get(ctx, capture.Atoms())
if err != nil {
return fmt.Errorf("Failed to acquire the capture's atoms: %v", err)
}
atoms := boxedAtoms.(*atom.List).Atoms
stdout := ctx.Raw("").Writer()
for i, a := range atoms {
if dyn, ok := a.(*atom.Dynamic); ok && !flags.rawValues {
fmt.Fprintf(stdout, "%.6d %v\n", i, dyn.StringWithConstants(schema.Constants))
} else {
fmt.Fprintf(stdout, "%.6d %v\n", i, a)
}
if flags.includeExtras || flags.includeObservations {
extras := a.Extras()
for _, e := range extras.All() {
fmt.Fprintf(stdout, " %s: [%+v]\n", e.Class().Schema().Identity, e)
}
if flags.includeObservations && extras.Observations() != nil {
for _, e := range extras.Observations().Reads {
if err := dumpMemory(ctx, client, stdout, capture, e, i); err != nil {
return err
}
}
for _, e := range extras.Observations().Writes {
if err := dumpMemory(ctx, client, stdout, capture, e, i); err != nil {
return err
}
}
}
}
}
return nil
}