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..6ee22a916d 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 from Label of the last debug_marker_begin command 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 and avoid adding + // 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..e83da0c96e 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,138 @@ 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 levelID to a position in the range of nodes ID [0, 1, 2, ...] + levelIDToPosition map[int]int + + // positionToChunksID are the Chunks ID obtained in the K-ary tree builded for the + // range of nodes ID [0, 1, 2, ...] + positionToChunksID [][]int + + // builded checks if the K-ary tree was builded for chunk + builded 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 +} + +// assignChunksIDToNodesInTheKaryTreeBuilded builds a K-ary tree for a range of +// nodes ID = [left, left+1, left+2, ..... ,right] (chunk), then it assigns the +// chunks ID to nodes ID obtained from the K-ary tree. +func (c *chunk) assignChunksIDToNodesInTheKaryTreeBuilded(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: create 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.assignChunksIDToNodesInTheKaryTreeBuilded(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 every set_of_values in nodes from implicit tree builded 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.builded { + currentChunk.builded = true + currentChunk.positionToChunksID = make([][]int, chunkSize) + currentChunksID := make([]int, 1) + currentChunk.assignChunksIDToNodesInTheKaryTreeBuilded(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()