diff --git a/gapis/api/gvr/gvr.go b/gapis/api/gvr/gvr.go index bd826377a2..ce96254afc 100644 --- a/gapis/api/gvr/gvr.go +++ b/gapis/api/gvr/gvr.go @@ -143,6 +143,11 @@ func (API) FlattenSubcommandIdx(idx api.SubCmdIdx, data *sync.Data, unused bool) return api.CmdID(0), false } +// IsTrivialTerminator returns true if the terminator is just stopping at the given index +func (API) IsTrivialTerminator(ctx context.Context, p *path.Capture, command api.SubCmdIdx) (bool, error) { + return true, nil +} + // RecoverMidExecutionCommand returns a virtual command, used to describe the // a subcommand that was created before the start of the trace // GVR has no subcommands of this type, so this should never be called diff --git a/gapis/api/sync/sync.go b/gapis/api/sync/sync.go index 1a61777995..3311490b9b 100644 --- a/gapis/api/sync/sync.go +++ b/gapis/api/sync/sync.go @@ -67,6 +67,9 @@ type SynchronizedAPI interface { // a subcommand that was created before the start of the trace. // If the api does not have mid-execution commands, NoMECSubcommandsError should be returned. RecoverMidExecutionCommand(ctx context.Context, c *path.Capture, data interface{}) (api.Cmd, error) + + // IsTrivialTerminator returns true if stopping at the given command is trivial. + IsTrivialTerminator(ctx context.Context, c *path.Capture, cmd api.SubCmdIdx) (bool, error) } type writer struct { @@ -112,13 +115,19 @@ func MutationCmdsFor(ctx context.Context, c *path.Capture, data *Data, cmds []ap terminators := make([]transform.Terminator, 0) transforms := transform.Transforms{} - + isTrivial := true for _, api := range rc.APIs { if sync, ok := api.(SynchronizedAPI); ok { term, err := sync.GetTerminator(ctx, c) if err != nil { return nil, err } + + t, err := sync.IsTrivialTerminator(ctx, c, fullCommand) + if err != nil { + return nil, err + } + isTrivial = t && isTrivial if term != nil { terminators = append(terminators, term) continue @@ -132,9 +141,12 @@ func MutationCmdsFor(ctx context.Context, c *path.Capture, data *Data, cmds []ap } transforms.Add(t) } - + if isTrivial { + return cmds[0:id], nil + } w := &writer{rc.NewState(ctx), nil} transforms.Transform(ctx, cmds, w) + return w.cmds, nil } diff --git a/gapis/api/vulkan/vulkan.go b/gapis/api/vulkan/vulkan.go index 4c78813257..dc8f950728 100644 --- a/gapis/api/vulkan/vulkan.go +++ b/gapis/api/vulkan/vulkan.go @@ -639,6 +639,30 @@ func (API) FlattenSubcommandIdx(idx api.SubCmdIdx, data *sync.Data, initialCall return api.CmdID(0), false } +// IsTrivialTerminator returns true if the terminator is just stopping at the given index +func (API) IsTrivialTerminator(ctx context.Context, p *path.Capture, after api.SubCmdIdx) (bool, error) { + s, err := resolve.SyncData(ctx, p) + if err != nil { + return false, err + } + + if len(after) == 1 { + a := api.CmdID(after[0]) + // If we are not running subcommands we can probably batch + for _, v := range s.SortedKeys() { + if v > a { + return true, nil + } + for _, k := range s.CommandRanges[v].SortedKeys() { + if k > a { + return false, nil + } + } + } + } + return false, nil +} + // RecoverMidExecutionCommand returns a virtual command, used to describe the // a subcommand that was created before the start of the trace func (API) RecoverMidExecutionCommand(ctx context.Context, c *path.Capture, dat interface{}) (api.Cmd, error) {