Skip to content
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

Implement draw calls per frame and add it to gapit/stats #2031

Merged
merged 2 commits into from
Jul 12, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 49 additions & 9 deletions cmd/gapit/stats.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,10 @@ import (
"flag"
"fmt"
"math"
"os"
"path/filepath"
"sort"
"text/tabwriter"

"github.com/google/gapid/core/app"
"github.com/google/gapid/core/log"
Expand Down Expand Up @@ -70,7 +72,6 @@ func (verb *infoVerb) getEventsInRange(ctx context.Context, client service.Servi
events, err := getEvents(ctx, client, &path.Events{
Capture: capture,
AllCommands: true,
DrawCalls: true,
FirstInFrame: true,
LastInFrame: true,
FramebufferObservations: true,
Expand Down Expand Up @@ -114,6 +115,34 @@ func (verb *infoVerb) getEventsInRange(ctx context.Context, client service.Servi
return events[begin:end], nil
}

func (verb *infoVerb) drawCallStats(ctx context.Context, client client.Client, c *path.Capture) (int, sint.HistogramStats, error) {
boxedVal, err := client.Get(ctx, (&path.Stats{
Capture: c,
DrawCall: true,
}).Path())
if err != nil {
return 0, sint.HistogramStats{}, err
}
data := boxedVal.(*service.Stats).DrawCalls

if verb.Frames.Start < len(data) {
data = data[verb.Frames.Start:]
} else {
data = []uint64{}
}
if verb.Frames.Count >= 0 && verb.Frames.Count < len(data) {
data = data[:verb.Frames.Count]
}

hist := make(sint.Histogram, len(data))
totalDraws := 0
for i, dat := range data {
totalDraws += int(dat)
hist[i] = int(dat)
}
return totalDraws, hist.Stats(), nil
}

func (verb *infoVerb) Run(ctx context.Context, flags flag.FlagSet) error {
client, capture, err := loadCapture(ctx, flags, verb.Gapis)
if err != nil {
Expand Down Expand Up @@ -141,14 +170,25 @@ func (verb *infoVerb) Run(ctx context.Context, flags flag.FlagSet) error {
}
}
callStats := cmdsPerFrame.Stats()
totalDraws, drawStats, err := verb.drawCallStats(ctx, client, capture)
if err != nil {
return err
}

w := tabwriter.NewWriter(os.Stdout, 4, 4, 0, ' ', 0)
fmt.Fprintf(w, "Commands: \t%v\n", counts[service.EventKind_AllCommands])
fmt.Fprintf(w, "Frames: \t%v\n", counts[service.EventKind_FirstInFrame])
fmt.Fprintf(w, "Draws: \t%v\n", totalDraws)
fmt.Fprintf(w, "FBO: \t%v\n", counts[service.EventKind_FramebufferObservation])

fmt.Fprintf(w, "Avg commands per frame: \t%.2f\n", callStats.Average)
fmt.Fprintf(w, "Stddev commands per frame: \t%.2f\n", callStats.Stddev)
fmt.Fprintf(w, "Median commands per frame: \t%v\n", callStats.Median)

fmt.Println("Commands: ", counts[service.EventKind_AllCommands])
fmt.Println("Frames: ", counts[service.EventKind_FirstInFrame])
fmt.Println("Draws: ", counts[service.EventKind_DrawCall])
fmt.Println("FBO: ", counts[service.EventKind_FramebufferObservation])
fmt.Printf("Avg commands per frame: %.2f\n", callStats.Average)
fmt.Printf("Stddev commands per frame: %.2f\n", callStats.Stddev)
fmt.Println("Median commands per frame: ", callStats.Median)
fmt.Fprintf(w, "Avg draw calls per frame: \t%.2f\n", drawStats.Average)
fmt.Fprintf(w, "Stddev draw calls per frame: \t%.2f\n", drawStats.Stddev)
fmt.Fprintf(w, "Median draw calls per frame: \t%v\n", drawStats.Median)
w.Flush()

return err
return nil
}
5 changes: 5 additions & 0 deletions gapis/api/cmd_flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ const (
PushUserMarker
PopUserMarker
UserMarker
ExecutedDraw
)

// IsDrawCall returns true if the command is a draw call.
Expand Down Expand Up @@ -56,3 +57,7 @@ func (f CmdFlags) IsPopUserMarker() bool { return (f & PopUserMarker) != 0 }
// marker.
// The command may implement the Labeled interface to expose the marker name.
func (f CmdFlags) IsUserMarker() bool { return (f & UserMarker) != 0 }

// IsExecutedDraw returns true if the command is a draw call that gets executed
// as a subcommand.
func (f CmdFlags) IsExecutedDraw() bool { return (f & ExecutedDraw) != 0 }
35 changes: 35 additions & 0 deletions gapis/api/sync/data.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,29 @@ type SubcommandReference struct {
IsCallerGroup bool
}

// SyncNodeIdx is the identifier for a node in the sync dependency graph.
type SyncNodeIdx uint64

// SyncNode is the interface implemented by types that can be used as vertices
// in the sync dependency graph.
type SyncNode interface {
isSyncNode()
}

// CmdNode is a node in the sync dependency graph that is a command.
type CmdNode struct {
Idx api.SubCmdIdx
}

// AbstractNode is a node in the sync dependency graph that doesn't correspond
// to any point in the trace and is just used as a marker.
type AbstractNode struct{}

var (
_ = SyncNode(CmdNode{})
_ = SyncNode(AbstractNode{})
)

// Data contains a map of synchronization pairs.
type Data struct {
// CommandRanges contains commands that will be blocked from completion,
Expand All @@ -65,6 +88,11 @@ type Data struct {
// indexed by the immediate parent of the subcommands in the group.
// e.g.: group: [73, 1, 4, 5~6] should be indexed by [73, 1, 4]
SubCommandMarkerGroups *subCommandMarkerGroupTrie
// SyncDependencies contains the commands that must complete
// (according to their fences or semaphores) before they can be executed.
SyncDependencies map[SyncNodeIdx][]SyncNodeIdx
SyncNodes []SyncNode
CmdSyncNodes map[api.CmdID]SyncNodeIdx
}

type subCommandMarkerGroupTrie struct {
Expand Down Expand Up @@ -95,6 +123,9 @@ func NewData() *Data {
SubcommandGroups: map[api.CmdID][]api.SubCmdIdx{},
Hidden: api.CmdIDSet{},
SubCommandMarkerGroups: &subCommandMarkerGroupTrie{},
SyncDependencies: map[SyncNodeIdx][]SyncNodeIdx{},
SyncNodes: []SyncNode{},
CmdSyncNodes: map[api.CmdID]SyncNodeIdx{},
}
}

Expand Down Expand Up @@ -132,3 +163,7 @@ func (e ExecutionRanges) SortedKeys() SynchronizationIndices {
sort.Sort(v)
return v
}

func (CmdNode) isSyncNode() {}

func (AbstractNode) isSyncNode() {}
4 changes: 2 additions & 2 deletions gapis/api/templates/api.go.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -1299,8 +1299,8 @@ import (
}

func (ϟc *{{$name}}) CmdFlags(ϟctx context.Context, ϟi ϟapi.CmdID, ϟg *ϟapi.GlobalState) ϟapi.CmdFlags {
{{$names := Strings "draw_call" "transform_feedback" "clear" "frame_start" "frame_end" "user_marker" "push_user_marker" "pop_user_marker"}}
{{$flags := Strings "DrawCall" "TransformFeedback" "Clear" "StartOfFrame" "EndOfFrame" "UserMarker" "PushUserMarker" "PopUserMarker"}}
{{$names := Strings "draw_call" "transform_feedback" "clear" "frame_start" "frame_end" "user_marker" "push_user_marker" "pop_user_marker" "executed_draw"}}
{{$flags := Strings "DrawCall" "TransformFeedback" "Clear" "StartOfFrame" "EndOfFrame" "UserMarker" "PushUserMarker" "PopUserMarker" "ExecutedDraw"}}

var out ϟapi.CmdFlags
{{range $i, $name := $names}}
Expand Down
6 changes: 6 additions & 0 deletions gapis/api/vulkan/api/draw_commands.api
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,7 @@ sub void dovkCmdDraw(ref!vkCmdDrawArgs draw) {

@threadSafety("app")
@indirect("VkCommandBuffer", "VkDevice")
@executed_draw
cmd void vkCmdDraw(
VkCommandBuffer commandBuffer,
u32 vertexCount,
Expand Down Expand Up @@ -198,6 +199,7 @@ sub void dovkCmdDrawIndexed(ref!vkCmdDrawIndexedArgs draw) {

@threadSafety("app")
@indirect("VkCommandBuffer", "VkDevice")
@executed_draw
cmd void vkCmdDrawIndexed(
VkCommandBuffer commandBuffer,
u32 indexCount,
Expand Down Expand Up @@ -243,6 +245,7 @@ sub void dovkCmdDrawIndirect(ref!vkCmdDrawIndirectArgs draw) {

@threadSafety("app")
@indirect("VkCommandBuffer", "VkDevice")
@executed_draw
cmd void vkCmdDrawIndirect(
VkCommandBuffer commandBuffer,
VkBuffer buffer,
Expand Down Expand Up @@ -285,6 +288,7 @@ sub void dovkCmdDrawIndexedIndirect(ref!vkCmdDrawIndexedIndirectArgs draw) {

@threadSafety("app")
@indirect("VkCommandBuffer", "VkDevice")
@executed_draw
cmd void vkCmdDrawIndexedIndirect(
VkCommandBuffer commandBuffer,
VkBuffer buffer,
Expand Down Expand Up @@ -314,6 +318,7 @@ sub void dovkCmdDispatch(ref!vkCmdDispatchArgs args) {

@threadSafety("app")
@indirect("VkCommandBuffer", "VkDevice")
@executed_draw
cmd void vkCmdDispatch(
VkCommandBuffer commandBuffer,
u32 groupCountX,
Expand Down Expand Up @@ -344,6 +349,7 @@ sub void dovkCmdDispatchIndirect(ref!vkCmdDispatchIndirectArgs dispatch) {

@threadSafety("app")
@indirect("VkCommandBuffer", "VkDevice")
@executed_draw
cmd void vkCmdDispatchIndirect(
VkCommandBuffer commandBuffer,
VkBuffer buffer,
Expand Down
Loading