Skip to content

Commit

Permalink
Prioritize contexts based on draws / frames.
Browse files Browse the repository at this point in the history
  • Loading branch information
ben-clayton committed Sep 11, 2017
1 parent 3f7b9d2 commit 553c9d7
Show file tree
Hide file tree
Showing 9 changed files with 137 additions and 25 deletions.
23 changes: 18 additions & 5 deletions gapic/src/main/com/google/gapid/models/ApiContext.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
package com.google.gapid.models;

import static java.util.Arrays.stream;
import static java.util.Comparator.comparingInt;

import com.google.common.collect.Lists;
import com.google.common.util.concurrent.Futures;
Expand All @@ -38,7 +39,7 @@ public class ApiContext
extends CaptureDependentModel<ApiContext.FilteringContext[], ApiContext.Listener> {
private static final Logger LOG = Logger.getLogger(ApiContext.class.getName());

private FilteringContext selectedContext = FilteringContext.ALL;
private FilteringContext selectedContext = null;

public ApiContext(Shell shell, Client client, Capture capture) {
super(LOG, shell, client, Listener.class, capture);
Expand All @@ -48,7 +49,7 @@ public ApiContext(Shell shell, Client client, Capture capture) {
protected void reset(boolean maintainState) {
super.reset(maintainState);
if (!maintainState) {
selectedContext = FilteringContext.ALL;
selectedContext = null;
}
}

Expand Down Expand Up @@ -96,21 +97,29 @@ protected void fireLoadStartEvent() {
protected void fireLoadedEvent() {
if (count() == 1) {
selectedContext = getData()[0];
} else if (selectedContext != FilteringContext.ALL) {
} else if (selectedContext != null) {
selectedContext = stream(getData())
.filter(c -> c.equals(selectedContext))
.findFirst()
.orElse(FilteringContext.ALL);
.orElseGet(this::highestPriorityContext);
} else {
selectedContext = highestPriorityContext();
}
listeners.fire().onContextsLoaded();
}

private FilteringContext highestPriorityContext() {
return stream(getData())
.max(comparingInt(FilteringContext::getPriority))
.orElse(FilteringContext.ALL);
}

public int count() {
return isLoaded() ? getData().length : 0;
}

public FilteringContext getSelectedContext() {
return selectedContext;
return selectedContext != null ? selectedContext : highestPriorityContext();
}

public void selectContext(FilteringContext context) {
Expand Down Expand Up @@ -205,6 +214,10 @@ public Path.CommandTree.Builder commandTree(Path.CommandTree.Builder path) {
.setAllowIncompleteFrame(true);
}

public int getPriority() {
return context != null ? context.getPriority() : 0;
}

public Path.Events.Builder events(Path.Events.Builder path) {
path.getFilterBuilder().setContext(id);
return path;
Expand Down
1 change: 1 addition & 0 deletions gapis/api/gles/CMakeFiles.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ set(files
guess_semantics.go
helpers.go
image.go
importance.go
issue_whitelist.go
links.go
markers.go
Expand Down
43 changes: 43 additions & 0 deletions gapis/api/gles/importance.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
// 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 gles

import "github.com/google/gapid/gapis/resolve"

var _ = []resolve.Importance{
&GlDrawArrays{},
&GlDrawArraysIndirect{},
&GlDrawArraysInstanced{},
&GlDrawElements{},
&GlDrawElementsBaseVertex{},
&GlDrawElementsIndirect{},
&GlDrawElementsInstanced{},
&GlDrawElementsInstancedBaseVertex{},
&GlDrawRangeElements{},
&GlDrawRangeElementsBaseVertex{},
&EglSwapBuffers{},
}

func (*GlDrawArrays) Importance() int { return 1 }
func (*GlDrawArraysIndirect) Importance() int { return 1 }
func (*GlDrawArraysInstanced) Importance() int { return 1 }
func (*GlDrawElements) Importance() int { return 1 }
func (*GlDrawElementsBaseVertex) Importance() int { return 1 }
func (*GlDrawElementsIndirect) Importance() int { return 1 }
func (*GlDrawElementsInstanced) Importance() int { return 1 }
func (*GlDrawElementsInstancedBaseVertex) Importance() int { return 1 }
func (*GlDrawRangeElements) Importance() int { return 1 }
func (*GlDrawRangeElementsBaseVertex) Importance() int { return 1 }
func (*EglSwapBuffers) Importance() int { return 5 }
1 change: 1 addition & 0 deletions gapis/api/gvr/CMakeFiles.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ set(files
framebindings.go
gvr.api
gvr.go
importance.go
mutate.go
resolvables.proto
types.api
Expand Down
23 changes: 23 additions & 0 deletions gapis/api/gvr/importance.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// 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 gvr

import "github.com/google/gapid/gapis/resolve"

var _ = []resolve.Importance{
&Gvr_frame_submit{},
}

func (*Gvr_frame_submit) Importance() int { return 100 }
66 changes: 47 additions & 19 deletions gapis/resolve/contexts.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ package resolve

import (
"context"
"sort"

"github.com/google/gapid/core/data/id"
"github.com/google/gapid/gapis/api"
Expand Down Expand Up @@ -47,6 +48,12 @@ func Context(ctx context.Context, p *path.Context) (*InternalContext, error) {
return boxed.(*InternalContext), nil
}

// Importance is the interface implemeneted by commands that provide an
// "importance score". This value is used to prioritize contexts.
type Importance interface {
Importance() int
}

// Resolve implements the database.Resolver interface.
func (r *ContextListResolvable) Resolve(ctx context.Context) (interface{}, error) {
ctx = capture.Put(ctx, r.Capture)
Expand All @@ -56,8 +63,8 @@ func (r *ContextListResolvable) Resolve(ctx context.Context) (interface{}, error
return nil, err
}

seen := map[api.ContextID]int{}
contexts := []*path.Context{}
priorities := map[api.ContextID]int{}
contexts := []api.Context{}

s := c.NewState()
err = api.ForeachCmd(ctx, c.Commands, func(ctx context.Context, i api.CmdID, cmd api.Cmd) error {
Expand All @@ -67,28 +74,49 @@ func (r *ContextListResolvable) Resolve(ctx context.Context) (interface{}, error
if api == nil {
return nil
}
if context := api.Context(s, cmd.Thread()); context != nil {
ctxID := context.ID()
idx, ok := seen[ctxID]
if !ok {
idx = len(contexts)
seen[ctxID] = idx
id, err := database.Store(ctx, &InternalContext{
Id: string(ctxID[:]),
Api: &path.API{Id: path.NewID(id.ID(api.ID()))},
Name: context.Name(),
})
if err != nil {
return err
}
contexts = append(contexts, r.Capture.Context(path.NewID(id)))
}

context := api.Context(s, cmd.Thread())
if context == nil {
return nil
}

id := context.ID()
p, ok := priorities[id]
if !ok {
priorities[id] = p
contexts = append(contexts, context)
}
if i, ok := cmd.(Importance); ok {
p += i.Importance()
priorities[id] = p
}
return nil
})
if err != nil {
return nil, err
}

return &service.Contexts{List: contexts}, nil
sort.Slice(contexts, func(i, j int) bool {
return priorities[contexts[i].ID()] < priorities[contexts[j].ID()]
})

out := &service.Contexts{
List: make([]*path.Context, len(contexts)),
}

for i, c := range contexts {
api := c.API()
ctxID := c.ID()
id, err := database.Store(ctx, &InternalContext{
Id: string(ctxID[:]),
Api: &path.API{Id: path.NewID(id.ID(api.ID()))},
Name: c.Name(),
Priority: uint32(i),
})
if err != nil {
return nil, err
}
out.List[i] = r.Capture.Context(path.NewID(id))
}
return out, nil
}
1 change: 1 addition & 0 deletions gapis/resolve/resolvables.proto
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ message InternalContext {
string id = 1;
path.API api = 2;
string name = 3;
uint32 priority = 4;
}

message CommandTreeResolvable {
Expand Down
2 changes: 1 addition & 1 deletion gapis/resolve/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ func internalToService(v interface{}) (interface{}, error) {
case api.Cmd:
return api.CmdToService(v)
case *InternalContext:
return &service.Context{Name: v.Name, Api: v.Api}, nil
return &service.Context{Name: v.Name, Api: v.Api, Priority: v.Priority}, nil
default:
return v, nil
}
Expand Down
2 changes: 2 additions & 0 deletions gapis/service/service.proto
Original file line number Diff line number Diff line change
Expand Up @@ -619,6 +619,8 @@ message Context {
string name = 1;
// The API that this context belongs to.
path.API api = 2;
// The estimated importance for the context. 0 = lowest priority.
uint32 priority = 3;
}

// CommandTree represents a command tree hierarchy.
Expand Down

0 comments on commit 553c9d7

Please sign in to comment.