Skip to content

Commit

Permalink
Graph Visualization: Added a 'Label' structure, debug marks , order of
Browse files Browse the repository at this point in the history
commandBuffer and reestructuration of the code.

'Label' Structure: It improves the time and space complexity for algorithms
on the graph and the output format.

Debug markers: they are added whenever do not break any previous hierarchy
already defined. It follows the idea of balance parenthesis.

Reestructuration of the code: This is divided in graph_algorithms,
graph_structure, graph_output and graph_visualization to better understanding
and future work.
  • Loading branch information
elviscapiaq committed Jan 14, 2019
1 parent 64b7de0 commit 5f232a1
Show file tree
Hide file tree
Showing 9 changed files with 591 additions and 332 deletions.
70 changes: 68 additions & 2 deletions gapis/api/graph_visualization.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,72 @@

package api

import (
"bytes"
"fmt"
)

type Label struct {
LevelsName []string
LevelsID []int
}

func (label *Label) GetSize() int {
return len(label.LevelsName)
}

func (label *Label) PushBack(name string, id int) {
label.LevelsName = append(label.LevelsName, name)
label.LevelsID = append(label.LevelsID, id)
}
func (label *Label) PushFront(name string, id int) {
newLabel := &Label{LevelsName: []string{name}, LevelsID: []int{id}}
newLabel.PushBackLabel(label)
label.LevelsName = newLabel.LevelsName
label.LevelsID = newLabel.LevelsID
}

func (label *Label) PushBackLabel(labelToPush *Label) {
label.LevelsName = append(label.LevelsName, labelToPush.LevelsName...)
label.LevelsID = append(label.LevelsID, labelToPush.LevelsID...)
}

func (label *Label) Insert(level int, name string, id int) {
if level < len(label.LevelsName) {
label.LevelsName = append(label.LevelsName, "")
label.LevelsID = append(label.LevelsID, 0)
copy(label.LevelsName[level+1:], label.LevelsName[level:])
copy(label.LevelsID[level+1:], label.LevelsID[level:])
label.LevelsName[level] = name
label.LevelsID[level] = id
}
}

func (label *Label) GetCommandName() string {
if len(label.LevelsName) > 0 {
return label.LevelsName[len(label.LevelsName)-1]
}
return ""
}
func (label *Label) GetCommandId() int {
if len(label.LevelsID) > 0 {
return label.LevelsID[len(label.LevelsID)-1]
}
return 0
}

func (label *Label) GetLabelAsAString() string {
var output bytes.Buffer
for i := range label.LevelsID {
output.WriteString(label.LevelsName[i])
fmt.Fprintf(&output, "%d", label.LevelsID[i])
if i+1 < len(label.LevelsID) {
output.WriteString("/")
}
}
return output.String()
}

type Hierarchy struct {
LevelsID []int
}
Expand Down Expand Up @@ -70,7 +136,7 @@ type GraphVisualizationAPI interface {
}

type GraphVisualizationBuilder interface {
GetCommandLabel(command Cmd, commandNodeId uint64) string
GetCommandLabel(command Cmd, cmdId uint64) *Label

GetSubCommandLabel(index SubCmdIdx, commandName string, subCommandName string) string
GetSubCommandLabel(index SubCmdIdx, commandName string, cmdId uint64, subCommandName string) *Label
}
164 changes: 121 additions & 43 deletions gapis/api/vulkan/graph_visualization.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
package vulkan

import (
"bytes"
"fmt"
"github.com/google/gapid/gapis/api"
)
Expand All @@ -26,15 +27,18 @@ var (
)

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_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"
)

