From a59acde8a40f833efb576ba4a9cf2bafe676a6d3 Mon Sep 17 00:00:00 2001 From: Elvis Rusnel Capia Quispe Date: Wed, 16 Jan 2019 22:34:53 -0500 Subject: [PATCH] Graph Visualization: Added the General Chunk algorithm, multiple stacks to address debug markers, colors for nodes and unit testing. General Chunk Algorithm: This algorithm creates super-nodes to avoid display more than a fix number of nodes in every level. For every level, the nodes are grouped in super-nodes based on command names, then if the numbers of nodes exceed the maximum limit, chunks are created, and if in the new chunks the numbers of nodes exceed the maximum limit, then new chunks are created and so on. Results: Applying the General Chunk Algorithm is possible to visualize graphs containing millions of nodes and edges. The time is reduced from ~20 seconds to ~2 seconds to expand super-nodes in Tensorboard. Note1: All "op" attribute for nodes in pbtxt format must be different, since the find_similar_subgraphs algorithm from Tensorboard computes the similarity between nodes with same "op". Note2: Adding colors to the nodes increase the time for expand super-nodes. --- gapis/api/BUILD.bazel | 1 + gapis/api/graph_visualization.go | 18 + gapis/api/graph_visualization_test.go | 88 +++ gapis/api/vulkan/BUILD.bazel | 1 + gapis/api/vulkan/graph_visualization.go | 143 +++-- gapis/api/vulkan/graph_visualization_test.go | 582 ++++++++++++++++++ .../graph_visualization/graph_algorithms.go | 142 +++++ .../graph_algorithms_test.go | 131 ++++ .../graph_visualization/graph_output.go | 5 +- .../graph_visualization/graph_structure.go | 1 + .../graph_visualization.go | 10 +- 11 files changed, 1065 insertions(+), 57 deletions(-) create mode 100644 gapis/api/graph_visualization_test.go create mode 100644 gapis/api/vulkan/graph_visualization_test.go diff --git a/gapis/api/BUILD.bazel b/gapis/api/BUILD.bazel index bfbd77983b..dd855afa78 100644 --- a/gapis/api/BUILD.bazel +++ b/gapis/api/BUILD.bazel @@ -93,6 +93,7 @@ go_test( srcs = [ "cmd_id_group_test.go", "cmd_service_test.go", + "graph_visualization_test.go", "subcmd_idx_test.go", "subcmd_idx_trie_test.go", ], diff --git a/gapis/api/graph_visualization.go b/gapis/api/graph_visualization.go index ec1c466c32..cce8771a1a 100644 --- a/gapis/api/graph_visualization.go +++ b/gapis/api/graph_visualization.go @@ -86,6 +86,24 @@ func (label *Label) GetCommandId() int { return 0 } +// GetTopLevelName returns the name of the first level +// corresponding to the top level in hierarchy. +func (label *Label) GetTopLevelName() string { + if len(label.LevelsName) > 0 { + return label.LevelsName[0] + } + return "" +} + +// GetTopLevelID returns the ID of the first level +// corresponding to the top level in hierarchy. +func (label *Label) GetTopLevelID() int { + if len(label.LevelsID) > 0 { + return label.LevelsID[0] + } + return 0 +} + // GetLabelAsAString returns the Label as a string concatenating // names and ID for each level delimited by '/'. func (label *Label) GetLabelAsAString() string { diff --git a/gapis/api/graph_visualization_test.go b/gapis/api/graph_visualization_test.go new file mode 100644 index 0000000000..69835825ba --- /dev/null +++ b/gapis/api/graph_visualization_test.go @@ -0,0 +1,88 @@ +// 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 api + +import ( + "reflect" + "testing" +) + +func TestLabel(t *testing.T) { + + label := &Label{} + label.PushBack("name1", 1) + label.PushBack("name2", 2) + label.PushBack("name3", 3) + label.PushBack("name4", 4) + label.PushFront("name5", 5) + label.PushFront("name6", 6) + + obtainedLabel := label + + wantedLabel := &Label{ + LevelsName: []string{"name6", "name5", "name1", "name2", "name3", "name4"}, + LevelsID: []int{6, 5, 1, 2, 3, 4}, + } + + if !reflect.DeepEqual(wantedLabel, obtainedLabel) { + t.Errorf("The Label is different\n") + t.Errorf("Wanted %v, obtained %v\n", wantedLabel, obtainedLabel) + } + + label.Insert(0, "name10", 10) + label.Insert(5, "name11", 11) + label.Insert(5, "name12", 12) + + wantedLabel = &Label{ + LevelsName: []string{"name10", "name6", "name5", "name1", "name2", "name12", "name11", "name3", "name4"}, + LevelsID: []int{10, 6, 5, 1, 2, 12, 11, 3, 4}, + } + + if !reflect.DeepEqual(wantedLabel, obtainedLabel) { + t.Errorf("The Label is different\n") + t.Errorf("Wanted %v, obtained %v\n", wantedLabel, obtainedLabel) + } + + obtainedLabel.PushBackLabel(obtainedLabel) + wantedLabel = &Label{ + LevelsName: []string{"name10", "name6", "name5", "name1", "name2", "name12", "name11", "name3", "name4", + "name10", "name6", "name5", "name1", "name2", "name12", "name11", "name3", "name4"}, + LevelsID: []int{10, 6, 5, 1, 2, 12, 11, 3, 4, + 10, 6, 5, 1, 2, 12, 11, 3, 4}, + } + + if !reflect.DeepEqual(wantedLabel, obtainedLabel) { + t.Errorf("The Label is different\n") + t.Errorf("Wanted %v, obtained %v\n", wantedLabel, obtainedLabel) + } + + if obtainedLabel.GetCommandName() != "name4" { + t.Errorf("The command name is different") + } + if obtainedLabel.GetCommandId() != 4 { + t.Errorf("The command ID is different") + } + if obtainedLabel.GetTopLevelName() != "name10" { + t.Errorf("The top name is different") + } + if obtainedLabel.GetTopLevelID() != 10 { + t.Errorf("The top ID is different") + } + wantedLabelAsAString := "name1010/name66/name55/name11/name22/name1212/name1111/name33/name44/" + + "name1010/name66/name55/name11/name22/name1212/name1111/name33/name44" + if obtainedLabel.GetLabelAsAString() != wantedLabelAsAString { + t.Errorf("The LabelAsAString is different") + t.Errorf("Wanted %v, obtained %v\n", wantedLabelAsAString, obtainedLabel.GetLabelAsAString()) + } +} diff --git a/gapis/api/vulkan/BUILD.bazel b/gapis/api/vulkan/BUILD.bazel index 7ed26aeb1b..0d3feaa9b3 100644 --- a/gapis/api/vulkan/BUILD.bazel +++ b/gapis/api/vulkan/BUILD.bazel @@ -151,6 +151,7 @@ go_test( name = "go_default_test", srcs = [ "externs_test.go", + "graph_visualization_test.go", "image_primer_shaders_test.go", "image_primer_test.go", ], diff --git a/gapis/api/vulkan/graph_visualization.go b/gapis/api/vulkan/graph_visualization.go index 27bf993b37..8832b599fb 100644 --- a/gapis/api/vulkan/graph_visualization.go +++ b/gapis/api/vulkan/graph_visualization.go @@ -51,9 +51,75 @@ type labelForVulkanCommands struct { subCommandIndexNameToHierarchyLabel map[string]*api.Label commandBufferIdToHierarchy map[VkCommandBuffer]*api.Hierarchy commandBufferIdToOrderNumber map[VkCommandBuffer]int - labelsInsideDebugMarkers []*api.Label - positionOfDebugMarkersBegin []int - numberOfDebugMarker int + nameAndIdToDebugMarkerStack map[string]*debugMarkerStack +} + +type debugMarkerStack struct { + // positionsOfDebugMarkersBegin is used like a stack, representing the position + // of debug_marker_begin commands in labels to access fast to its Label. + positionsOfDebugMarkersBegin []int + + // labels are all labels from commands considered. + labels []*api.Label + + // debugMarkerID is the unique ID assigned to debug_markers created. + debugMarkerID int +} + +func (dm *debugMarkerStack) getSize() int { + return len(dm.positionsOfDebugMarkersBegin) +} + +// top returns the Label of the last debug_marker_begin command if exists. +func (dm *debugMarkerStack) top() *api.Label { + if dm.getSize() > 0 { + position := dm.positionsOfDebugMarkersBegin[dm.getSize()-1] + if position < len(dm.labels) { + return dm.labels[position] + } + } + return &api.Label{} +} + +func (dm *debugMarkerStack) pop() { + if dm.getSize() > 0 { + dm.positionsOfDebugMarkersBegin = dm.positionsOfDebugMarkersBegin[:dm.getSize()-1] + } +} + +func (dm *debugMarkerStack) push(label *api.Label) { + dm.labels = append(dm.labels, label) + if label.GetCommandName() == VK_CMD_DEBUG_MARKER_BEGIN { + dm.positionsOfDebugMarkersBegin = append(dm.positionsOfDebugMarkersBegin, len(dm.labels)-1) + } +} + +// addDebugMarker adds a new debug marker from the last debug_marker_begin Label to the current Label. +func (dm *debugMarkerStack) addDebugMarker() { + position := dm.positionsOfDebugMarkersBegin[dm.getSize()-1] + size := dm.labels[position].GetSize() + dm.debugMarkerID++ + for i := position; i < len(dm.labels); i++ { + dm.labels[i].Insert(size-1, VK_CMD_DEBUG_MARKER, dm.debugMarkerID) + } +} + +func (dm *debugMarkerStack) checkDebugMarkers(label *api.Label) { + // It preserves Labels with no-decreasing sizes in the stack of debug_markers_begin avoiding + // insert debug markers in Labels with smaller sizes that would break the levels of hierarchy. + for dm.getSize() > 0 && label.GetSize() < dm.top().GetSize() { + dm.pop() + } + dm.push(label) + + if label.GetCommandName() == VK_CMD_DEBUG_MARKER_END { + if dm.getSize() > 0 { + if label.GetSize() == dm.top().GetSize() && getMaxCommonPrefix(label, dm.top()) == label.GetSize()-1 { + dm.addDebugMarker() + } + dm.pop() + } + } } func getCommandHierarchyNames() *api.HierarchyNames { @@ -88,55 +154,6 @@ func getMaxCommonPrefix(label1 *api.Label, label2 *api.Label) int { return size } -func addDebugMarker(builder *labelForVulkanCommands, from, to int) { - level := builder.labelsInsideDebugMarkers[len(builder.labelsInsideDebugMarkers)-1].GetSize() - 1 - builder.numberOfDebugMarker++ - for i := from; i <= to; i++ { - builder.labelsInsideDebugMarkers[i].Insert(level, VK_CMD_DEBUG_MARKER, builder.numberOfDebugMarker) - } -} - -func checkDebugMarkers(builder *labelForVulkanCommands, currentLabel *api.Label) { - commandName := currentLabel.GetCommandName() - positionOfLastDebugMarkerBegin := 0 - labelOfLastDebugMarkerBegin := &api.Label{} - if len(builder.positionOfDebugMarkersBegin) > 0 { - positionOfLastDebugMarkerBegin = builder.positionOfDebugMarkersBegin[len(builder.positionOfDebugMarkersBegin)-1] - labelOfLastDebugMarkerBegin = builder.labelsInsideDebugMarkers[positionOfLastDebugMarkerBegin] - } - - if commandName == VK_CMD_DEBUG_MARKER_BEGIN { - if len(builder.positionOfDebugMarkersBegin) > 0 { - if currentLabel.GetSize() < labelOfLastDebugMarkerBegin.GetSize() { - builder.positionOfDebugMarkersBegin = builder.positionOfDebugMarkersBegin[:len(builder.positionOfDebugMarkersBegin)-1] - } - } - builder.labelsInsideDebugMarkers = append(builder.labelsInsideDebugMarkers, currentLabel) - builder.positionOfDebugMarkersBegin = append(builder.positionOfDebugMarkersBegin, len(builder.labelsInsideDebugMarkers)-1) - - } else if commandName == VK_CMD_DEBUG_MARKER_END { - - if len(builder.positionOfDebugMarkersBegin) > 0 { - if currentLabel.GetSize() != labelOfLastDebugMarkerBegin.GetSize() { - builder.positionOfDebugMarkersBegin = builder.positionOfDebugMarkersBegin[:len(builder.positionOfDebugMarkersBegin)-1] - - } else if getMaxCommonPrefix(labelOfLastDebugMarkerBegin, currentLabel) == currentLabel.GetSize()-1 { - builder.labelsInsideDebugMarkers = append(builder.labelsInsideDebugMarkers, currentLabel) - builder.positionOfDebugMarkersBegin = append(builder.positionOfDebugMarkersBegin, len(builder.labelsInsideDebugMarkers)-1) - addDebugMarker(builder, positionOfLastDebugMarkerBegin, len(builder.labelsInsideDebugMarkers)-1) - builder.positionOfDebugMarkersBegin = builder.positionOfDebugMarkersBegin[:len(builder.positionOfDebugMarkersBegin)-1] - } - } - - } else if len(builder.positionOfDebugMarkersBegin) > 0 { - if currentLabel.GetSize() < labelOfLastDebugMarkerBegin.GetSize() { - builder.positionOfDebugMarkersBegin = builder.positionOfDebugMarkersBegin[:len(builder.positionOfDebugMarkersBegin)-1] - } else { - builder.labelsInsideDebugMarkers = append(builder.labelsInsideDebugMarkers, currentLabel) - } - } -} - func getCommandBufferId(command api.Cmd) (VkCommandBuffer, bool) { parameters := command.CmdParams() for _, parameter := range parameters { @@ -151,6 +168,7 @@ func getCommandBufferId(command api.Cmd) (VkCommandBuffer, bool) { func (builder *labelForVulkanCommands) GetCommandLabel(command api.Cmd, cmdId uint64) *api.Label { label := &api.Label{} commandName := command.CmdName() + nameAndId := "" if commandBufferId, ok := getCommandBufferId(command); ok { hierarchy, ok := builder.commandBufferIdToHierarchy[commandBufferId] if !ok { @@ -161,10 +179,18 @@ func (builder *labelForVulkanCommands) GetCommandLabel(command api.Cmd, cmdId ui label.PushBack(COMMAND_BUFFER, builder.commandBufferIdToOrderNumber[commandBufferId]) label.PushBackLabel(getLabelFromHierarchy(commandName, commandHierarchyNames, hierarchy)) label.PushBack(commandName, int(cmdId)) + nameAndId = fmt.Sprintf("%s%d", COMMAND_BUFFER, builder.commandBufferIdToOrderNumber[commandBufferId]) } else { label.PushBack(commandName, int(cmdId)) + nameAndId = fmt.Sprintf("%s%d", commandName, cmdId) + } + + currentDebugMarker, ok := builder.nameAndIdToDebugMarkerStack[nameAndId] + if !ok { + currentDebugMarker = &debugMarkerStack{} + builder.nameAndIdToDebugMarkerStack[nameAndId] = currentDebugMarker } - checkDebugMarkers(builder, label) + currentDebugMarker.checkDebugMarkers(label) return label } @@ -193,9 +219,15 @@ func (builder *labelForVulkanCommands) GetSubCommandLabel(index api.SubCmdIdx, c labelFromHierarchy := getLabelFromHierarchy(subCommandName, subCommandHierarchyNames, hierarchy) labelFromHierarchy.PushBack(subCommandName, int(index[len(index)-1])) builder.subCommandIndexNameToHierarchyLabel[subCommandIndexName.String()] = labelFromHierarchy - label.PushBackLabel(labelFromHierarchy) - checkDebugMarkers(builder, label) + + nameAndId := fmt.Sprintf("%s%d", commandName, cmdId) + currentDebugMarker, ok := builder.nameAndIdToDebugMarkerStack[nameAndId] + if !ok { + currentDebugMarker = &debugMarkerStack{} + builder.nameAndIdToDebugMarkerStack[nameAndId] = currentDebugMarker + } + currentDebugMarker.checkDebugMarkers(label) return label } @@ -233,5 +265,6 @@ func (API) GetGraphVisualizationBuilder() api.GraphVisualizationBuilder { subCommandIndexNameToHierarchyLabel: map[string]*api.Label{}, commandBufferIdToHierarchy: map[VkCommandBuffer]*api.Hierarchy{}, commandBufferIdToOrderNumber: map[VkCommandBuffer]int{}, + nameAndIdToDebugMarkerStack: map[string]*debugMarkerStack{}, } } diff --git a/gapis/api/vulkan/graph_visualization_test.go b/gapis/api/vulkan/graph_visualization_test.go new file mode 100644 index 0000000000..969ee07e79 --- /dev/null +++ b/gapis/api/vulkan/graph_visualization_test.go @@ -0,0 +1,582 @@ +// 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 vulkan + +import ( + "github.com/google/gapid/gapis/api" + "reflect" + "testing" +) + +const ( + VK_CMD_BIND_DESCRIPTOR_SETS = "vkCmdBindDescriptorSets" +) + +func TestGetLabelFromHierarchy1(t *testing.T) { + + commandHierarchyNames := getCommandHierarchyNames() + + auxiliarCommands := []string{ + "SetViewPort", + "SetBarrier", + "DrawIndex", + "SetScissor", + "SetIndexForDraw", + } + + commandsName := []string{ + VK_BEGIN_COMMAND_BUFFER, + auxiliarCommands[0], + auxiliarCommands[0], + VK_CMD_BEGIN_RENDER_PASS, + auxiliarCommands[0], + auxiliarCommands[1], + VK_CMD_NEXT_SUBPASS, + auxiliarCommands[2], + auxiliarCommands[1], + VK_CMD_NEXT_SUBPASS, + auxiliarCommands[0], + VK_CMD_END_RENDER_PASS, + auxiliarCommands[2], + auxiliarCommands[3], + VK_CMD_BEGIN_RENDER_PASS, + VK_CMD_END_RENDER_PASS, + VK_CMD_BEGIN_RENDER_PASS, + VK_CMD_END_RENDER_PASS, + VK_END_COMMAND_BUFFER, + + auxiliarCommands[3], + auxiliarCommands[4], + + VK_BEGIN_COMMAND_BUFFER, + auxiliarCommands[0], + auxiliarCommands[1], + auxiliarCommands[2], + auxiliarCommands[3], + VK_END_COMMAND_BUFFER, + + VK_BEGIN_COMMAND_BUFFER, + auxiliarCommands[4], + VK_END_COMMAND_BUFFER, + } + wantedLabels := []*api.Label{ + &api.Label{LevelsName: []string{VK_COMMAND_BUFFER}, LevelsID: []int{1}}, + &api.Label{LevelsName: []string{VK_COMMAND_BUFFER}, LevelsID: []int{1}}, + &api.Label{LevelsName: []string{VK_COMMAND_BUFFER}, LevelsID: []int{1}}, + &api.Label{LevelsName: []string{VK_COMMAND_BUFFER, VK_RENDER_PASS}, LevelsID: []int{1, 1}}, + &api.Label{LevelsName: []string{VK_COMMAND_BUFFER, VK_RENDER_PASS, VK_SUBPASS}, LevelsID: []int{1, 1, 1}}, + &api.Label{LevelsName: []string{VK_COMMAND_BUFFER, VK_RENDER_PASS, VK_SUBPASS}, LevelsID: []int{1, 1, 1}}, + &api.Label{LevelsName: []string{VK_COMMAND_BUFFER, VK_RENDER_PASS, VK_SUBPASS}, LevelsID: []int{1, 1, 2}}, + &api.Label{LevelsName: []string{VK_COMMAND_BUFFER, VK_RENDER_PASS, VK_SUBPASS}, LevelsID: []int{1, 1, 2}}, + &api.Label{LevelsName: []string{VK_COMMAND_BUFFER, VK_RENDER_PASS, VK_SUBPASS}, LevelsID: []int{1, 1, 2}}, + &api.Label{LevelsName: []string{VK_COMMAND_BUFFER, VK_RENDER_PASS, VK_SUBPASS}, LevelsID: []int{1, 1, 3}}, + &api.Label{LevelsName: []string{VK_COMMAND_BUFFER, VK_RENDER_PASS, VK_SUBPASS}, LevelsID: []int{1, 1, 3}}, + &api.Label{LevelsName: []string{VK_COMMAND_BUFFER, VK_RENDER_PASS}, LevelsID: []int{1, 1}}, + &api.Label{LevelsName: []string{VK_COMMAND_BUFFER}, LevelsID: []int{1}}, + &api.Label{LevelsName: []string{VK_COMMAND_BUFFER}, LevelsID: []int{1}}, + &api.Label{LevelsName: []string{VK_COMMAND_BUFFER, VK_RENDER_PASS}, LevelsID: []int{1, 2}}, + &api.Label{LevelsName: []string{VK_COMMAND_BUFFER, VK_RENDER_PASS}, LevelsID: []int{1, 2}}, + &api.Label{LevelsName: []string{VK_COMMAND_BUFFER, VK_RENDER_PASS}, LevelsID: []int{1, 3}}, + &api.Label{LevelsName: []string{VK_COMMAND_BUFFER, VK_RENDER_PASS}, LevelsID: []int{1, 3}}, + &api.Label{LevelsName: []string{VK_COMMAND_BUFFER}, LevelsID: []int{1}}, + &api.Label{}, + &api.Label{}, + &api.Label{LevelsName: []string{VK_COMMAND_BUFFER}, LevelsID: []int{2}}, + &api.Label{LevelsName: []string{VK_COMMAND_BUFFER}, LevelsID: []int{2}}, + &api.Label{LevelsName: []string{VK_COMMAND_BUFFER}, LevelsID: []int{2}}, + &api.Label{LevelsName: []string{VK_COMMAND_BUFFER}, LevelsID: []int{2}}, + &api.Label{LevelsName: []string{VK_COMMAND_BUFFER}, LevelsID: []int{2}}, + &api.Label{LevelsName: []string{VK_COMMAND_BUFFER}, LevelsID: []int{2}}, + &api.Label{LevelsName: []string{VK_COMMAND_BUFFER}, LevelsID: []int{3}}, + &api.Label{LevelsName: []string{VK_COMMAND_BUFFER}, LevelsID: []int{3}}, + &api.Label{LevelsName: []string{VK_COMMAND_BUFFER}, LevelsID: []int{3}}, + } + + currentHierarchy := &api.Hierarchy{} + obtainedLabels := []*api.Label{} + for _, name := range commandsName { + label := getLabelFromHierarchy(name, commandHierarchyNames, currentHierarchy) + obtainedLabels = append(obtainedLabels, label) + } + for i := range wantedLabels { + if !reflect.DeepEqual(wantedLabels[i], obtainedLabels[i]) { + t.Errorf("The label for command %s with id %d is different", commandsName[i], i) + t.Errorf("Obtained %v, wanted %v", obtainedLabels[i], wantedLabels[i]) + } + } + +} + +func TestGetLabelFromHierarchy2(t *testing.T) { + + commandHierarchyNames := getCommandHierarchyNames() + + auxiliarCommands := []string{ + "SetViewPort", + "SetBarrier", + "DrawIndex", + "SetScissor", + "SetIndexForDraw", + } + + commandsName := []string{ + VK_BEGIN_COMMAND_BUFFER, + auxiliarCommands[0], + auxiliarCommands[0], + VK_CMD_BEGIN_RENDER_PASS, + auxiliarCommands[0], + auxiliarCommands[1], + VK_CMD_NEXT_SUBPASS, + auxiliarCommands[2], + auxiliarCommands[1], + VK_CMD_NEXT_SUBPASS, + auxiliarCommands[0], + VK_CMD_END_RENDER_PASS, + auxiliarCommands[2], + auxiliarCommands[3], + VK_END_COMMAND_BUFFER, + + auxiliarCommands[3], + auxiliarCommands[4], + + VK_BEGIN_COMMAND_BUFFER, + auxiliarCommands[0], + auxiliarCommands[0], + VK_CMD_BEGIN_RENDER_PASS, + auxiliarCommands[0], + auxiliarCommands[1], + VK_CMD_NEXT_SUBPASS, + auxiliarCommands[2], + auxiliarCommands[1], + VK_CMD_NEXT_SUBPASS, + auxiliarCommands[0], + VK_CMD_END_RENDER_PASS, + auxiliarCommands[2], + auxiliarCommands[3], + VK_END_COMMAND_BUFFER, + + auxiliarCommands[3], + auxiliarCommands[4], + + VK_BEGIN_COMMAND_BUFFER, + auxiliarCommands[0], + auxiliarCommands[0], + VK_CMD_BEGIN_RENDER_PASS, + auxiliarCommands[0], + auxiliarCommands[1], + VK_CMD_NEXT_SUBPASS, + auxiliarCommands[2], + auxiliarCommands[1], + VK_CMD_NEXT_SUBPASS, + auxiliarCommands[0], + VK_CMD_END_RENDER_PASS, + auxiliarCommands[2], + auxiliarCommands[3], + VK_END_COMMAND_BUFFER, + + auxiliarCommands[3], + auxiliarCommands[4], + } + wantedLabels := []*api.Label{ + &api.Label{LevelsName: []string{VK_COMMAND_BUFFER}, LevelsID: []int{1}}, + &api.Label{LevelsName: []string{VK_COMMAND_BUFFER}, LevelsID: []int{1}}, + &api.Label{LevelsName: []string{VK_COMMAND_BUFFER}, LevelsID: []int{1}}, + &api.Label{LevelsName: []string{VK_COMMAND_BUFFER, VK_RENDER_PASS}, LevelsID: []int{1, 1}}, + &api.Label{LevelsName: []string{VK_COMMAND_BUFFER, VK_RENDER_PASS, VK_SUBPASS}, LevelsID: []int{1, 1, 1}}, + &api.Label{LevelsName: []string{VK_COMMAND_BUFFER, VK_RENDER_PASS, VK_SUBPASS}, LevelsID: []int{1, 1, 1}}, + &api.Label{LevelsName: []string{VK_COMMAND_BUFFER, VK_RENDER_PASS, VK_SUBPASS}, LevelsID: []int{1, 1, 2}}, + &api.Label{LevelsName: []string{VK_COMMAND_BUFFER, VK_RENDER_PASS, VK_SUBPASS}, LevelsID: []int{1, 1, 2}}, + &api.Label{LevelsName: []string{VK_COMMAND_BUFFER, VK_RENDER_PASS, VK_SUBPASS}, LevelsID: []int{1, 1, 2}}, + &api.Label{LevelsName: []string{VK_COMMAND_BUFFER, VK_RENDER_PASS, VK_SUBPASS}, LevelsID: []int{1, 1, 3}}, + &api.Label{LevelsName: []string{VK_COMMAND_BUFFER, VK_RENDER_PASS, VK_SUBPASS}, LevelsID: []int{1, 1, 3}}, + &api.Label{LevelsName: []string{VK_COMMAND_BUFFER, VK_RENDER_PASS}, LevelsID: []int{1, 1}}, + &api.Label{LevelsName: []string{VK_COMMAND_BUFFER}, LevelsID: []int{1}}, + &api.Label{LevelsName: []string{VK_COMMAND_BUFFER}, LevelsID: []int{1}}, + &api.Label{LevelsName: []string{VK_COMMAND_BUFFER}, LevelsID: []int{1}}, + &api.Label{}, + &api.Label{}, + + &api.Label{LevelsName: []string{VK_COMMAND_BUFFER}, LevelsID: []int{2}}, + &api.Label{LevelsName: []string{VK_COMMAND_BUFFER}, LevelsID: []int{2}}, + &api.Label{LevelsName: []string{VK_COMMAND_BUFFER}, LevelsID: []int{2}}, + &api.Label{LevelsName: []string{VK_COMMAND_BUFFER, VK_RENDER_PASS}, LevelsID: []int{2, 1}}, + &api.Label{LevelsName: []string{VK_COMMAND_BUFFER, VK_RENDER_PASS, VK_SUBPASS}, LevelsID: []int{2, 1, 1}}, + &api.Label{LevelsName: []string{VK_COMMAND_BUFFER, VK_RENDER_PASS, VK_SUBPASS}, LevelsID: []int{2, 1, 1}}, + &api.Label{LevelsName: []string{VK_COMMAND_BUFFER, VK_RENDER_PASS, VK_SUBPASS}, LevelsID: []int{2, 1, 2}}, + &api.Label{LevelsName: []string{VK_COMMAND_BUFFER, VK_RENDER_PASS, VK_SUBPASS}, LevelsID: []int{2, 1, 2}}, + &api.Label{LevelsName: []string{VK_COMMAND_BUFFER, VK_RENDER_PASS, VK_SUBPASS}, LevelsID: []int{2, 1, 2}}, + &api.Label{LevelsName: []string{VK_COMMAND_BUFFER, VK_RENDER_PASS, VK_SUBPASS}, LevelsID: []int{2, 1, 3}}, + &api.Label{LevelsName: []string{VK_COMMAND_BUFFER, VK_RENDER_PASS, VK_SUBPASS}, LevelsID: []int{2, 1, 3}}, + &api.Label{LevelsName: []string{VK_COMMAND_BUFFER, VK_RENDER_PASS}, LevelsID: []int{2, 1}}, + &api.Label{LevelsName: []string{VK_COMMAND_BUFFER}, LevelsID: []int{2}}, + &api.Label{LevelsName: []string{VK_COMMAND_BUFFER}, LevelsID: []int{2}}, + &api.Label{LevelsName: []string{VK_COMMAND_BUFFER}, LevelsID: []int{2}}, + &api.Label{}, + &api.Label{}, + + &api.Label{LevelsName: []string{VK_COMMAND_BUFFER}, LevelsID: []int{3}}, + &api.Label{LevelsName: []string{VK_COMMAND_BUFFER}, LevelsID: []int{3}}, + &api.Label{LevelsName: []string{VK_COMMAND_BUFFER}, LevelsID: []int{3}}, + &api.Label{LevelsName: []string{VK_COMMAND_BUFFER, VK_RENDER_PASS}, LevelsID: []int{3, 1}}, + &api.Label{LevelsName: []string{VK_COMMAND_BUFFER, VK_RENDER_PASS, VK_SUBPASS}, LevelsID: []int{3, 1, 1}}, + &api.Label{LevelsName: []string{VK_COMMAND_BUFFER, VK_RENDER_PASS, VK_SUBPASS}, LevelsID: []int{3, 1, 1}}, + &api.Label{LevelsName: []string{VK_COMMAND_BUFFER, VK_RENDER_PASS, VK_SUBPASS}, LevelsID: []int{3, 1, 2}}, + &api.Label{LevelsName: []string{VK_COMMAND_BUFFER, VK_RENDER_PASS, VK_SUBPASS}, LevelsID: []int{3, 1, 2}}, + &api.Label{LevelsName: []string{VK_COMMAND_BUFFER, VK_RENDER_PASS, VK_SUBPASS}, LevelsID: []int{3, 1, 2}}, + &api.Label{LevelsName: []string{VK_COMMAND_BUFFER, VK_RENDER_PASS, VK_SUBPASS}, LevelsID: []int{3, 1, 3}}, + &api.Label{LevelsName: []string{VK_COMMAND_BUFFER, VK_RENDER_PASS, VK_SUBPASS}, LevelsID: []int{3, 1, 3}}, + &api.Label{LevelsName: []string{VK_COMMAND_BUFFER, VK_RENDER_PASS}, LevelsID: []int{3, 1}}, + &api.Label{LevelsName: []string{VK_COMMAND_BUFFER}, LevelsID: []int{3}}, + &api.Label{LevelsName: []string{VK_COMMAND_BUFFER}, LevelsID: []int{3}}, + &api.Label{LevelsName: []string{VK_COMMAND_BUFFER}, LevelsID: []int{3}}, + &api.Label{}, + &api.Label{}, + } + + currentHierarchy := &api.Hierarchy{} + obtainedLabels := []*api.Label{} + for _, name := range commandsName { + label := getLabelFromHierarchy(name, commandHierarchyNames, currentHierarchy) + obtainedLabels = append(obtainedLabels, label) + } + for i := range wantedLabels { + if !reflect.DeepEqual(wantedLabels[i], obtainedLabels[i]) { + t.Errorf("The label for command %s with id %d is different", commandsName[i], i) + t.Errorf("Obtained %v, wanted %v", obtainedLabels[i], wantedLabels[i]) + } + } +} + +func TestGetLabelFromHierarchy3(t *testing.T) { + + commandHierarchyNames := getCommandHierarchyNames() + + auxiliarCommands := []string{ + "SetViewPort", + "SetBarrier", + "DrawIndex", + "SetScissor", + "SetIndexForDraw", + } + + commandsName := []string{ + auxiliarCommands[0], + auxiliarCommands[1], + VK_BEGIN_COMMAND_BUFFER, + auxiliarCommands[0], + auxiliarCommands[1], + VK_CMD_BEGIN_RENDER_PASS, + auxiliarCommands[1], + auxiliarCommands[2], + auxiliarCommands[3], + VK_CMD_NEXT_SUBPASS, + auxiliarCommands[1], + auxiliarCommands[2], + VK_CMD_NEXT_SUBPASS, + VK_CMD_NEXT_SUBPASS, + auxiliarCommands[1], + auxiliarCommands[2], + VK_CMD_NEXT_SUBPASS, + VK_CMD_END_RENDER_PASS, + auxiliarCommands[0], + VK_CMD_BEGIN_RENDER_PASS, + VK_CMD_NEXT_SUBPASS, + VK_CMD_NEXT_SUBPASS, + VK_CMD_NEXT_SUBPASS, + VK_CMD_NEXT_SUBPASS, + VK_CMD_END_RENDER_PASS, + auxiliarCommands[0], + VK_CMD_BEGIN_RENDER_PASS, + VK_CMD_END_RENDER_PASS, + auxiliarCommands[0], + VK_CMD_BEGIN_RENDER_PASS, + VK_CMD_END_RENDER_PASS, + auxiliarCommands[3], + VK_CMD_BEGIN_RENDER_PASS, + VK_CMD_END_RENDER_PASS, + VK_CMD_BEGIN_RENDER_PASS, + VK_CMD_END_RENDER_PASS, + VK_END_COMMAND_BUFFER, + auxiliarCommands[2], + auxiliarCommands[1], + VK_BEGIN_COMMAND_BUFFER, + VK_END_COMMAND_BUFFER, + auxiliarCommands[1], + } + wantedLabels := []*api.Label{ + &api.Label{}, + &api.Label{}, + &api.Label{LevelsName: []string{VK_COMMAND_BUFFER}, LevelsID: []int{1}}, + &api.Label{LevelsName: []string{VK_COMMAND_BUFFER}, LevelsID: []int{1}}, + &api.Label{LevelsName: []string{VK_COMMAND_BUFFER}, LevelsID: []int{1}}, + &api.Label{LevelsName: []string{VK_COMMAND_BUFFER, VK_RENDER_PASS}, LevelsID: []int{1, 1}}, + &api.Label{LevelsName: []string{VK_COMMAND_BUFFER, VK_RENDER_PASS, VK_SUBPASS}, LevelsID: []int{1, 1, 1}}, + &api.Label{LevelsName: []string{VK_COMMAND_BUFFER, VK_RENDER_PASS, VK_SUBPASS}, LevelsID: []int{1, 1, 1}}, + &api.Label{LevelsName: []string{VK_COMMAND_BUFFER, VK_RENDER_PASS, VK_SUBPASS}, LevelsID: []int{1, 1, 1}}, + &api.Label{LevelsName: []string{VK_COMMAND_BUFFER, VK_RENDER_PASS, VK_SUBPASS}, LevelsID: []int{1, 1, 2}}, + &api.Label{LevelsName: []string{VK_COMMAND_BUFFER, VK_RENDER_PASS, VK_SUBPASS}, LevelsID: []int{1, 1, 2}}, + &api.Label{LevelsName: []string{VK_COMMAND_BUFFER, VK_RENDER_PASS, VK_SUBPASS}, LevelsID: []int{1, 1, 2}}, + &api.Label{LevelsName: []string{VK_COMMAND_BUFFER, VK_RENDER_PASS, VK_SUBPASS}, LevelsID: []int{1, 1, 3}}, + &api.Label{LevelsName: []string{VK_COMMAND_BUFFER, VK_RENDER_PASS, VK_SUBPASS}, LevelsID: []int{1, 1, 4}}, + &api.Label{LevelsName: []string{VK_COMMAND_BUFFER, VK_RENDER_PASS, VK_SUBPASS}, LevelsID: []int{1, 1, 4}}, + &api.Label{LevelsName: []string{VK_COMMAND_BUFFER, VK_RENDER_PASS, VK_SUBPASS}, LevelsID: []int{1, 1, 4}}, + &api.Label{LevelsName: []string{VK_COMMAND_BUFFER, VK_RENDER_PASS, VK_SUBPASS}, LevelsID: []int{1, 1, 5}}, + &api.Label{LevelsName: []string{VK_COMMAND_BUFFER, VK_RENDER_PASS}, LevelsID: []int{1, 1}}, + &api.Label{LevelsName: []string{VK_COMMAND_BUFFER}, LevelsID: []int{1}}, + &api.Label{LevelsName: []string{VK_COMMAND_BUFFER, VK_RENDER_PASS}, LevelsID: []int{1, 2}}, + &api.Label{LevelsName: []string{VK_COMMAND_BUFFER, VK_RENDER_PASS, VK_SUBPASS}, LevelsID: []int{1, 2, 2}}, + &api.Label{LevelsName: []string{VK_COMMAND_BUFFER, VK_RENDER_PASS, VK_SUBPASS}, LevelsID: []int{1, 2, 3}}, + &api.Label{LevelsName: []string{VK_COMMAND_BUFFER, VK_RENDER_PASS, VK_SUBPASS}, LevelsID: []int{1, 2, 4}}, + &api.Label{LevelsName: []string{VK_COMMAND_BUFFER, VK_RENDER_PASS, VK_SUBPASS}, LevelsID: []int{1, 2, 5}}, + &api.Label{LevelsName: []string{VK_COMMAND_BUFFER, VK_RENDER_PASS}, LevelsID: []int{1, 2}}, + &api.Label{LevelsName: []string{VK_COMMAND_BUFFER}, LevelsID: []int{1}}, + &api.Label{LevelsName: []string{VK_COMMAND_BUFFER, VK_RENDER_PASS}, LevelsID: []int{1, 3}}, + &api.Label{LevelsName: []string{VK_COMMAND_BUFFER, VK_RENDER_PASS}, LevelsID: []int{1, 3}}, + &api.Label{LevelsName: []string{VK_COMMAND_BUFFER}, LevelsID: []int{1}}, + &api.Label{LevelsName: []string{VK_COMMAND_BUFFER, VK_RENDER_PASS}, LevelsID: []int{1, 4}}, + &api.Label{LevelsName: []string{VK_COMMAND_BUFFER, VK_RENDER_PASS}, LevelsID: []int{1, 4}}, + &api.Label{LevelsName: []string{VK_COMMAND_BUFFER}, LevelsID: []int{1}}, + &api.Label{LevelsName: []string{VK_COMMAND_BUFFER, VK_RENDER_PASS}, LevelsID: []int{1, 5}}, + &api.Label{LevelsName: []string{VK_COMMAND_BUFFER, VK_RENDER_PASS}, LevelsID: []int{1, 5}}, + &api.Label{LevelsName: []string{VK_COMMAND_BUFFER, VK_RENDER_PASS}, LevelsID: []int{1, 6}}, + &api.Label{LevelsName: []string{VK_COMMAND_BUFFER, VK_RENDER_PASS}, LevelsID: []int{1, 6}}, + &api.Label{LevelsName: []string{VK_COMMAND_BUFFER}, LevelsID: []int{1}}, + &api.Label{}, + &api.Label{}, + &api.Label{LevelsName: []string{VK_COMMAND_BUFFER}, LevelsID: []int{2}}, + &api.Label{LevelsName: []string{VK_COMMAND_BUFFER}, LevelsID: []int{2}}, + &api.Label{}, + } + + currentHierarchy := &api.Hierarchy{} + obtainedLabels := []*api.Label{} + for _, name := range commandsName { + label := getLabelFromHierarchy(name, commandHierarchyNames, currentHierarchy) + obtainedLabels = append(obtainedLabels, label) + } + for i := range wantedLabels { + if !reflect.DeepEqual(wantedLabels[i], obtainedLabels[i]) { + t.Errorf("The label for command %s with id %d is different", commandsName[i], i) + t.Errorf("Obtained %v, wanted %v", obtainedLabels[i], wantedLabels[i]) + } + } +} + +func TestDebugMarkers1(t *testing.T) { + + dm := &debugMarkerStack{} + input := []*api.Label{ + &api.Label{ + LevelsName: []string{VK_COMMAND_BUFFER, VK_RENDER_PASS, VK_SUBPASS, VK_CMD_DEBUG_MARKER_END}, + LevelsID: []int{1, 1, 1, 1}, + }, + &api.Label{ + LevelsName: []string{VK_COMMAND_BUFFER, VK_RENDER_PASS, VK_SUBPASS, VK_CMD_DEBUG_MARKER_BEGIN}, + LevelsID: []int{1, 1, 1, 3}, + }, + &api.Label{ + LevelsName: []string{VK_COMMAND_BUFFER, VK_RENDER_PASS, VK_SUBPASS, VK_CMD_DEBUG_MARKER_BEGIN}, + LevelsID: []int{1, 1, 1, 4}, + }, + &api.Label{ + LevelsName: []string{VK_COMMAND_BUFFER, VK_RENDER_PASS, VK_SUBPASS, VK_CMD_DEBUG_MARKER_BEGIN}, + LevelsID: []int{1, 1, 1, 6}, + }, + &api.Label{ + LevelsName: []string{VK_COMMAND_BUFFER, VK_RENDER_PASS, VK_SUBPASS, VK_CMD_BIND_DESCRIPTOR_SETS}, + LevelsID: []int{1, 1, 1, 7}, + }, + &api.Label{ + LevelsName: []string{VK_COMMAND_BUFFER, VK_RENDER_PASS, VK_SUBPASS, VK_CMD_BIND_DESCRIPTOR_SETS}, + LevelsID: []int{1, 1, 1, 8}, + }, + &api.Label{ + LevelsName: []string{VK_COMMAND_BUFFER, VK_RENDER_PASS, VK_SUBPASS, VK_CMD_BIND_DESCRIPTOR_SETS}, + LevelsID: []int{1, 1, 1, 9}, + }, + &api.Label{ + LevelsName: []string{VK_COMMAND_BUFFER, VK_RENDER_PASS, VK_SUBPASS, VK_CMD_DEBUG_MARKER_END}, + LevelsID: []int{1, 1, 1, 10}, + }, + &api.Label{ + LevelsName: []string{VK_COMMAND_BUFFER, VK_RENDER_PASS, VK_SUBPASS, VK_CMD_DEBUG_MARKER_END}, + LevelsID: []int{1, 1, 1, 11}, + }, + &api.Label{ + LevelsName: []string{VK_COMMAND_BUFFER, VK_RENDER_PASS, VK_SUBPASS, VK_CMD_DEBUG_MARKER_END}, + LevelsID: []int{1, 1, 1, 12}, + }, + &api.Label{ + LevelsName: []string{VK_COMMAND_BUFFER, VK_RENDER_PASS, VK_SUBPASS, VK_CMD_DEBUG_MARKER_BEGIN}, + LevelsID: []int{1, 1, 1, 20}, + }, + &api.Label{ + LevelsName: []string{VK_COMMAND_BUFFER, VK_RENDER_PASS, VK_SUBPASS, VK_CMD_DEBUG_MARKER_BEGIN}, + LevelsID: []int{1, 1, 1, 21}, + }, + } + wantedOutput := []*api.Label{ + &api.Label{ + LevelsName: []string{VK_COMMAND_BUFFER, VK_RENDER_PASS, VK_SUBPASS, VK_CMD_DEBUG_MARKER_END}, + LevelsID: []int{1, 1, 1, 1}, + }, + &api.Label{ + LevelsName: []string{VK_COMMAND_BUFFER, VK_RENDER_PASS, VK_SUBPASS, VK_CMD_DEBUG_MARKER, VK_CMD_DEBUG_MARKER_BEGIN}, + LevelsID: []int{1, 1, 1, 3, 3}, + }, + &api.Label{ + LevelsName: []string{VK_COMMAND_BUFFER, VK_RENDER_PASS, VK_SUBPASS, VK_CMD_DEBUG_MARKER, VK_CMD_DEBUG_MARKER, VK_CMD_DEBUG_MARKER_BEGIN}, + LevelsID: []int{1, 1, 1, 3, 2, 4}, + }, + &api.Label{ + LevelsName: []string{VK_COMMAND_BUFFER, VK_RENDER_PASS, VK_SUBPASS, VK_CMD_DEBUG_MARKER, VK_CMD_DEBUG_MARKER, VK_CMD_DEBUG_MARKER, VK_CMD_DEBUG_MARKER_BEGIN}, + LevelsID: []int{1, 1, 1, 3, 2, 1, 6}, + }, + &api.Label{ + LevelsName: []string{VK_COMMAND_BUFFER, VK_RENDER_PASS, VK_SUBPASS, VK_CMD_DEBUG_MARKER, VK_CMD_DEBUG_MARKER, VK_CMD_DEBUG_MARKER, VK_CMD_BIND_DESCRIPTOR_SETS}, + LevelsID: []int{1, 1, 1, 3, 2, 1, 7}, + }, + &api.Label{ + LevelsName: []string{VK_COMMAND_BUFFER, VK_RENDER_PASS, VK_SUBPASS, VK_CMD_DEBUG_MARKER, VK_CMD_DEBUG_MARKER, VK_CMD_DEBUG_MARKER, VK_CMD_BIND_DESCRIPTOR_SETS}, + LevelsID: []int{1, 1, 1, 3, 2, 1, 8}, + }, + &api.Label{ + LevelsName: []string{VK_COMMAND_BUFFER, VK_RENDER_PASS, VK_SUBPASS, VK_CMD_DEBUG_MARKER, VK_CMD_DEBUG_MARKER, VK_CMD_DEBUG_MARKER, VK_CMD_BIND_DESCRIPTOR_SETS}, + LevelsID: []int{1, 1, 1, 3, 2, 1, 9}, + }, + &api.Label{ + LevelsName: []string{VK_COMMAND_BUFFER, VK_RENDER_PASS, VK_SUBPASS, VK_CMD_DEBUG_MARKER, VK_CMD_DEBUG_MARKER, VK_CMD_DEBUG_MARKER, VK_CMD_DEBUG_MARKER_END}, + LevelsID: []int{1, 1, 1, 3, 2, 1, 10}, + }, + &api.Label{ + LevelsName: []string{VK_COMMAND_BUFFER, VK_RENDER_PASS, VK_SUBPASS, VK_CMD_DEBUG_MARKER, VK_CMD_DEBUG_MARKER, VK_CMD_DEBUG_MARKER_END}, + LevelsID: []int{1, 1, 1, 3, 2, 11}, + }, + &api.Label{ + LevelsName: []string{VK_COMMAND_BUFFER, VK_RENDER_PASS, VK_SUBPASS, VK_CMD_DEBUG_MARKER, VK_CMD_DEBUG_MARKER_END}, + LevelsID: []int{1, 1, 1, 3, 12}, + }, + &api.Label{ + LevelsName: []string{VK_COMMAND_BUFFER, VK_RENDER_PASS, VK_SUBPASS, VK_CMD_DEBUG_MARKER_BEGIN}, + LevelsID: []int{1, 1, 1, 20}, + }, + &api.Label{ + LevelsName: []string{VK_COMMAND_BUFFER, VK_RENDER_PASS, VK_SUBPASS, VK_CMD_DEBUG_MARKER_BEGIN}, + LevelsID: []int{1, 1, 1, 21}, + }, + } + + for _, label := range input { + dm.checkDebugMarkers(label) + } + obtainedOutput := input + + if !reflect.DeepEqual(wantedOutput, obtainedOutput) { + t.Errorf("The debug markers were added incorrectly\n") + } +} + +func TestDebugMarkers2(t *testing.T) { + + dm := &debugMarkerStack{} + input := []*api.Label{ + &api.Label{ + LevelsName: []string{VK_COMMAND_BUFFER, VK_RENDER_PASS, VK_CMD_DEBUG_MARKER_BEGIN}, + LevelsID: []int{1, 1, 1}, + }, + &api.Label{ + LevelsName: []string{VK_COMMAND_BUFFER, VK_CMD_DEBUG_MARKER_BEGIN}, + LevelsID: []int{1, 2}, + }, + &api.Label{ + LevelsName: []string{VK_COMMAND_BUFFER, VK_CMD_DEBUG_MARKER_END}, + LevelsID: []int{1, 3}, + }, + &api.Label{ + LevelsName: []string{VK_COMMAND_BUFFER, VK_RENDER_PASS, VK_CMD_DEBUG_MARKER_END}, + LevelsID: []int{1, 1, 3}, + }, + &api.Label{ + LevelsName: []string{VK_COMMAND_BUFFER, VK_CMD_DEBUG_MARKER_BEGIN}, + LevelsID: []int{1, 4}, + }, + &api.Label{ + LevelsName: []string{VK_COMMAND_BUFFER, VK_RENDER_PASS, VK_CMD_DEBUG_MARKER_BEGIN}, + LevelsID: []int{1, 2, 1}, + }, + &api.Label{ + LevelsName: []string{VK_COMMAND_BUFFER, VK_RENDER_PASS, VK_CMD_BIND_DESCRIPTOR_SETS}, + LevelsID: []int{1, 2, 3}, + }, + &api.Label{ + LevelsName: []string{VK_COMMAND_BUFFER, VK_RENDER_PASS, VK_CMD_DEBUG_MARKER_END}, + LevelsID: []int{1, 2, 5}, + }, + + &api.Label{ + LevelsName: []string{VK_COMMAND_BUFFER, VK_CMD_DEBUG_MARKER_END}, + LevelsID: []int{1, 7}, + }, + } + + wantedOutput := []*api.Label{ + &api.Label{ + LevelsName: []string{VK_COMMAND_BUFFER, VK_RENDER_PASS, VK_CMD_DEBUG_MARKER_BEGIN}, + LevelsID: []int{1, 1, 1}, + }, + &api.Label{ + LevelsName: []string{VK_COMMAND_BUFFER, VK_CMD_DEBUG_MARKER, VK_CMD_DEBUG_MARKER_BEGIN}, + LevelsID: []int{1, 1, 2}, + }, + &api.Label{ + LevelsName: []string{VK_COMMAND_BUFFER, VK_CMD_DEBUG_MARKER, VK_CMD_DEBUG_MARKER_END}, + LevelsID: []int{1, 1, 3}, + }, + &api.Label{ + LevelsName: []string{VK_COMMAND_BUFFER, VK_RENDER_PASS, VK_CMD_DEBUG_MARKER_END}, + LevelsID: []int{1, 1, 3}, + }, + &api.Label{ + LevelsName: []string{VK_COMMAND_BUFFER, VK_CMD_DEBUG_MARKER, VK_CMD_DEBUG_MARKER_BEGIN}, + LevelsID: []int{1, 3, 4}, + }, + &api.Label{ + LevelsName: []string{VK_COMMAND_BUFFER, VK_CMD_DEBUG_MARKER, VK_RENDER_PASS, VK_CMD_DEBUG_MARKER, VK_CMD_DEBUG_MARKER_BEGIN}, + LevelsID: []int{1, 3, 2, 2, 1}, + }, + &api.Label{ + LevelsName: []string{VK_COMMAND_BUFFER, VK_CMD_DEBUG_MARKER, VK_RENDER_PASS, VK_CMD_DEBUG_MARKER, VK_CMD_BIND_DESCRIPTOR_SETS}, + LevelsID: []int{1, 3, 2, 2, 3}, + }, + &api.Label{ + LevelsName: []string{VK_COMMAND_BUFFER, VK_CMD_DEBUG_MARKER, VK_RENDER_PASS, VK_CMD_DEBUG_MARKER, VK_CMD_DEBUG_MARKER_END}, + LevelsID: []int{1, 3, 2, 2, 5}, + }, + + &api.Label{ + LevelsName: []string{VK_COMMAND_BUFFER, VK_CMD_DEBUG_MARKER, VK_CMD_DEBUG_MARKER_END}, + LevelsID: []int{1, 3, 7}, + }, + } + + for _, label := range input { + dm.checkDebugMarkers(label) + } + obtainedOutput := input + + if !reflect.DeepEqual(wantedOutput, obtainedOutput) { + t.Errorf("The debug markers were added incorrectly\n") + } +} diff --git a/gapis/resolve/dependencygraph2/graph_visualization/graph_algorithms.go b/gapis/resolve/dependencygraph2/graph_visualization/graph_algorithms.go index ff4affa85c..a7bfbf3f5e 100644 --- a/gapis/resolve/dependencygraph2/graph_visualization/graph_algorithms.go +++ b/gapis/resolve/dependencygraph2/graph_visualization/graph_algorithms.go @@ -15,6 +15,8 @@ package graph_visualization import ( + "bytes" + "fmt" "github.com/google/gapid/gapis/api" ) @@ -23,6 +25,7 @@ const ( VISITED_AND_USED = -1 FRAME = "FRAME" UNUSED = "UNUSED" + SUPER = "SUPER" ) // It is used to find the Strongly Connected Components (SCC) in a directed graph based on Tarjan algorithm @@ -152,3 +155,142 @@ func (g *graph) joinNodesWithZeroDegree() { } } } + +func (g *graph) assignColorToNodes() { + for _, currentNode := range g.nodeIdToNode { + currentNode.color = currentNode.label.GetTopLevelName() + } +} + +func (g *graph) joinNodesThatDoNotBelongToAnyFrame() { + for _, currentNode := range g.nodeIdToNode { + if currentNode.label.GetSize() > 0 && currentNode.label.GetTopLevelName() != FRAME { + currentNode.label.PushFront(UNUSED, 0) + } + } +} + +type chunkConfig struct { + maximumNumberOfNodesByLevel int + minimumNumberOfNodesToBeChunk int +} + +type chunk struct { + // levelIDToPosition maps a single levelID from Label to a position in + // the range [0, 1, 2, 3, ...]. + levelIDToPosition map[int]int + + // positionToChunksID are the chunks ID obtained from the K-ary tree built + // for the range [0, 1, 2, 3, ...]. + positionToChunksID [][]int + + // built checks if the K-ary tree was built for this chunk. + built bool + + // config contains the minimum number of nodes to build the K-ary tree and also + // the value of k, which is called maximum number of nodes by level. + config chunkConfig +} + +// assignChunksIDToNodesInTheKaryTreeBuilt builds a K-ary tree for the range of +// nodes ID [left, left+1, left+2, ..... , right-1, right] (chunk). Then it assigns +// the chunks ID for the nodes ID obtained from the K-ary tree. +func (c *chunk) assignChunksIDToNodesInTheKaryTreeBuilt(left, right int, currentChunksID *[]int) { + + // Base case: if the number of nodes ID in the current chunk is at most K, + // then the currentChunksID is assigned to nodes ID. + if (right - left + 1) <= c.config.maximumNumberOfNodesByLevel { + for i := left; i <= right; i++ { + c.positionToChunksID[i] = make([]int, len(*currentChunksID)) + copy(c.positionToChunksID[i], *currentChunksID) + } + } else { + // General case: It creates at most K smaller chunks as balanced as possible + // and build the K-ary tree for each of them. + + // It is append to give ID to the smaller chunks. + *currentChunksID = append(*currentChunksID, 1) + // It computes the ceiling to take all nodes ID of the current chunk + chunkSize := (right - left + 1 + c.config.maximumNumberOfNodesByLevel - 1) / c.config.maximumNumberOfNodesByLevel + newLeft := left + newRight := newLeft + chunkSize - 1 + chunkID := 1 + for newLeft <= right { + if newRight > right { + newRight = right + } + // It assigns the ID for the new smaller chunk. + (*currentChunksID)[len(*currentChunksID)-1] = chunkID + // Call recursively to build the K-ary tree for the new smaller chunk. + c.assignChunksIDToNodesInTheKaryTreeBuilt(newLeft, newRight, currentChunksID) + newLeft = newRight + 1 + newRight = newLeft + chunkSize - 1 + chunkID++ + } + // It removes the last element before go backwards in the recursion. + *currentChunksID = (*currentChunksID)[:len(*currentChunksID)-1] + } +} + +func (g *graph) makeChunks(config chunkConfig) { + + // This first part builds an implicit tree of nodes defined like a pair + // {key -> set_of_values}. The key of a node is a string and the set_of_values + // is a set of integers being LevelsID from Labels. For each level i in + // Label starting from top level, a new node is created with: + // key = LevelsName[0] + levelsID[0] + / + LevelsName[1] + LevelsID[1] + / + ... + LevelsName[i], + // where '+' means concatenation and LevelsID[i] is inserted in set_of_values, + // if the node with such key already exists only the LevelsID[i] is inserted. + nodes := g.getSortedNodes() + labelAsAStringToChunk := map[string]*chunk{} + for _, currentNode := range nodes { + var labelAsAString bytes.Buffer + for i, name := range currentNode.label.LevelsName { + id := currentNode.label.LevelsID[i] + labelAsAString.WriteString(name) + if name != FRAME { + currentChunk, ok := labelAsAStringToChunk[labelAsAString.String()] + if !ok { + currentChunk = &chunk{levelIDToPosition: map[int]int{}, config: config} + labelAsAStringToChunk[labelAsAString.String()] = currentChunk + } + if _, ok := currentChunk.levelIDToPosition[id]; !ok { + currentChunk.levelIDToPosition[id] = len(currentChunk.levelIDToPosition) + } + } + fmt.Fprintf(&labelAsAString, "%d/", id) + } + } + + // This second part builds a K-ary tree for each set_of_values in nodes of the + // implicit tree built in the first part. In a K-ary tree every node consist + // of at most K children (chunks). + for _, currentNode := range nodes { + var labelAsAString bytes.Buffer + newLabel := &api.Label{} + for i, name := range currentNode.label.LevelsName { + id := currentNode.label.LevelsID[i] + labelAsAString.WriteString(name) + if name != FRAME { + currentChunk := labelAsAStringToChunk[labelAsAString.String()] + chunkSize := len(currentChunk.levelIDToPosition) + if chunkSize >= currentChunk.config.minimumNumberOfNodesToBeChunk { + if !currentChunk.built { + currentChunk.built = true + currentChunk.positionToChunksID = make([][]int, chunkSize) + currentChunksID := make([]int, 1) + currentChunk.assignChunksIDToNodesInTheKaryTreeBuilt(0, chunkSize-1, ¤tChunksID) + } + position := currentChunk.levelIDToPosition[id] + newLevelsID := currentChunk.positionToChunksID[position] + for _, id := range newLevelsID { + newLabel.PushBack(SUPER+name, id) + } + } + } + fmt.Fprintf(&labelAsAString, "%d/", id) + newLabel.PushBack(name, id) + } + currentNode.label = newLabel + } +} diff --git a/gapis/resolve/dependencygraph2/graph_visualization/graph_algorithms_test.go b/gapis/resolve/dependencygraph2/graph_visualization/graph_algorithms_test.go index e55728158e..8aa1f51ec2 100644 --- a/gapis/resolve/dependencygraph2/graph_visualization/graph_algorithms_test.go +++ b/gapis/resolve/dependencygraph2/graph_visualization/graph_algorithms_test.go @@ -15,9 +15,26 @@ package graph_visualization import ( + "github.com/google/gapid/gapis/api" + "reflect" "testing" ) +const ( + VK_BEGIN_COMMAND_BUFFER = "vkBeginCommandBuffer" + VK_CMD_BEGIN_RENDER_PASS = "vkCmdBeginRenderPass" + VK_CMD_NEXT_SUBPASS = "vkCmdNextSubpass" + VK_COMMAND_BUFFER = "vkCommandBuffer" + VK_RENDER_PASS = "vkRenderPass" + VK_SUBPASS = "vkSubpass" + VK_END_COMMAND_BUFFER = "vkEndCommandBuffer" + VK_CMD_END_RENDER_PASS = "vkCmdEndRenderPass" + COMMAND_BUFFER = "commandBuffer" + VK_CMD_DEBUG_MARKER_BEGIN = "vkCmdDebugMarkerBeginEXT" + VK_CMD_DEBUG_MARKER_END = "vkCmdDebugMarkerEndEXT" + VK_CMD_DEBUG_MARKER = "vkCmdDebugMarker" +) + func TestGetIdInStronglyConnectedComponents(t *testing.T) { currentGraph := createGraph(0) @@ -122,3 +139,117 @@ func TestBfs(t *testing.T) { } } + +func TestMakeChunks(t *testing.T) { + numberOfNodes := 30 + currentGraph := createGraph(numberOfNodes) + auxiliarCommands := []string{ + "SetBarrier", + "DrawIndex", + "SetScissor", + "SetIndexForDraw", + } + labels := []*api.Label{ + &api.Label{LevelsName: []string{auxiliarCommands[0]}, LevelsID: []int{0}}, + &api.Label{LevelsName: []string{COMMAND_BUFFER, VK_BEGIN_COMMAND_BUFFER}, LevelsID: []int{1, 1}}, + &api.Label{LevelsName: []string{COMMAND_BUFFER, VK_RENDER_PASS, VK_CMD_BEGIN_RENDER_PASS}, LevelsID: []int{1, 1, 2}}, + &api.Label{LevelsName: []string{COMMAND_BUFFER, VK_RENDER_PASS, VK_SUBPASS, auxiliarCommands[1]}, LevelsID: []int{1, 1, 1, 3}}, + &api.Label{LevelsName: []string{COMMAND_BUFFER, VK_RENDER_PASS, VK_SUBPASS, auxiliarCommands[0]}, LevelsID: []int{1, 1, 1, 4}}, + &api.Label{LevelsName: []string{COMMAND_BUFFER, VK_RENDER_PASS, VK_SUBPASS, auxiliarCommands[0]}, LevelsID: []int{1, 1, 2, 5}}, + &api.Label{LevelsName: []string{COMMAND_BUFFER, VK_RENDER_PASS, VK_SUBPASS, auxiliarCommands[0]}, LevelsID: []int{1, 1, 2, 6}}, + &api.Label{LevelsName: []string{COMMAND_BUFFER, VK_RENDER_PASS, VK_SUBPASS, auxiliarCommands[0]}, LevelsID: []int{1, 1, 2, 7}}, + &api.Label{LevelsName: []string{COMMAND_BUFFER, VK_RENDER_PASS, VK_SUBPASS, auxiliarCommands[0]}, LevelsID: []int{1, 1, 2, 8}}, + &api.Label{LevelsName: []string{COMMAND_BUFFER, VK_RENDER_PASS, VK_SUBPASS, auxiliarCommands[0]}, LevelsID: []int{1, 1, 2, 9}}, + &api.Label{LevelsName: []string{COMMAND_BUFFER, VK_RENDER_PASS, VK_SUBPASS, auxiliarCommands[0]}, LevelsID: []int{1, 1, 2, 10}}, + &api.Label{LevelsName: []string{COMMAND_BUFFER, VK_RENDER_PASS, VK_SUBPASS, auxiliarCommands[0]}, LevelsID: []int{1, 1, 2, 11}}, + &api.Label{LevelsName: []string{COMMAND_BUFFER, VK_RENDER_PASS, VK_SUBPASS, auxiliarCommands[0]}, LevelsID: []int{1, 1, 2, 12}}, + &api.Label{LevelsName: []string{COMMAND_BUFFER, VK_RENDER_PASS, VK_SUBPASS, auxiliarCommands[0]}, LevelsID: []int{1, 1, 2, 13}}, + &api.Label{LevelsName: []string{COMMAND_BUFFER, VK_RENDER_PASS, VK_SUBPASS, auxiliarCommands[0]}, LevelsID: []int{1, 1, 2, 14}}, + &api.Label{LevelsName: []string{auxiliarCommands[0]}, LevelsID: []int{15}}, + &api.Label{LevelsName: []string{auxiliarCommands[0]}, LevelsID: []int{16}}, + &api.Label{LevelsName: []string{auxiliarCommands[0]}, LevelsID: []int{17}}, + &api.Label{LevelsName: []string{auxiliarCommands[0]}, LevelsID: []int{18}}, + &api.Label{LevelsName: []string{auxiliarCommands[0]}, LevelsID: []int{19}}, + &api.Label{LevelsName: []string{auxiliarCommands[0]}, LevelsID: []int{20}}, + &api.Label{LevelsName: []string{auxiliarCommands[0]}, LevelsID: []int{21}}, + &api.Label{LevelsName: []string{COMMAND_BUFFER, VK_RENDER_PASS, VK_SUBPASS, auxiliarCommands[0]}, LevelsID: []int{1, 2, 1, 22}}, + &api.Label{LevelsName: []string{COMMAND_BUFFER, VK_RENDER_PASS, VK_SUBPASS, auxiliarCommands[0]}, LevelsID: []int{1, 2, 2, 23}}, + &api.Label{LevelsName: []string{COMMAND_BUFFER, VK_RENDER_PASS, VK_SUBPASS, auxiliarCommands[0]}, LevelsID: []int{1, 2, 3, 24}}, + &api.Label{LevelsName: []string{COMMAND_BUFFER, VK_RENDER_PASS, VK_SUBPASS, auxiliarCommands[0]}, LevelsID: []int{1, 2, 4, 25}}, + &api.Label{LevelsName: []string{COMMAND_BUFFER, VK_RENDER_PASS, VK_SUBPASS, auxiliarCommands[0]}, LevelsID: []int{1, 2, 5, 26}}, + &api.Label{LevelsName: []string{COMMAND_BUFFER, VK_RENDER_PASS, VK_SUBPASS, auxiliarCommands[0]}, LevelsID: []int{1, 2, 6, 27}}, + &api.Label{LevelsName: []string{auxiliarCommands[0]}, LevelsID: []int{28}}, + &api.Label{LevelsName: []string{auxiliarCommands[0]}, LevelsID: []int{29}}, + } + nodes := []*node{} + for i := 0; i < numberOfNodes; i++ { + currentNode := currentGraph.nodeIdToNode[i+1] + currentNode.label = labels[i] + nodes = append(nodes, currentNode) + } + + config := chunkConfig{ + maximumNumberOfNodesByLevel: 5, + minimumNumberOfNodesToBeChunk: 2, + } + currentGraph.makeChunks(config) + + wantedLabels := []*api.Label{ + &api.Label{LevelsName: []string{SUPER + auxiliarCommands[0], SUPER + auxiliarCommands[0], auxiliarCommands[0]}, LevelsID: []int{0, 1, 0}}, + &api.Label{LevelsName: []string{COMMAND_BUFFER, VK_BEGIN_COMMAND_BUFFER}, LevelsID: []int{1, 1}}, + &api.Label{LevelsName: []string{COMMAND_BUFFER, SUPER + VK_RENDER_PASS, VK_RENDER_PASS, VK_CMD_BEGIN_RENDER_PASS}, LevelsID: []int{1, 0, 1, 2}}, + &api.Label{LevelsName: []string{COMMAND_BUFFER, SUPER + VK_RENDER_PASS, VK_RENDER_PASS, SUPER + VK_SUBPASS, VK_SUBPASS, auxiliarCommands[1]}, + LevelsID: []int{1, 0, 1, 0, 1, 3}}, + &api.Label{LevelsName: []string{COMMAND_BUFFER, SUPER + VK_RENDER_PASS, VK_RENDER_PASS, SUPER + VK_SUBPASS, VK_SUBPASS, auxiliarCommands[0]}, + LevelsID: []int{1, 0, 1, 0, 1, 4}}, + &api.Label{LevelsName: []string{COMMAND_BUFFER, SUPER + VK_RENDER_PASS, VK_RENDER_PASS, SUPER + VK_SUBPASS, VK_SUBPASS, SUPER + auxiliarCommands[0], + SUPER + auxiliarCommands[0], auxiliarCommands[0]}, LevelsID: []int{1, 0, 1, 0, 2, 0, 1, 5}}, + &api.Label{LevelsName: []string{COMMAND_BUFFER, SUPER + VK_RENDER_PASS, VK_RENDER_PASS, SUPER + VK_SUBPASS, VK_SUBPASS, SUPER + auxiliarCommands[0], + SUPER + auxiliarCommands[0], auxiliarCommands[0]}, LevelsID: []int{1, 0, 1, 0, 2, 0, 1, 6}}, + &api.Label{LevelsName: []string{COMMAND_BUFFER, SUPER + VK_RENDER_PASS, VK_RENDER_PASS, SUPER + VK_SUBPASS, VK_SUBPASS, SUPER + auxiliarCommands[0], + SUPER + auxiliarCommands[0], auxiliarCommands[0]}, LevelsID: []int{1, 0, 1, 0, 2, 0, 2, 7}}, + &api.Label{LevelsName: []string{COMMAND_BUFFER, SUPER + VK_RENDER_PASS, VK_RENDER_PASS, SUPER + VK_SUBPASS, VK_SUBPASS, SUPER + auxiliarCommands[0], + SUPER + auxiliarCommands[0], auxiliarCommands[0]}, LevelsID: []int{1, 0, 1, 0, 2, 0, 2, 8}}, + &api.Label{LevelsName: []string{COMMAND_BUFFER, SUPER + VK_RENDER_PASS, VK_RENDER_PASS, SUPER + VK_SUBPASS, VK_SUBPASS, SUPER + auxiliarCommands[0], + SUPER + auxiliarCommands[0], auxiliarCommands[0]}, LevelsID: []int{1, 0, 1, 0, 2, 0, 3, 9}}, + &api.Label{LevelsName: []string{COMMAND_BUFFER, SUPER + VK_RENDER_PASS, VK_RENDER_PASS, SUPER + VK_SUBPASS, VK_SUBPASS, SUPER + auxiliarCommands[0], + SUPER + auxiliarCommands[0], auxiliarCommands[0]}, LevelsID: []int{1, 0, 1, 0, 2, 0, 3, 10}}, + &api.Label{LevelsName: []string{COMMAND_BUFFER, SUPER + VK_RENDER_PASS, VK_RENDER_PASS, SUPER + VK_SUBPASS, VK_SUBPASS, SUPER + auxiliarCommands[0], + SUPER + auxiliarCommands[0], auxiliarCommands[0]}, LevelsID: []int{1, 0, 1, 0, 2, 0, 4, 11}}, + &api.Label{LevelsName: []string{COMMAND_BUFFER, SUPER + VK_RENDER_PASS, VK_RENDER_PASS, SUPER + VK_SUBPASS, VK_SUBPASS, SUPER + auxiliarCommands[0], + SUPER + auxiliarCommands[0], auxiliarCommands[0]}, LevelsID: []int{1, 0, 1, 0, 2, 0, 4, 12}}, + &api.Label{LevelsName: []string{COMMAND_BUFFER, SUPER + VK_RENDER_PASS, VK_RENDER_PASS, SUPER + VK_SUBPASS, VK_SUBPASS, SUPER + auxiliarCommands[0], + SUPER + auxiliarCommands[0], auxiliarCommands[0]}, LevelsID: []int{1, 0, 1, 0, 2, 0, 5, 13}}, + &api.Label{LevelsName: []string{COMMAND_BUFFER, SUPER + VK_RENDER_PASS, VK_RENDER_PASS, SUPER + VK_SUBPASS, VK_SUBPASS, SUPER + auxiliarCommands[0], + SUPER + auxiliarCommands[0], auxiliarCommands[0]}, LevelsID: []int{1, 0, 1, 0, 2, 0, 5, 14}}, + &api.Label{LevelsName: []string{SUPER + auxiliarCommands[0], SUPER + auxiliarCommands[0], auxiliarCommands[0]}, LevelsID: []int{0, 1, 15}}, + &api.Label{LevelsName: []string{SUPER + auxiliarCommands[0], SUPER + auxiliarCommands[0], auxiliarCommands[0]}, LevelsID: []int{0, 2, 16}}, + &api.Label{LevelsName: []string{SUPER + auxiliarCommands[0], SUPER + auxiliarCommands[0], auxiliarCommands[0]}, LevelsID: []int{0, 2, 17}}, + &api.Label{LevelsName: []string{SUPER + auxiliarCommands[0], SUPER + auxiliarCommands[0], auxiliarCommands[0]}, LevelsID: []int{0, 3, 18}}, + &api.Label{LevelsName: []string{SUPER + auxiliarCommands[0], SUPER + auxiliarCommands[0], auxiliarCommands[0]}, LevelsID: []int{0, 3, 19}}, + &api.Label{LevelsName: []string{SUPER + auxiliarCommands[0], SUPER + auxiliarCommands[0], auxiliarCommands[0]}, LevelsID: []int{0, 4, 20}}, + &api.Label{LevelsName: []string{SUPER + auxiliarCommands[0], SUPER + auxiliarCommands[0], auxiliarCommands[0]}, LevelsID: []int{0, 4, 21}}, + &api.Label{LevelsName: []string{COMMAND_BUFFER, SUPER + VK_RENDER_PASS, VK_RENDER_PASS, SUPER + VK_SUBPASS, SUPER + VK_SUBPASS, VK_SUBPASS, + auxiliarCommands[0]}, LevelsID: []int{1, 0, 2, 0, 1, 1, 22}}, + &api.Label{LevelsName: []string{COMMAND_BUFFER, SUPER + VK_RENDER_PASS, VK_RENDER_PASS, SUPER + VK_SUBPASS, SUPER + VK_SUBPASS, VK_SUBPASS, + auxiliarCommands[0]}, LevelsID: []int{1, 0, 2, 0, 1, 2, 23}}, + &api.Label{LevelsName: []string{COMMAND_BUFFER, SUPER + VK_RENDER_PASS, VK_RENDER_PASS, SUPER + VK_SUBPASS, SUPER + VK_SUBPASS, VK_SUBPASS, + auxiliarCommands[0]}, LevelsID: []int{1, 0, 2, 0, 2, 3, 24}}, + &api.Label{LevelsName: []string{COMMAND_BUFFER, SUPER + VK_RENDER_PASS, VK_RENDER_PASS, SUPER + VK_SUBPASS, SUPER + VK_SUBPASS, VK_SUBPASS, + auxiliarCommands[0]}, LevelsID: []int{1, 0, 2, 0, 2, 4, 25}}, + &api.Label{LevelsName: []string{COMMAND_BUFFER, SUPER + VK_RENDER_PASS, VK_RENDER_PASS, SUPER + VK_SUBPASS, SUPER + VK_SUBPASS, VK_SUBPASS, + auxiliarCommands[0]}, LevelsID: []int{1, 0, 2, 0, 3, 5, 26}}, + &api.Label{LevelsName: []string{COMMAND_BUFFER, SUPER + VK_RENDER_PASS, VK_RENDER_PASS, SUPER + VK_SUBPASS, SUPER + VK_SUBPASS, VK_SUBPASS, + auxiliarCommands[0]}, LevelsID: []int{1, 0, 2, 0, 3, 6, 27}}, + &api.Label{LevelsName: []string{SUPER + auxiliarCommands[0], SUPER + auxiliarCommands[0], auxiliarCommands[0]}, LevelsID: []int{0, 5, 28}}, + &api.Label{LevelsName: []string{SUPER + auxiliarCommands[0], SUPER + auxiliarCommands[0], auxiliarCommands[0]}, LevelsID: []int{0, 5, 29}}, + } + for i := range wantedLabels { + if !reflect.DeepEqual(wantedLabels[i], nodes[i].label) { + t.Errorf("The label for the node with id %d is different\n", i) + t.Errorf("Wanted %v\n", wantedLabels[i]) + t.Errorf("Obtained %v\n", nodes[i].label) + } + } + +} diff --git a/gapis/resolve/dependencygraph2/graph_visualization/graph_output.go b/gapis/resolve/dependencygraph2/graph_visualization/graph_output.go index 14eab759df..80085845a2 100644 --- a/gapis/resolve/dependencygraph2/graph_visualization/graph_output.go +++ b/gapis/resolve/dependencygraph2/graph_visualization/graph_output.go @@ -32,7 +32,7 @@ func (g *graph) writeEdgesInDotFormat(output *bytes.Buffer) { func (g *graph) writeNodesInDotFormat(output *bytes.Buffer) { nodes := g.getSortedNodes() for _, currentNode := range nodes { - fmt.Fprintf(output, "%d[label=%s];\n", currentNode.id, currentNode.label) + fmt.Fprintf(output, "%d[label=%s];\n", currentNode.id, currentNode.label.GetCommandName()) } } @@ -57,6 +57,9 @@ func (g *graph) getGraphInPbtxtFormat() []byte { for _, neighbour := range neighbours { output.WriteString("input: \"" + neighbour.label.GetLabelAsAString() + "\"\n") } + if currentNode.color != "" { + output.WriteString("device: \"" + currentNode.color + "\"\n") + } output.WriteString("attr {\n") output.WriteString("key: \"" + currentNode.attributes + "\"\n") output.WriteString("}\n") diff --git a/gapis/resolve/dependencygraph2/graph_visualization/graph_structure.go b/gapis/resolve/dependencygraph2/graph_visualization/graph_structure.go index e38eedb31d..9900ce6dcf 100644 --- a/gapis/resolve/dependencygraph2/graph_visualization/graph_structure.go +++ b/gapis/resolve/dependencygraph2/graph_visualization/graph_structure.go @@ -29,6 +29,7 @@ type node struct { attributes string isEndOfFrame bool subCommandNodes []*node + color string } type edge struct { diff --git a/gapis/resolve/dependencygraph2/graph_visualization/graph_visualization.go b/gapis/resolve/dependencygraph2/graph_visualization/graph_visualization.go index 26ac05d2ed..a0f3d296ea 100644 --- a/gapis/resolve/dependencygraph2/graph_visualization/graph_visualization.go +++ b/gapis/resolve/dependencygraph2/graph_visualization/graph_visualization.go @@ -124,8 +124,16 @@ func GetGraphVisualizationFromCapture(ctx context.Context, p *path.Capture, form if err != nil { return []byte{}, err } + currentGraph.assignColorToNodes() currentGraph.joinNodesByFrame() - currentGraph.joinNodesWithZeroDegree() + currentGraph.joinNodesThatDoNotBelongToAnyFrame() + + currentChunkConfig := chunkConfig{ + maximumNumberOfNodesByLevel: 5, + minimumNumberOfNodesToBeChunk: 2, + } + currentGraph.makeChunks(currentChunkConfig) + output := []byte{} if format == service.GraphFormat_PBTXT { output = currentGraph.getGraphInPbtxtFormat()