var (
Expand All @@ -43,8 +47,13 @@ var (
)

type labelForVulkanCommands struct {
labelToHierarchy map[string]*api.Hierarchy
subCommandIndexNameToHierarchyLabel map[string]string
labelAsAStringToHierarchy map[string]*api.Hierarchy
subCommandIndexNameToHierarchyLabel map[string]*api.Label
commandBufferIdToHierarchy map[VkCommandBuffer]*api.Hierarchy
commandBufferIdToOrderNumber map[VkCommandBuffer]int
labelsInsideDebugMarkers []*api.Label
positionOfDebugMarkersBegin []int
numberOfDebugMarker int
}

func getCommandHierarchyNames() *api.HierarchyNames {
Expand All @@ -66,60 +75,127 @@ func getSubCommandHierarchyNames() *api.HierarchyNames {
return subCommandHierarchyNames
}

func getCommandBuffer(command api.Cmd) string {
func getMaxCommonPrefix(label1 *api.Label, label2 *api.Label) int {
size := len(label1.LevelsID)
if len(label2.LevelsID) < size {
size = len(label2.LevelsID)
}
for i := 0; i < size; i++ {
if label1.LevelsName[i] != label2.LevelsName[i] || label1.LevelsID[i] != label2.LevelsID[i] {
return i
}
}
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 labelOfLastDebugMarkerBegin.GetSize() != currentLabel.GetSize() {
builder.positionOfDebugMarkersBegin = builder.positionOfDebugMarkersBegin[:0]
}
}
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 labelOfLastDebugMarkerBegin.GetSize() != currentLabel.GetSize() {
builder.positionOfDebugMarkersBegin = builder.positionOfDebugMarkersBegin[:0]

} 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 labelOfLastDebugMarkerBegin.GetSize() != currentLabel.GetSize() {
builder.positionOfDebugMarkersBegin = builder.positionOfDebugMarkersBegin[:0]
} else {
builder.labelsInsideDebugMarkers = append(builder.labelsInsideDebugMarkers, currentLabel)
}
}
}

func getCommandBufferId(command api.Cmd) (VkCommandBuffer, bool) {
parameters := command.CmdParams()
for _, parameter := range parameters {
if parameter.Name == COMMAND_BUFFER {
commandBuffer := fmt.Sprintf("%s_%d", parameter.Name, parameter.Get())
return commandBuffer
return parameter.Get().(VkCommandBuffer), true
}
}
return ""
return 0, false
}

func (builder *labelForVulkanCommands) GetCommandLabel(command api.Cmd, commandNodeId uint64) string {
func (builder *labelForVulkanCommands) GetCommandLabel(command api.Cmd, cmdId uint64) *api.Label {
label := &api.Label{}
commandName := command.CmdName()
label := ""
if commandBuffer := getCommandBuffer(command); commandBuffer != "" {
if _, ok := builder.labelToHierarchy[commandBuffer]; !ok {
builder.labelToHierarchy[commandBuffer] = &api.Hierarchy{}
if commandBufferId, ok := getCommandBufferId(command); ok {
if _, ok := builder.commandBufferIdToHierarchy[commandBufferId]; !ok {
builder.commandBufferIdToHierarchy[commandBufferId] = &api.Hierarchy{}
builder.commandBufferIdToOrderNumber[commandBufferId] = len(builder.commandBufferIdToOrderNumber) + 1
}
hierarchy := builder.labelToHierarchy[commandBuffer]
label += commandBuffer + "/"
label += getLabelFromHierarchy(commandName, commandHierarchyNames, hierarchy)
label += fmt.Sprintf("%s_%d", commandName, commandNodeId)
hierarchy := builder.commandBufferIdToHierarchy[commandBufferId]
label.PushBack(COMMAND_BUFFER, builder.commandBufferIdToOrderNumber[commandBufferId])
label.PushBackLabel(getLabelFromHierarchy(commandName, commandHierarchyNames, hierarchy))
label.PushBack(commandName, int(cmdId))
} else {
label += fmt.Sprintf("%s_%d", commandName, commandNodeId)
label.PushBack(commandName, int(cmdId))
}
checkDebugMarkers(builder, label)
return label
}

func (builder *labelForVulkanCommands) GetSubCommandLabel(index api.SubCmdIdx, commandName, subCommandName string) string {
label := commandName
subCommandIndexName := commandName
func (builder *labelForVulkanCommands) GetSubCommandLabel(index api.SubCmdIdx, commandName string, cmdId uint64, subCommandName string) *api.Label {
label := &api.Label{}
label.PushBack(commandName, int(cmdId))
var subCommandIndexName bytes.Buffer
fmt.Fprintf(&subCommandIndexName, "%s_%d", commandName, cmdId)
for i := 1; i < len(index); i++ {
subCommandIndexName += fmt.Sprintf("/%d", index[i])
fmt.Fprintf(&subCommandIndexName, "/%d", index[i])
if i+1 < len(index) {
if hierarchyLabel, ok := builder.subCommandIndexNameToHierarchyLabel[subCommandIndexName]; ok {
label += "/" + hierarchyLabel
if hierarchyLabel, ok := builder.subCommandIndexNameToHierarchyLabel[subCommandIndexName.String()]; ok {
label.PushBackLabel(hierarchyLabel)
} else {
label += fmt.Sprintf("/%d", index[i])
label.PushBack("", int(index[i]))
}
}
}
if _, ok := builder.labelToHierarchy[label]; !ok {
builder.labelToHierarchy[label] = &api.Hierarchy{}
temporalLabelAsAString := label.GetLabelAsAString()
if _, ok := builder.labelAsAStringToHierarchy[temporalLabelAsAString]; !ok {
builder.labelAsAStringToHierarchy[temporalLabelAsAString] = &api.Hierarchy{}
}
hierarchy := builder.labelToHierarchy[label]
hierarchy := builder.labelAsAStringToHierarchy[temporalLabelAsAString]
labelFromHierarchy := getLabelFromHierarchy(subCommandName, subCommandHierarchyNames, hierarchy)
labelFromHierarchy += fmt.Sprintf("%s_%d", subCommandName, index[len(index)-1])
builder.subCommandIndexNameToHierarchyLabel[subCommandIndexName] = labelFromHierarchy
labelFromHierarchy.PushBack(subCommandName, int(index[len(index)-1]))
builder.subCommandIndexNameToHierarchyLabel[subCommandIndexName.String()] = labelFromHierarchy

label += "/" + labelFromHierarchy
label.PushBackLabel(labelFromHierarchy)
checkDebugMarkers(builder, label)
return label
}

func getLabelFromHierarchy(name string, hierarchyNames *api.HierarchyNames, hierarchy *api.Hierarchy) string {
func getLabelFromHierarchy(name string, hierarchyNames *api.HierarchyNames, hierarchy *api.Hierarchy) *api.Label {
isEndCommand := false
if level, ok := hierarchyNames.BeginNameToLevel[name]; ok {
hierarchy.PushBackToResize(level + 1)
Expand All @@ -129,9 +205,9 @@ func getLabelFromHierarchy(name string, hierarchyNames *api.HierarchyNames, hier
isEndCommand = true
}

label := ""
label := &api.Label{}
for level := 1; level < hierarchy.GetSize(); level++ {
label += fmt.Sprintf("%d_%s/", hierarchy.GetID(level), hierarchyNames.GetName(level))
label.PushBack(hierarchyNames.GetName(level), hierarchy.GetID(level))
}

if level, ok := hierarchyNames.BeginNameToLevel[name]; ok && name == VK_CMD_BEGIN_RENDER_PASS {
Expand All @@ -147,7 +223,9 @@ func getLabelFromHierarchy(name string, hierarchyNames *api.HierarchyNames, hier

func (API) GetGraphVisualizationBuilder() api.GraphVisualizationBuilder {
return &labelForVulkanCommands{
labelToHierarchy: map[string]*api.Hierarchy{},
subCommandIndexNameToHierarchyLabel: map[string]string{},
labelAsAStringToHierarchy: map[string]*api.Hierarchy{},
subCommandIndexNameToHierarchyLabel: map[string]*api.Label{},
commandBufferIdToHierarchy: map[VkCommandBuffer]*api.Hierarchy{},
commandBufferIdToOrderNumber: map[VkCommandBuffer]int{},
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test")
go_library(
name = "go_default_library",
srcs = [
"graph_algorithms.go",
"graph_output.go",
"graph_structure.go",
"graph_visualization.go",
],
Expand All @@ -32,6 +34,10 @@ go_library(

go_test(
name = "go_default_test",
srcs = ["graph_structure_test.go"],
srcs = [
"graph_algorithms_test.go",
"graph_structure_test.go",
],
embed = [":go_default_library"],
deps = ["//gapis/api:go_default_library"],
)
Loading

0 comments on commit 5f232a1

Please sign in to comment.