test: custom_results: graphics: Performance testing protobufs.

Protobufs to allow individual developers to record results of traces
that are not executing actual tests on non-standard builds, including
non Chrome OS environments like Crouton or from Linux Desktops.

Protobufs can be written out to bigquery for further analysis.

Messages exist to model
- Machine is gathering the result.
- Package identifies a particular version of software running.
- Result is the actual result allowing multiple metrics of interest.
- SoftwareConfig is the set of software running on a device for both
  Chrome OS and Debian based systems.
- SoftwareOverridesConfig is the set of software that was overriden
  from the standard system software for a particular run.
- Trace is general information about an apitrace trace.

BUG=b:152987133
TEST=bqschemauploader, generate data, post results, query via plx

Change-Id: Ibf8d5276c471e2204ac65b9884f10a38821e150e
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/infra/proto/+/2137477
Tested-by: David Riley <davidriley@chromium.org>
Reviewed-by: Sean Abraham <seanabraham@chromium.org>
Commit-Queue: David Riley <davidriley@chromium.org>
diff --git a/go/test/custom_results/graphics/machine.pb.go b/go/test/custom_results/graphics/machine.pb.go
new file mode 100644
index 0000000..3ef6fc2
--- /dev/null
+++ b/go/test/custom_results/graphics/machine.pb.go
@@ -0,0 +1,117 @@
+// Code generated by protoc-gen-go. DO NOT EDIT.
+// source: test/custom_results/graphics/machine.proto
+
+package graphics
+
+import (
+	fmt "fmt"
+	proto "github.com/golang/protobuf/proto"
+	timestamp "github.com/golang/protobuf/ptypes/timestamp"
+	math "math"
+)
+
+// Reference imports to suppress errors if they are not otherwise used.
+var _ = proto.Marshal
+var _ = fmt.Errorf
+var _ = math.Inf
+
+// This is a compile-time assertion to ensure that this generated file
+// is compatible with the proto package it is being compiled against.
+// A compilation error at this line likely means your copy of the
+// proto package needs to be updated.
+const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package
+
+// Next Tag: 5
+type Machine struct {
+	// Global unique machine identifier.
+	Name       *MachineId           `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
+	CreateTime *timestamp.Timestamp `protobuf:"bytes,2,opt,name=create_time,json=createTime,proto3" json:"create_time,omitempty"`
+	// Identity of owner.
+	Owner string `protobuf:"bytes,3,opt,name=owner,proto3" json:"owner,omitempty"`
+	// Hardware identification.
+	Hwid                 string   `protobuf:"bytes,4,opt,name=hwid,proto3" json:"hwid,omitempty"`
+	XXX_NoUnkeyedLiteral struct{} `json:"-"`
+	XXX_unrecognized     []byte   `json:"-"`
+	XXX_sizecache        int32    `json:"-"`
+}
+
+func (m *Machine) Reset()         { *m = Machine{} }
+func (m *Machine) String() string { return proto.CompactTextString(m) }
+func (*Machine) ProtoMessage()    {}
+func (*Machine) Descriptor() ([]byte, []int) {
+	return fileDescriptor_53eecb40097bb418, []int{0}
+}
+
+func (m *Machine) XXX_Unmarshal(b []byte) error {
+	return xxx_messageInfo_Machine.Unmarshal(m, b)
+}
+func (m *Machine) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	return xxx_messageInfo_Machine.Marshal(b, m, deterministic)
+}
+func (m *Machine) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_Machine.Merge(m, src)
+}
+func (m *Machine) XXX_Size() int {
+	return xxx_messageInfo_Machine.Size(m)
+}
+func (m *Machine) XXX_DiscardUnknown() {
+	xxx_messageInfo_Machine.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_Machine proto.InternalMessageInfo
+
+func (m *Machine) GetName() *MachineId {
+	if m != nil {
+		return m.Name
+	}
+	return nil
+}
+
+func (m *Machine) GetCreateTime() *timestamp.Timestamp {
+	if m != nil {
+		return m.CreateTime
+	}
+	return nil
+}
+
+func (m *Machine) GetOwner() string {
+	if m != nil {
+		return m.Owner
+	}
+	return ""
+}
+
+func (m *Machine) GetHwid() string {
+	if m != nil {
+		return m.Hwid
+	}
+	return ""
+}
+
+func init() {
+	proto.RegisterType((*Machine)(nil), "test.custom_results.graphics.Machine")
+}
+
+func init() {
+	proto.RegisterFile("test/custom_results/graphics/machine.proto", fileDescriptor_53eecb40097bb418)
+}
+
+var fileDescriptor_53eecb40097bb418 = []byte{
+	// 250 bytes of a gzipped FileDescriptorProto
+	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x90, 0x31, 0x4b, 0x34, 0x31,
+	0x10, 0x86, 0xd9, 0xef, 0x5b, 0x15, 0x73, 0x5d, 0xb0, 0x58, 0x16, 0xc1, 0xc3, 0xc6, 0x43, 0x70,
+	0x06, 0xb4, 0xbc, 0xce, 0x42, 0xb4, 0xb0, 0x59, 0xac, 0x6c, 0x96, 0x5c, 0x76, 0x2e, 0x1b, 0xb8,
+	0xec, 0x2c, 0x49, 0x96, 0xfb, 0x55, 0xfe, 0x47, 0xd9, 0xc4, 0x2d, 0x6c, 0x0e, 0xbb, 0xcc, 0xcb,
+	0xf3, 0x66, 0x1e, 0x46, 0xdc, 0x47, 0x0a, 0x11, 0xf5, 0x14, 0x22, 0xbb, 0xd6, 0x53, 0x98, 0x0e,
+	0x31, 0xa0, 0xf1, 0x6a, 0xec, 0xad, 0x0e, 0xe8, 0x94, 0xee, 0xed, 0x40, 0x30, 0x7a, 0x8e, 0x2c,
+	0xaf, 0x67, 0x16, 0x7e, 0xb3, 0xb0, 0xb0, 0xf5, 0x8d, 0x61, 0x36, 0x07, 0xc2, 0xc4, 0xee, 0xa6,
+	0x3d, 0x46, 0xeb, 0x28, 0x44, 0xe5, 0xc6, 0x5c, 0xaf, 0x1f, 0xfe, 0xb2, 0xaa, 0xb5, 0x5d, 0xc6,
+	0x6f, 0xbf, 0x0a, 0x71, 0xf1, 0x9e, 0x43, 0xb9, 0x15, 0xe5, 0xa0, 0x1c, 0x55, 0xc5, 0xba, 0xd8,
+	0xac, 0x1e, 0xef, 0xe0, 0x94, 0x08, 0xfc, 0x94, 0xde, 0xba, 0x26, 0x95, 0xe4, 0x56, 0xac, 0xb4,
+	0x27, 0x15, 0xa9, 0x9d, 0x8d, 0xaa, 0x7f, 0xe9, 0x8f, 0x1a, 0xb2, 0x2e, 0x2c, 0xba, 0xf0, 0xb1,
+	0xe8, 0x36, 0x22, 0xe3, 0x73, 0x20, 0xaf, 0xc4, 0x19, 0x1f, 0x07, 0xf2, 0xd5, 0xff, 0x75, 0xb1,
+	0xb9, 0x6c, 0xf2, 0x20, 0xa5, 0x28, 0xfb, 0xa3, 0xed, 0xaa, 0x32, 0x85, 0xe9, 0xfd, 0xfc, 0xfa,
+	0xf9, 0x62, 0x18, 0x74, 0xef, 0xd9, 0xd9, 0xc9, 0x01, 0x7b, 0x83, 0xcb, 0xc0, 0x01, 0xed, 0xb0,
+	0xf7, 0x2a, 0xdf, 0x06, 0x0d, 0xe3, 0xa9, 0x53, 0xec, 0xce, 0x13, 0xf6, 0xf4, 0x1d, 0x00, 0x00,
+	0xff, 0xff, 0x80, 0x53, 0x54, 0x89, 0x9c, 0x01, 0x00, 0x00,
+}
diff --git a/go/test/custom_results/graphics/machine_id.pb.go b/go/test/custom_results/graphics/machine_id.pb.go
new file mode 100644
index 0000000..f98795e
--- /dev/null
+++ b/go/test/custom_results/graphics/machine_id.pb.go
@@ -0,0 +1,83 @@
+// Code generated by protoc-gen-go. DO NOT EDIT.
+// source: test/custom_results/graphics/machine_id.proto
+
+package graphics
+
+import (
+	fmt "fmt"
+	proto "github.com/golang/protobuf/proto"
+	math "math"
+)
+
+// Reference imports to suppress errors if they are not otherwise used.
+var _ = proto.Marshal
+var _ = fmt.Errorf
+var _ = math.Inf
+
+// This is a compile-time assertion to ensure that this generated file
+// is compatible with the proto package it is being compiled against.
+// A compilation error at this line likely means your copy of the
+// proto package needs to be updated.
+const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package
+
+// Uniquely identifies a machine.
+type MachineId struct {
+	Value                string   `protobuf:"bytes,1,opt,name=value,proto3" json:"value,omitempty"`
+	XXX_NoUnkeyedLiteral struct{} `json:"-"`
+	XXX_unrecognized     []byte   `json:"-"`
+	XXX_sizecache        int32    `json:"-"`
+}
+
+func (m *MachineId) Reset()         { *m = MachineId{} }
+func (m *MachineId) String() string { return proto.CompactTextString(m) }
+func (*MachineId) ProtoMessage()    {}
+func (*MachineId) Descriptor() ([]byte, []int) {
+	return fileDescriptor_5996ccb5ae9e4bd1, []int{0}
+}
+
+func (m *MachineId) XXX_Unmarshal(b []byte) error {
+	return xxx_messageInfo_MachineId.Unmarshal(m, b)
+}
+func (m *MachineId) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	return xxx_messageInfo_MachineId.Marshal(b, m, deterministic)
+}
+func (m *MachineId) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_MachineId.Merge(m, src)
+}
+func (m *MachineId) XXX_Size() int {
+	return xxx_messageInfo_MachineId.Size(m)
+}
+func (m *MachineId) XXX_DiscardUnknown() {
+	xxx_messageInfo_MachineId.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_MachineId proto.InternalMessageInfo
+
+func (m *MachineId) GetValue() string {
+	if m != nil {
+		return m.Value
+	}
+	return ""
+}
+
+func init() {
+	proto.RegisterType((*MachineId)(nil), "test.custom_results.graphics.MachineId")
+}
+
+func init() {
+	proto.RegisterFile("test/custom_results/graphics/machine_id.proto", fileDescriptor_5996ccb5ae9e4bd1)
+}
+
+var fileDescriptor_5996ccb5ae9e4bd1 = []byte{
+	// 152 bytes of a gzipped FileDescriptorProto
+	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xd2, 0x2d, 0x49, 0x2d, 0x2e,
+	0xd1, 0x4f, 0x2e, 0x2d, 0x2e, 0xc9, 0xcf, 0x8d, 0x2f, 0x4a, 0x2d, 0x2e, 0xcd, 0x29, 0x29, 0xd6,
+	0x4f, 0x2f, 0x4a, 0x2c, 0xc8, 0xc8, 0x4c, 0x2e, 0xd6, 0xcf, 0x4d, 0x4c, 0xce, 0xc8, 0xcc, 0x4b,
+	0x8d, 0xcf, 0x4c, 0xd1, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x92, 0x01, 0x29, 0xd7, 0x43, 0x55,
+	0xae, 0x07, 0x53, 0xae, 0xa4, 0xc8, 0xc5, 0xe9, 0x0b, 0xd1, 0xe1, 0x99, 0x22, 0x24, 0xc2, 0xc5,
+	0x5a, 0x96, 0x98, 0x53, 0x9a, 0x2a, 0xc1, 0xa8, 0xc0, 0xa8, 0xc1, 0x19, 0x04, 0xe1, 0x38, 0x79,
+	0x44, 0xb9, 0xa5, 0xe7, 0xeb, 0x25, 0x67, 0x14, 0xe5, 0xe7, 0x66, 0x96, 0xe6, 0xea, 0xe5, 0x17,
+	0xa5, 0xeb, 0xc3, 0x38, 0xf9, 0xc5, 0xfa, 0x99, 0x79, 0x69, 0x45, 0x89, 0xfa, 0x60, 0xab, 0xf4,
+	0xd3, 0xf3, 0xf5, 0xf1, 0xb9, 0x2d, 0x89, 0x0d, 0xac, 0xcc, 0x18, 0x10, 0x00, 0x00, 0xff, 0xff,
+	0x3c, 0xbf, 0x38, 0x47, 0xc2, 0x00, 0x00, 0x00,
+}
diff --git a/go/test/custom_results/graphics/package.pb.go b/go/test/custom_results/graphics/package.pb.go
new file mode 100644
index 0000000..56ab29d
--- /dev/null
+++ b/go/test/custom_results/graphics/package.pb.go
@@ -0,0 +1,136 @@
+// Code generated by protoc-gen-go. DO NOT EDIT.
+// source: test/custom_results/graphics/package.proto
+
+package graphics
+
+import (
+	fmt "fmt"
+	proto "github.com/golang/protobuf/proto"
+	timestamp "github.com/golang/protobuf/ptypes/timestamp"
+	math "math"
+)
+
+// Reference imports to suppress errors if they are not otherwise used.
+var _ = proto.Marshal
+var _ = fmt.Errorf
+var _ = math.Inf
+
+// This is a compile-time assertion to ensure that this generated file
+// is compatible with the proto package it is being compiled against.
+// A compilation error at this line likely means your copy of the
+// proto package needs to be updated.
+const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package
+
+// Next Tag: 7
+type Package struct {
+	Name    string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
+	Version string `protobuf:"bytes,2,opt,name=version,proto3" json:"version,omitempty"`
+	// Hash of last commit in git repo.
+	GitHash string `protobuf:"bytes,3,opt,name=git_hash,json=gitHash,proto3" json:"git_hash,omitempty"`
+	// Git branch package was build from.
+	Branch string `protobuf:"bytes,4,opt,name=branch,proto3" json:"branch,omitempty"`
+	// Commit date of last commit in git repo.
+	CommitDate *timestamp.Timestamp `protobuf:"bytes,5,opt,name=commit_date,json=commitDate,proto3" json:"commit_date,omitempty"`
+	// For packages coming from git, indicate if the build was generated
+	// with a dirty git repo.
+	RepoDirty            bool     `protobuf:"varint,6,opt,name=repo_dirty,json=repoDirty,proto3" json:"repo_dirty,omitempty"`
+	XXX_NoUnkeyedLiteral struct{} `json:"-"`
+	XXX_unrecognized     []byte   `json:"-"`
+	XXX_sizecache        int32    `json:"-"`
+}
+
+func (m *Package) Reset()         { *m = Package{} }
+func (m *Package) String() string { return proto.CompactTextString(m) }
+func (*Package) ProtoMessage()    {}
+func (*Package) Descriptor() ([]byte, []int) {
+	return fileDescriptor_bec6cee28f50b9e9, []int{0}
+}
+
+func (m *Package) XXX_Unmarshal(b []byte) error {
+	return xxx_messageInfo_Package.Unmarshal(m, b)
+}
+func (m *Package) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	return xxx_messageInfo_Package.Marshal(b, m, deterministic)
+}
+func (m *Package) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_Package.Merge(m, src)
+}
+func (m *Package) XXX_Size() int {
+	return xxx_messageInfo_Package.Size(m)
+}
+func (m *Package) XXX_DiscardUnknown() {
+	xxx_messageInfo_Package.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_Package proto.InternalMessageInfo
+
+func (m *Package) GetName() string {
+	if m != nil {
+		return m.Name
+	}
+	return ""
+}
+
+func (m *Package) GetVersion() string {
+	if m != nil {
+		return m.Version
+	}
+	return ""
+}
+
+func (m *Package) GetGitHash() string {
+	if m != nil {
+		return m.GitHash
+	}
+	return ""
+}
+
+func (m *Package) GetBranch() string {
+	if m != nil {
+		return m.Branch
+	}
+	return ""
+}
+
+func (m *Package) GetCommitDate() *timestamp.Timestamp {
+	if m != nil {
+		return m.CommitDate
+	}
+	return nil
+}
+
+func (m *Package) GetRepoDirty() bool {
+	if m != nil {
+		return m.RepoDirty
+	}
+	return false
+}
+
+func init() {
+	proto.RegisterType((*Package)(nil), "test.custom_results.graphics.Package")
+}
+
+func init() {
+	proto.RegisterFile("test/custom_results/graphics/package.proto", fileDescriptor_bec6cee28f50b9e9)
+}
+
+var fileDescriptor_bec6cee28f50b9e9 = []byte{
+	// 272 bytes of a gzipped FileDescriptorProto
+	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x7c, 0x90, 0x3f, 0x4b, 0x04, 0x31,
+	0x14, 0xc4, 0x59, 0x3d, 0xef, 0x4f, 0xae, 0x4b, 0x21, 0xf1, 0x50, 0x3c, 0xac, 0x16, 0x8b, 0x04,
+	0xb4, 0xb4, 0x93, 0x43, 0xae, 0x94, 0xc5, 0xca, 0x66, 0x79, 0x9b, 0xcb, 0x25, 0xc1, 0xcb, 0xbe,
+	0x25, 0x79, 0x2b, 0xf8, 0x05, 0xfd, 0x5c, 0xb2, 0x1b, 0xb7, 0xb0, 0xb1, 0xcb, 0xcc, 0xfc, 0xf2,
+	0x18, 0x86, 0xdd, 0x93, 0x49, 0xa4, 0x74, 0x9f, 0x08, 0x43, 0x1d, 0x4d, 0xea, 0x4f, 0x94, 0x94,
+	0x8d, 0xd0, 0x39, 0xaf, 0x93, 0xea, 0x40, 0x7f, 0x80, 0x35, 0xb2, 0x8b, 0x48, 0xc8, 0xaf, 0x07,
+	0x56, 0xfe, 0x65, 0xe5, 0xc4, 0x6e, 0x6e, 0x2d, 0xa2, 0x3d, 0x19, 0x35, 0xb2, 0x4d, 0x7f, 0x54,
+	0xe4, 0x83, 0x49, 0x04, 0xa1, 0xcb, 0xdf, 0xef, 0xbe, 0x0b, 0xb6, 0x78, 0xcd, 0x07, 0x39, 0x67,
+	0xb3, 0x16, 0x82, 0x11, 0xc5, 0xb6, 0x28, 0x57, 0xd5, 0xf8, 0xe6, 0x82, 0x2d, 0x3e, 0x4d, 0x4c,
+	0x1e, 0x5b, 0x71, 0x36, 0xda, 0x93, 0xe4, 0x57, 0x6c, 0x69, 0x3d, 0xd5, 0x0e, 0x92, 0x13, 0xe7,
+	0x39, 0xb2, 0x9e, 0xf6, 0x90, 0x1c, 0xbf, 0x64, 0xf3, 0x26, 0x42, 0xab, 0x9d, 0x98, 0x8d, 0xc1,
+	0xaf, 0xe2, 0x4f, 0x6c, 0xad, 0x31, 0x04, 0x4f, 0xf5, 0x01, 0xc8, 0x88, 0x8b, 0x6d, 0x51, 0xae,
+	0x1f, 0x36, 0x32, 0x77, 0x94, 0x53, 0x47, 0xf9, 0x36, 0x75, 0xac, 0x58, 0xc6, 0x77, 0x40, 0x86,
+	0xdf, 0x30, 0x16, 0x4d, 0x87, 0xf5, 0xc1, 0x47, 0xfa, 0x12, 0xf3, 0x6d, 0x51, 0x2e, 0xab, 0xd5,
+	0xe0, 0xec, 0x06, 0xe3, 0x79, 0xff, 0xfe, 0x62, 0x51, 0x6a, 0x17, 0x31, 0xf8, 0x3e, 0x48, 0x8c,
+	0x56, 0x4d, 0x02, 0x93, 0xf2, 0xed, 0x31, 0x42, 0x5e, 0x41, 0x59, 0x54, 0xff, 0xed, 0xdb, 0xcc,
+	0x47, 0xec, 0xf1, 0x27, 0x00, 0x00, 0xff, 0xff, 0xad, 0x9b, 0xae, 0x5c, 0x86, 0x01, 0x00, 0x00,
+}
diff --git a/go/test/custom_results/graphics/result.pb.go b/go/test/custom_results/graphics/result.pb.go
new file mode 100644
index 0000000..3d35553
--- /dev/null
+++ b/go/test/custom_results/graphics/result.pb.go
@@ -0,0 +1,505 @@
+// Code generated by protoc-gen-go. DO NOT EDIT.
+// source: test/custom_results/graphics/result.proto
+
+package graphics
+
+import (
+	fmt "fmt"
+	proto "github.com/golang/protobuf/proto"
+	timestamp "github.com/golang/protobuf/ptypes/timestamp"
+	math "math"
+)
+
+// Reference imports to suppress errors if they are not otherwise used.
+var _ = proto.Marshal
+var _ = fmt.Errorf
+var _ = math.Inf
+
+// This is a compile-time assertion to ensure that this generated file
+// is compatible with the proto package it is being compiled against.
+// A compilation error at this line likely means your copy of the
+// proto package needs to be updated.
+const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package
+
+type Result_ExecutionEnvironment int32
+
+const (
+	Result_UNKNOWN  Result_ExecutionEnvironment = 0
+	Result_HOST     Result_ExecutionEnvironment = 1
+	Result_TERMINA  Result_ExecutionEnvironment = 2
+	Result_CROSTINI Result_ExecutionEnvironment = 3
+	Result_STEAM    Result_ExecutionEnvironment = 4
+	Result_ARC      Result_ExecutionEnvironment = 5
+	Result_ARCVM    Result_ExecutionEnvironment = 6
+	Result_CROUTON  Result_ExecutionEnvironment = 7
+	Result_CROSVM   Result_ExecutionEnvironment = 8
+)
+
+var Result_ExecutionEnvironment_name = map[int32]string{
+	0: "UNKNOWN",
+	1: "HOST",
+	2: "TERMINA",
+	3: "CROSTINI",
+	4: "STEAM",
+	5: "ARC",
+	6: "ARCVM",
+	7: "CROUTON",
+	8: "CROSVM",
+}
+
+var Result_ExecutionEnvironment_value = map[string]int32{
+	"UNKNOWN":  0,
+	"HOST":     1,
+	"TERMINA":  2,
+	"CROSTINI": 3,
+	"STEAM":    4,
+	"ARC":      5,
+	"ARCVM":    6,
+	"CROUTON":  7,
+	"CROSVM":   8,
+}
+
+func (x Result_ExecutionEnvironment) String() string {
+	return proto.EnumName(Result_ExecutionEnvironment_name, int32(x))
+}
+
+func (Result_ExecutionEnvironment) EnumDescriptor() ([]byte, []int) {
+	return fileDescriptor_c3a06ed77c11a28f, []int{0, 0}
+}
+
+// Result of a single test, trace, or benchmark run.
+// Next Tag: 19
+type Result struct {
+	// Global unique result identifier.
+	Id *ResultId `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`
+	// When the result started and finished being collected.
+	StartTime *timestamp.Timestamp `protobuf:"bytes,2,opt,name=start_time,json=startTime,proto3" json:"start_time,omitempty"`
+	EndTime   *timestamp.Timestamp `protobuf:"bytes,3,opt,name=end_time,json=endTime,proto3" json:"end_time,omitempty"`
+	// Machine which generated the result.
+	Machine *MachineId `protobuf:"bytes,4,opt,name=machine,proto3" json:"machine,omitempty"`
+	// Installed software at the time the result was collected.
+	SoftwareConfig       *SoftwareConfigId           `protobuf:"bytes,5,opt,name=software_config,json=softwareConfig,proto3" json:"software_config,omitempty"`
+	ExecutionEnvironment Result_ExecutionEnvironment `protobuf:"varint,6,opt,name=execution_environment,json=executionEnvironment,proto3,enum=test.custom_results.graphics.Result_ExecutionEnvironment" json:"execution_environment,omitempty"`
+	// Lab or user originating this result.
+	// Format:
+	// - lab/LABNAME
+	// - user/USERNAME
+	InvocationSource string `protobuf:"bytes,7,opt,name=invocation_source,json=invocationSource,proto3" json:"invocation_source,omitempty"`
+	// Details on the invocation if it was generated as part of a test.
+	// TODO(davidriley): Flesh these out better.
+	// TODO(davidriley): Record test status and error messages.
+	TestId    string `protobuf:"bytes,17,opt,name=test_id,json=testId,proto3" json:"test_id,omitempty"`
+	TestName  string `protobuf:"bytes,8,opt,name=test_name,json=testName,proto3" json:"test_name,omitempty"`
+	TestJobId string `protobuf:"bytes,9,opt,name=test_job_id,json=testJobId,proto3" json:"test_job_id,omitempty"`
+	// Command line used invoke the test.
+	CommandLine string `protobuf:"bytes,10,opt,name=command_line,json=commandLine,proto3" json:"command_line,omitempty"`
+	// Thing being tested.
+	Benchmark string   `protobuf:"bytes,11,opt,name=benchmark,proto3" json:"benchmark,omitempty"`
+	Trace     *TraceId `protobuf:"bytes,12,opt,name=trace,proto3" json:"trace,omitempty"`
+	// fps, frames, time
+	// usec for frame N
+	// cpu/gpu utilization/frequency
+	Metrics []*Result_Metric `protobuf:"bytes,13,rep,name=metrics,proto3" json:"metrics,omitempty"`
+	// Identify the most interesting metric to show by default for a given result.
+	PrimaryMetricName string          `protobuf:"bytes,14,opt,name=primary_metric_name,json=primaryMetricName,proto3" json:"primary_metric_name,omitempty"`
+	Labels            []*Result_Label `protobuf:"bytes,15,rep,name=labels,proto3" json:"labels,omitempty"`
+	// Software that was explicitly overriden from the normal system software
+	// for a given result.
+	Overrides            *SoftwareOverridesConfig `protobuf:"bytes,18,opt,name=overrides,proto3" json:"overrides,omitempty"`
+	XXX_NoUnkeyedLiteral struct{}                 `json:"-"`
+	XXX_unrecognized     []byte                   `json:"-"`
+	XXX_sizecache        int32                    `json:"-"`
+}
+
+func (m *Result) Reset()         { *m = Result{} }
+func (m *Result) String() string { return proto.CompactTextString(m) }
+func (*Result) ProtoMessage()    {}
+func (*Result) Descriptor() ([]byte, []int) {
+	return fileDescriptor_c3a06ed77c11a28f, []int{0}
+}
+
+func (m *Result) XXX_Unmarshal(b []byte) error {
+	return xxx_messageInfo_Result.Unmarshal(m, b)
+}
+func (m *Result) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	return xxx_messageInfo_Result.Marshal(b, m, deterministic)
+}
+func (m *Result) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_Result.Merge(m, src)
+}
+func (m *Result) XXX_Size() int {
+	return xxx_messageInfo_Result.Size(m)
+}
+func (m *Result) XXX_DiscardUnknown() {
+	xxx_messageInfo_Result.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_Result proto.InternalMessageInfo
+
+func (m *Result) GetId() *ResultId {
+	if m != nil {
+		return m.Id
+	}
+	return nil
+}
+
+func (m *Result) GetStartTime() *timestamp.Timestamp {
+	if m != nil {
+		return m.StartTime
+	}
+	return nil
+}
+
+func (m *Result) GetEndTime() *timestamp.Timestamp {
+	if m != nil {
+		return m.EndTime
+	}
+	return nil
+}
+
+func (m *Result) GetMachine() *MachineId {
+	if m != nil {
+		return m.Machine
+	}
+	return nil
+}
+
+func (m *Result) GetSoftwareConfig() *SoftwareConfigId {
+	if m != nil {
+		return m.SoftwareConfig
+	}
+	return nil
+}
+
+func (m *Result) GetExecutionEnvironment() Result_ExecutionEnvironment {
+	if m != nil {
+		return m.ExecutionEnvironment
+	}
+	return Result_UNKNOWN
+}
+
+func (m *Result) GetInvocationSource() string {
+	if m != nil {
+		return m.InvocationSource
+	}
+	return ""
+}
+
+func (m *Result) GetTestId() string {
+	if m != nil {
+		return m.TestId
+	}
+	return ""
+}
+
+func (m *Result) GetTestName() string {
+	if m != nil {
+		return m.TestName
+	}
+	return ""
+}
+
+func (m *Result) GetTestJobId() string {
+	if m != nil {
+		return m.TestJobId
+	}
+	return ""
+}
+
+func (m *Result) GetCommandLine() string {
+	if m != nil {
+		return m.CommandLine
+	}
+	return ""
+}
+
+func (m *Result) GetBenchmark() string {
+	if m != nil {
+		return m.Benchmark
+	}
+	return ""
+}
+
+func (m *Result) GetTrace() *TraceId {
+	if m != nil {
+		return m.Trace
+	}
+	return nil
+}
+
+func (m *Result) GetMetrics() []*Result_Metric {
+	if m != nil {
+		return m.Metrics
+	}
+	return nil
+}
+
+func (m *Result) GetPrimaryMetricName() string {
+	if m != nil {
+		return m.PrimaryMetricName
+	}
+	return ""
+}
+
+func (m *Result) GetLabels() []*Result_Label {
+	if m != nil {
+		return m.Labels
+	}
+	return nil
+}
+
+func (m *Result) GetOverrides() *SoftwareOverridesConfig {
+	if m != nil {
+		return m.Overrides
+	}
+	return nil
+}
+
+// TODO(davidriley): This unit could be made into a separate Message
+// a) This stanza is directly part of TraceResult with TraceResult repeated.
+// b) This stanze becomes a separate repeated Message within TraceResult.
+// c) This stanza becomes a separate Message with TraceResultId link to them.
+// Next Tag: 7
+type Result_Metric struct {
+	Name                 string   `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
+	Index                uint64   `protobuf:"varint,2,opt,name=index,proto3" json:"index,omitempty"`
+	Value                float64  `protobuf:"fixed64,3,opt,name=value,proto3" json:"value,omitempty"`
+	Units                string   `protobuf:"bytes,4,opt,name=units,proto3" json:"units,omitempty"`
+	LargerIsBetter       bool     `protobuf:"varint,5,opt,name=larger_is_better,json=largerIsBetter,proto3" json:"larger_is_better,omitempty"`
+	ExternallyGathered   bool     `protobuf:"varint,6,opt,name=externally_gathered,json=externallyGathered,proto3" json:"externally_gathered,omitempty"`
+	XXX_NoUnkeyedLiteral struct{} `json:"-"`
+	XXX_unrecognized     []byte   `json:"-"`
+	XXX_sizecache        int32    `json:"-"`
+}
+
+func (m *Result_Metric) Reset()         { *m = Result_Metric{} }
+func (m *Result_Metric) String() string { return proto.CompactTextString(m) }
+func (*Result_Metric) ProtoMessage()    {}
+func (*Result_Metric) Descriptor() ([]byte, []int) {
+	return fileDescriptor_c3a06ed77c11a28f, []int{0, 0}
+}
+
+func (m *Result_Metric) XXX_Unmarshal(b []byte) error {
+	return xxx_messageInfo_Result_Metric.Unmarshal(m, b)
+}
+func (m *Result_Metric) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	return xxx_messageInfo_Result_Metric.Marshal(b, m, deterministic)
+}
+func (m *Result_Metric) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_Result_Metric.Merge(m, src)
+}
+func (m *Result_Metric) XXX_Size() int {
+	return xxx_messageInfo_Result_Metric.Size(m)
+}
+func (m *Result_Metric) XXX_DiscardUnknown() {
+	xxx_messageInfo_Result_Metric.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_Result_Metric proto.InternalMessageInfo
+
+func (m *Result_Metric) GetName() string {
+	if m != nil {
+		return m.Name
+	}
+	return ""
+}
+
+func (m *Result_Metric) GetIndex() uint64 {
+	if m != nil {
+		return m.Index
+	}
+	return 0
+}
+
+func (m *Result_Metric) GetValue() float64 {
+	if m != nil {
+		return m.Value
+	}
+	return 0
+}
+
+func (m *Result_Metric) GetUnits() string {
+	if m != nil {
+		return m.Units
+	}
+	return ""
+}
+
+func (m *Result_Metric) GetLargerIsBetter() bool {
+	if m != nil {
+		return m.LargerIsBetter
+	}
+	return false
+}
+
+func (m *Result_Metric) GetExternallyGathered() bool {
+	if m != nil {
+		return m.ExternallyGathered
+	}
+	return false
+}
+
+// General non-numeric details collected about the environment or system
+// state.  eg Interesting environment variables, glxinfo info.
+// Next Tag: 4
+type Result_Label struct {
+	Name                 string   `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
+	Value                string   `protobuf:"bytes,2,opt,name=value,proto3" json:"value,omitempty"`
+	Grouping             string   `protobuf:"bytes,3,opt,name=grouping,proto3" json:"grouping,omitempty"`
+	XXX_NoUnkeyedLiteral struct{} `json:"-"`
+	XXX_unrecognized     []byte   `json:"-"`
+	XXX_sizecache        int32    `json:"-"`
+}
+
+func (m *Result_Label) Reset()         { *m = Result_Label{} }
+func (m *Result_Label) String() string { return proto.CompactTextString(m) }
+func (*Result_Label) ProtoMessage()    {}
+func (*Result_Label) Descriptor() ([]byte, []int) {
+	return fileDescriptor_c3a06ed77c11a28f, []int{0, 1}
+}
+
+func (m *Result_Label) XXX_Unmarshal(b []byte) error {
+	return xxx_messageInfo_Result_Label.Unmarshal(m, b)
+}
+func (m *Result_Label) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	return xxx_messageInfo_Result_Label.Marshal(b, m, deterministic)
+}
+func (m *Result_Label) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_Result_Label.Merge(m, src)
+}
+func (m *Result_Label) XXX_Size() int {
+	return xxx_messageInfo_Result_Label.Size(m)
+}
+func (m *Result_Label) XXX_DiscardUnknown() {
+	xxx_messageInfo_Result_Label.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_Result_Label proto.InternalMessageInfo
+
+func (m *Result_Label) GetName() string {
+	if m != nil {
+		return m.Name
+	}
+	return ""
+}
+
+func (m *Result_Label) GetValue() string {
+	if m != nil {
+		return m.Value
+	}
+	return ""
+}
+
+func (m *Result_Label) GetGrouping() string {
+	if m != nil {
+		return m.Grouping
+	}
+	return ""
+}
+
+type ResultList struct {
+	Value                []*Result `protobuf:"bytes,1,rep,name=value,proto3" json:"value,omitempty"`
+	XXX_NoUnkeyedLiteral struct{}  `json:"-"`
+	XXX_unrecognized     []byte    `json:"-"`
+	XXX_sizecache        int32     `json:"-"`
+}
+
+func (m *ResultList) Reset()         { *m = ResultList{} }
+func (m *ResultList) String() string { return proto.CompactTextString(m) }
+func (*ResultList) ProtoMessage()    {}
+func (*ResultList) Descriptor() ([]byte, []int) {
+	return fileDescriptor_c3a06ed77c11a28f, []int{1}
+}
+
+func (m *ResultList) XXX_Unmarshal(b []byte) error {
+	return xxx_messageInfo_ResultList.Unmarshal(m, b)
+}
+func (m *ResultList) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	return xxx_messageInfo_ResultList.Marshal(b, m, deterministic)
+}
+func (m *ResultList) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_ResultList.Merge(m, src)
+}
+func (m *ResultList) XXX_Size() int {
+	return xxx_messageInfo_ResultList.Size(m)
+}
+func (m *ResultList) XXX_DiscardUnknown() {
+	xxx_messageInfo_ResultList.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_ResultList proto.InternalMessageInfo
+
+func (m *ResultList) GetValue() []*Result {
+	if m != nil {
+		return m.Value
+	}
+	return nil
+}
+
+func init() {
+	proto.RegisterEnum("test.custom_results.graphics.Result_ExecutionEnvironment", Result_ExecutionEnvironment_name, Result_ExecutionEnvironment_value)
+	proto.RegisterType((*Result)(nil), "test.custom_results.graphics.Result")
+	proto.RegisterType((*Result_Metric)(nil), "test.custom_results.graphics.Result.Metric")
+	proto.RegisterType((*Result_Label)(nil), "test.custom_results.graphics.Result.Label")
+	proto.RegisterType((*ResultList)(nil), "test.custom_results.graphics.ResultList")
+}
+
+func init() {
+	proto.RegisterFile("test/custom_results/graphics/result.proto", fileDescriptor_c3a06ed77c11a28f)
+}
+
+var fileDescriptor_c3a06ed77c11a28f = []byte{
+	// 828 bytes of a gzipped FileDescriptorProto
+	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x55, 0x6d, 0x6f, 0xe3, 0x44,
+	0x10, 0xc6, 0x6d, 0x5e, 0x27, 0xa5, 0xe7, 0xee, 0x15, 0x61, 0x85, 0x13, 0x94, 0x8a, 0x97, 0x40,
+	0xc1, 0x96, 0x8a, 0x8a, 0x74, 0xc0, 0x97, 0x34, 0x0a, 0xd4, 0xd0, 0x24, 0xd2, 0x26, 0x77, 0x27,
+	0xf1, 0xc5, 0xda, 0xd8, 0x5b, 0x67, 0x21, 0xde, 0x8d, 0x76, 0x37, 0xa5, 0xf7, 0x8d, 0xbf, 0xc5,
+	0x8f, 0xe1, 0xbf, 0x20, 0xcf, 0x3a, 0x8d, 0x0e, 0x1d, 0x21, 0xdf, 0x3c, 0xcf, 0x3c, 0xcf, 0xec,
+	0xcc, 0xb3, 0x3b, 0x32, 0x7c, 0x61, 0xb9, 0xb1, 0x51, 0xba, 0x36, 0x56, 0x15, 0x89, 0xe6, 0x66,
+	0xbd, 0xb4, 0x26, 0xca, 0x35, 0x5b, 0x2d, 0x44, 0x6a, 0x22, 0x07, 0x84, 0x2b, 0xad, 0xac, 0x22,
+	0xcf, 0x4a, 0x6a, 0xf8, 0x26, 0x35, 0xdc, 0x50, 0xbb, 0x1f, 0xe5, 0x4a, 0xe5, 0x4b, 0x1e, 0x21,
+	0x77, 0xbe, 0xbe, 0x8b, 0xac, 0x28, 0xb8, 0xb1, 0xac, 0x58, 0x39, 0x79, 0xf7, 0xeb, 0x9d, 0x27,
+	0x15, 0x2c, 0x5d, 0x08, 0xc9, 0x13, 0x91, 0x55, 0xf4, 0xaf, 0xf6, 0x68, 0x6c, 0xcb, 0xbe, 0xda,
+	0xc9, 0x36, 0xea, 0xce, 0xfe, 0xc1, 0x34, 0x4f, 0x52, 0x25, 0xef, 0x44, 0xbe, 0x95, 0xfd, 0xb0,
+	0x9f, 0x4c, 0xdd, 0x73, 0xad, 0x45, 0xc6, 0x4d, 0x55, 0xa0, 0x52, 0x5f, 0xec, 0x54, 0x5b, 0xcd,
+	0xd2, 0xed, 0x3c, 0xe7, 0x7f, 0x03, 0x34, 0x28, 0x72, 0xc8, 0xb7, 0x70, 0x20, 0xb2, 0xc0, 0x3b,
+	0xf3, 0x7a, 0x9d, 0xcb, 0xcf, 0xc2, 0x5d, 0xae, 0x86, 0x4e, 0x11, 0x67, 0xf4, 0x40, 0x64, 0xe4,
+	0x39, 0x80, 0xb1, 0x4c, 0xdb, 0xa4, 0xb4, 0x36, 0x38, 0x40, 0x7d, 0x37, 0x74, 0xbe, 0x87, 0x1b,
+	0xdf, 0xc3, 0xd9, 0xc6, 0x77, 0xda, 0x46, 0x76, 0x19, 0x93, 0x2b, 0x68, 0x71, 0x99, 0x39, 0xe1,
+	0xe1, 0xff, 0x0a, 0x9b, 0x5c, 0x66, 0x28, 0xeb, 0x43, 0xb3, 0xba, 0x98, 0xa0, 0x86, 0xaa, 0xcf,
+	0x77, 0xb7, 0x3b, 0x72, 0xe4, 0x38, 0xa3, 0x1b, 0x1d, 0x79, 0x05, 0x4f, 0xfe, 0x65, 0x7f, 0x50,
+	0xc7, 0x52, 0xe1, 0xee, 0x52, 0xd3, 0x4a, 0x34, 0x40, 0x4d, 0x9c, 0xd1, 0x63, 0xf3, 0x06, 0x42,
+	0x24, 0xbc, 0xc7, 0x1f, 0x78, 0xba, 0xb6, 0x42, 0xc9, 0x84, 0xcb, 0x7b, 0xa1, 0x95, 0x2c, 0xb8,
+	0xb4, 0x41, 0xe3, 0xcc, 0xeb, 0x1d, 0x5f, 0x3e, 0xdf, 0xc7, 0xd8, 0x70, 0xb8, 0xa9, 0x30, 0xdc,
+	0x16, 0xa0, 0xa7, 0xfc, 0x2d, 0x28, 0xb9, 0x80, 0x13, 0x21, 0xef, 0x55, 0xca, 0xf0, 0x40, 0xa3,
+	0xd6, 0x3a, 0xe5, 0x41, 0xf3, 0xcc, 0xeb, 0xb5, 0xa9, 0xbf, 0x4d, 0x4c, 0x11, 0x27, 0xef, 0x43,
+	0xb3, 0x3c, 0x3e, 0x11, 0x59, 0x70, 0x82, 0x94, 0x46, 0x19, 0xc6, 0x19, 0xf9, 0x00, 0xda, 0x98,
+	0x90, 0xac, 0xe0, 0x41, 0x0b, 0x53, 0xad, 0x12, 0x18, 0xb3, 0x82, 0x93, 0x0f, 0xa1, 0x83, 0xc9,
+	0xdf, 0xd4, 0xbc, 0x54, 0xb6, 0x31, 0x8d, 0xfc, 0x9f, 0xd5, 0x3c, 0xce, 0xc8, 0xc7, 0x70, 0x94,
+	0xaa, 0xa2, 0x60, 0x32, 0x4b, 0x96, 0xe5, 0x9d, 0x00, 0x12, 0x3a, 0x15, 0x76, 0x5b, 0xda, 0xfd,
+	0x0c, 0xda, 0x73, 0x2e, 0xd3, 0x45, 0xc1, 0xf4, 0xef, 0x41, 0xc7, 0x15, 0x78, 0x04, 0xc8, 0xf7,
+	0x50, 0xc7, 0x67, 0x19, 0x1c, 0xe1, 0x15, 0x7c, 0xba, 0xdb, 0xa3, 0x59, 0x49, 0x8d, 0x33, 0xea,
+	0x34, 0x64, 0x08, 0xcd, 0x82, 0x5b, 0x2d, 0x52, 0x13, 0xbc, 0x7b, 0x76, 0xd8, 0xeb, 0x5c, 0x5e,
+	0xec, 0x65, 0xf1, 0x08, 0x35, 0x74, 0xa3, 0x25, 0x21, 0x3c, 0x5d, 0x69, 0x51, 0x30, 0xfd, 0x3a,
+	0x71, 0x90, 0xf3, 0xe2, 0x18, 0x7b, 0x3d, 0xa9, 0x52, 0x4e, 0x84, 0xa6, 0x5c, 0x43, 0x63, 0xc9,
+	0xe6, 0x7c, 0x69, 0x82, 0x27, 0x78, 0xea, 0x97, 0x7b, 0x9d, 0x7a, 0x5b, 0x4a, 0x68, 0xa5, 0x24,
+	0x53, 0x68, 0x3f, 0xee, 0x70, 0x40, 0x70, 0xf6, 0xab, 0xfd, 0x9e, 0xdf, 0x64, 0x23, 0x73, 0xaf,
+	0x8e, 0x6e, 0xeb, 0x74, 0xff, 0xf2, 0xa0, 0xe1, 0xfa, 0x24, 0x04, 0x6a, 0x38, 0x84, 0x87, 0x43,
+	0xe0, 0x37, 0x39, 0x85, 0xba, 0x90, 0x19, 0x7f, 0xc0, 0x45, 0xad, 0x51, 0x17, 0x94, 0xe8, 0x3d,
+	0x5b, 0xae, 0xdd, 0x16, 0x7a, 0xd4, 0x05, 0x25, 0xba, 0x96, 0xc2, 0x1a, 0xdc, 0xb2, 0x36, 0x75,
+	0x01, 0xe9, 0x81, 0xbf, 0x64, 0x3a, 0xe7, 0x3a, 0x11, 0x26, 0x99, 0x73, 0x6b, 0xb9, 0xc6, 0xdd,
+	0x69, 0xd1, 0x63, 0x87, 0xc7, 0xe6, 0x1a, 0x51, 0x12, 0xc1, 0x53, 0xfe, 0x60, 0xb9, 0x96, 0x6c,
+	0xb9, 0x7c, 0x9d, 0xe4, 0xcc, 0x2e, 0xb8, 0xe6, 0x19, 0x6e, 0x42, 0x8b, 0x92, 0x6d, 0xea, 0xa7,
+	0x2a, 0xd3, 0x1d, 0x41, 0x1d, 0x1d, 0xfa, 0xaf, 0xce, 0x5d, 0x8f, 0x07, 0xae, 0x1b, 0xd7, 0x63,
+	0x17, 0x5a, 0xb9, 0x56, 0xeb, 0x95, 0x90, 0x39, 0x36, 0xdf, 0xa6, 0x8f, 0xf1, 0xf9, 0x9f, 0x1e,
+	0x9c, 0xbe, 0x6d, 0x95, 0x48, 0x07, 0x9a, 0x2f, 0xc6, 0xbf, 0x8c, 0x27, 0xaf, 0xc6, 0xfe, 0x3b,
+	0xa4, 0x05, 0xb5, 0x9b, 0xc9, 0x74, 0xe6, 0x7b, 0x25, 0x3c, 0x1b, 0xd2, 0x51, 0x3c, 0xee, 0xfb,
+	0x07, 0xe4, 0x08, 0x5a, 0x03, 0x3a, 0x99, 0xce, 0xe2, 0x71, 0xec, 0x1f, 0x92, 0x36, 0xd4, 0xa7,
+	0xb3, 0x61, 0x7f, 0xe4, 0xd7, 0x48, 0x13, 0x0e, 0xfb, 0x74, 0xe0, 0xd7, 0x4b, 0xac, 0x4f, 0x07,
+	0x2f, 0x47, 0x7e, 0xa3, 0x54, 0x0e, 0xe8, 0xe4, 0xc5, 0x6c, 0x32, 0xf6, 0x9b, 0x04, 0xa0, 0x51,
+	0x2a, 0x5f, 0x8e, 0xfc, 0xd6, 0xf9, 0x0d, 0x80, 0xbb, 0xfa, 0x5b, 0x61, 0x2c, 0xf9, 0x6e, 0x33,
+	0x82, 0x87, 0x6f, 0xe6, 0x93, 0x7d, 0xde, 0x4c, 0x35, 0xe8, 0xf5, 0xcd, 0xaf, 0x3f, 0xe6, 0x2a,
+	0x4c, 0x17, 0x5a, 0x15, 0x62, 0x5d, 0x84, 0x4a, 0xe7, 0xd1, 0x26, 0x50, 0x26, 0x12, 0xf2, 0x4e,
+	0x33, 0xf7, 0x97, 0x8b, 0x72, 0x15, 0xed, 0xfa, 0x05, 0xcc, 0x1b, 0x48, 0xfb, 0xe6, 0x9f, 0x00,
+	0x00, 0x00, 0xff, 0xff, 0xc7, 0xa4, 0x10, 0xf9, 0x65, 0x07, 0x00, 0x00,
+}
diff --git a/go/test/custom_results/graphics/result_id.pb.go b/go/test/custom_results/graphics/result_id.pb.go
new file mode 100644
index 0000000..5c13263
--- /dev/null
+++ b/go/test/custom_results/graphics/result_id.pb.go
@@ -0,0 +1,83 @@
+// Code generated by protoc-gen-go. DO NOT EDIT.
+// source: test/custom_results/graphics/result_id.proto
+
+package graphics
+
+import (
+	fmt "fmt"
+	proto "github.com/golang/protobuf/proto"
+	math "math"
+)
+
+// Reference imports to suppress errors if they are not otherwise used.
+var _ = proto.Marshal
+var _ = fmt.Errorf
+var _ = math.Inf
+
+// This is a compile-time assertion to ensure that this generated file
+// is compatible with the proto package it is being compiled against.
+// A compilation error at this line likely means your copy of the
+// proto package needs to be updated.
+const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package
+
+// Uniquely identifies a test result.
+type ResultId struct {
+	Value                string   `protobuf:"bytes,1,opt,name=value,proto3" json:"value,omitempty"`
+	XXX_NoUnkeyedLiteral struct{} `json:"-"`
+	XXX_unrecognized     []byte   `json:"-"`
+	XXX_sizecache        int32    `json:"-"`
+}
+
+func (m *ResultId) Reset()         { *m = ResultId{} }
+func (m *ResultId) String() string { return proto.CompactTextString(m) }
+func (*ResultId) ProtoMessage()    {}
+func (*ResultId) Descriptor() ([]byte, []int) {
+	return fileDescriptor_f87ee29742d669c3, []int{0}
+}
+
+func (m *ResultId) XXX_Unmarshal(b []byte) error {
+	return xxx_messageInfo_ResultId.Unmarshal(m, b)
+}
+func (m *ResultId) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	return xxx_messageInfo_ResultId.Marshal(b, m, deterministic)
+}
+func (m *ResultId) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_ResultId.Merge(m, src)
+}
+func (m *ResultId) XXX_Size() int {
+	return xxx_messageInfo_ResultId.Size(m)
+}
+func (m *ResultId) XXX_DiscardUnknown() {
+	xxx_messageInfo_ResultId.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_ResultId proto.InternalMessageInfo
+
+func (m *ResultId) GetValue() string {
+	if m != nil {
+		return m.Value
+	}
+	return ""
+}
+
+func init() {
+	proto.RegisterType((*ResultId)(nil), "test.custom_results.graphics.ResultId")
+}
+
+func init() {
+	proto.RegisterFile("test/custom_results/graphics/result_id.proto", fileDescriptor_f87ee29742d669c3)
+}
+
+var fileDescriptor_f87ee29742d669c3 = []byte{
+	// 147 bytes of a gzipped FileDescriptorProto
+	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xd2, 0x29, 0x49, 0x2d, 0x2e,
+	0xd1, 0x4f, 0x2e, 0x2d, 0x2e, 0xc9, 0xcf, 0x8d, 0x2f, 0x4a, 0x2d, 0x2e, 0xcd, 0x29, 0x29, 0xd6,
+	0x4f, 0x2f, 0x4a, 0x2c, 0xc8, 0xc8, 0x4c, 0x2e, 0xd6, 0x87, 0x08, 0xc4, 0x67, 0xa6, 0xe8, 0x15,
+	0x14, 0xe5, 0x97, 0xe4, 0x0b, 0xc9, 0x80, 0x54, 0xeb, 0xa1, 0xaa, 0xd6, 0x83, 0xa9, 0x56, 0x52,
+	0xe0, 0xe2, 0x08, 0x02, 0x8b, 0x79, 0xa6, 0x08, 0x89, 0x70, 0xb1, 0x96, 0x25, 0xe6, 0x94, 0xa6,
+	0x4a, 0x30, 0x2a, 0x30, 0x6a, 0x70, 0x06, 0x41, 0x38, 0x4e, 0x1e, 0x51, 0x6e, 0xe9, 0xf9, 0x7a,
+	0xc9, 0x19, 0x45, 0xf9, 0xb9, 0x99, 0xa5, 0xb9, 0x7a, 0xf9, 0x45, 0xe9, 0xfa, 0x30, 0x4e, 0x7e,
+	0xb1, 0x7e, 0x66, 0x5e, 0x5a, 0x51, 0xa2, 0x3e, 0xd8, 0x26, 0xfd, 0xf4, 0x7c, 0x7d, 0x7c, 0x2e,
+	0x4b, 0x62, 0x03, 0x2b, 0x33, 0x06, 0x04, 0x00, 0x00, 0xff, 0xff, 0xe2, 0xbd, 0xa4, 0xfe, 0xc0,
+	0x00, 0x00, 0x00,
+}
diff --git a/go/test/custom_results/graphics/software_config.pb.go b/go/test/custom_results/graphics/software_config.pb.go
new file mode 100644
index 0000000..a1fc216
--- /dev/null
+++ b/go/test/custom_results/graphics/software_config.pb.go
@@ -0,0 +1,405 @@
+// Code generated by protoc-gen-go. DO NOT EDIT.
+// source: test/custom_results/graphics/software_config.proto
+
+package graphics
+
+import (
+	fmt "fmt"
+	proto "github.com/golang/protobuf/proto"
+	timestamp "github.com/golang/protobuf/ptypes/timestamp"
+	math "math"
+)
+
+// Reference imports to suppress errors if they are not otherwise used.
+var _ = proto.Marshal
+var _ = fmt.Errorf
+var _ = math.Inf
+
+// This is a compile-time assertion to ensure that this generated file
+// is compatible with the proto package it is being compiled against.
+// A compilation error at this line likely means your copy of the
+// proto package needs to be updated.
+const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package
+
+// Software configuration of installed software on a device.
+// Next Tag: 11
+type SoftwareConfig struct {
+	// Global unique software configuration identifier.
+	Id         *SoftwareConfigId    `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`
+	CreateTime *timestamp.Timestamp `protobuf:"bytes,2,opt,name=create_time,json=createTime,proto3" json:"create_time,omitempty"`
+	// For nested systems, the software configuration of the host system.
+	Parent               *SoftwareConfigId        `protobuf:"bytes,3,opt,name=parent,proto3" json:"parent,omitempty"`
+	Packages             []*Package               `protobuf:"bytes,4,rep,name=packages,proto3" json:"packages,omitempty"`
+	KernelRelease        string                   `protobuf:"bytes,5,opt,name=kernel_release,json=kernelRelease,proto3" json:"kernel_release,omitempty"`
+	KernelVersion        string                   `protobuf:"bytes,6,opt,name=kernel_version,json=kernelVersion,proto3" json:"kernel_version,omitempty"`
+	Chromeos             *SoftwareConfig_ChromeOS `protobuf:"bytes,7,opt,name=chromeos,proto3" json:"chromeos,omitempty"`
+	Os                   *SoftwareConfig_OS       `protobuf:"bytes,8,opt,name=os,proto3" json:"os,omitempty"`
+	BiosVersion          string                   `protobuf:"bytes,9,opt,name=bios_version,json=biosVersion,proto3" json:"bios_version,omitempty"`
+	EcVersion            string                   `protobuf:"bytes,10,opt,name=ec_version,json=ecVersion,proto3" json:"ec_version,omitempty"`
+	XXX_NoUnkeyedLiteral struct{}                 `json:"-"`
+	XXX_unrecognized     []byte                   `json:"-"`
+	XXX_sizecache        int32                    `json:"-"`
+}
+
+func (m *SoftwareConfig) Reset()         { *m = SoftwareConfig{} }
+func (m *SoftwareConfig) String() string { return proto.CompactTextString(m) }
+func (*SoftwareConfig) ProtoMessage()    {}
+func (*SoftwareConfig) Descriptor() ([]byte, []int) {
+	return fileDescriptor_9bb41260180eeb52, []int{0}
+}
+
+func (m *SoftwareConfig) XXX_Unmarshal(b []byte) error {
+	return xxx_messageInfo_SoftwareConfig.Unmarshal(m, b)
+}
+func (m *SoftwareConfig) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	return xxx_messageInfo_SoftwareConfig.Marshal(b, m, deterministic)
+}
+func (m *SoftwareConfig) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_SoftwareConfig.Merge(m, src)
+}
+func (m *SoftwareConfig) XXX_Size() int {
+	return xxx_messageInfo_SoftwareConfig.Size(m)
+}
+func (m *SoftwareConfig) XXX_DiscardUnknown() {
+	xxx_messageInfo_SoftwareConfig.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_SoftwareConfig proto.InternalMessageInfo
+
+func (m *SoftwareConfig) GetId() *SoftwareConfigId {
+	if m != nil {
+		return m.Id
+	}
+	return nil
+}
+
+func (m *SoftwareConfig) GetCreateTime() *timestamp.Timestamp {
+	if m != nil {
+		return m.CreateTime
+	}
+	return nil
+}
+
+func (m *SoftwareConfig) GetParent() *SoftwareConfigId {
+	if m != nil {
+		return m.Parent
+	}
+	return nil
+}
+
+func (m *SoftwareConfig) GetPackages() []*Package {
+	if m != nil {
+		return m.Packages
+	}
+	return nil
+}
+
+func (m *SoftwareConfig) GetKernelRelease() string {
+	if m != nil {
+		return m.KernelRelease
+	}
+	return ""
+}
+
+func (m *SoftwareConfig) GetKernelVersion() string {
+	if m != nil {
+		return m.KernelVersion
+	}
+	return ""
+}
+
+func (m *SoftwareConfig) GetChromeos() *SoftwareConfig_ChromeOS {
+	if m != nil {
+		return m.Chromeos
+	}
+	return nil
+}
+
+func (m *SoftwareConfig) GetOs() *SoftwareConfig_OS {
+	if m != nil {
+		return m.Os
+	}
+	return nil
+}
+
+func (m *SoftwareConfig) GetBiosVersion() string {
+	if m != nil {
+		return m.BiosVersion
+	}
+	return ""
+}
+
+func (m *SoftwareConfig) GetEcVersion() string {
+	if m != nil {
+		return m.EcVersion
+	}
+	return ""
+}
+
+type SoftwareConfig_ChromeOS struct {
+	Board                string   `protobuf:"bytes,1,opt,name=board,proto3" json:"board,omitempty"`
+	BranchNumber         uint32   `protobuf:"varint,2,opt,name=branch_number,json=branchNumber,proto3" json:"branch_number,omitempty"`
+	BuilderPath          string   `protobuf:"bytes,3,opt,name=builder_path,json=builderPath,proto3" json:"builder_path,omitempty"`
+	BuildNumber          uint32   `protobuf:"varint,4,opt,name=build_number,json=buildNumber,proto3" json:"build_number,omitempty"`
+	BuildType            string   `protobuf:"bytes,5,opt,name=build_type,json=buildType,proto3" json:"build_type,omitempty"`
+	ChromeMilestone      uint32   `protobuf:"varint,6,opt,name=chrome_milestone,json=chromeMilestone,proto3" json:"chrome_milestone,omitempty"`
+	Description          string   `protobuf:"bytes,7,opt,name=description,proto3" json:"description,omitempty"`
+	Keyset               string   `protobuf:"bytes,8,opt,name=keyset,proto3" json:"keyset,omitempty"`
+	Name                 string   `protobuf:"bytes,9,opt,name=name,proto3" json:"name,omitempty"`
+	PatchNumber          string   `protobuf:"bytes,10,opt,name=patch_number,json=patchNumber,proto3" json:"patch_number,omitempty"`
+	Track                string   `protobuf:"bytes,11,opt,name=track,proto3" json:"track,omitempty"`
+	Version              string   `protobuf:"bytes,12,opt,name=version,proto3" json:"version,omitempty"`
+	XXX_NoUnkeyedLiteral struct{} `json:"-"`
+	XXX_unrecognized     []byte   `json:"-"`
+	XXX_sizecache        int32    `json:"-"`
+}
+
+func (m *SoftwareConfig_ChromeOS) Reset()         { *m = SoftwareConfig_ChromeOS{} }
+func (m *SoftwareConfig_ChromeOS) String() string { return proto.CompactTextString(m) }
+func (*SoftwareConfig_ChromeOS) ProtoMessage()    {}
+func (*SoftwareConfig_ChromeOS) Descriptor() ([]byte, []int) {
+	return fileDescriptor_9bb41260180eeb52, []int{0, 0}
+}
+
+func (m *SoftwareConfig_ChromeOS) XXX_Unmarshal(b []byte) error {
+	return xxx_messageInfo_SoftwareConfig_ChromeOS.Unmarshal(m, b)
+}
+func (m *SoftwareConfig_ChromeOS) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	return xxx_messageInfo_SoftwareConfig_ChromeOS.Marshal(b, m, deterministic)
+}
+func (m *SoftwareConfig_ChromeOS) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_SoftwareConfig_ChromeOS.Merge(m, src)
+}
+func (m *SoftwareConfig_ChromeOS) XXX_Size() int {
+	return xxx_messageInfo_SoftwareConfig_ChromeOS.Size(m)
+}
+func (m *SoftwareConfig_ChromeOS) XXX_DiscardUnknown() {
+	xxx_messageInfo_SoftwareConfig_ChromeOS.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_SoftwareConfig_ChromeOS proto.InternalMessageInfo
+
+func (m *SoftwareConfig_ChromeOS) GetBoard() string {
+	if m != nil {
+		return m.Board
+	}
+	return ""
+}
+
+func (m *SoftwareConfig_ChromeOS) GetBranchNumber() uint32 {
+	if m != nil {
+		return m.BranchNumber
+	}
+	return 0
+}
+
+func (m *SoftwareConfig_ChromeOS) GetBuilderPath() string {
+	if m != nil {
+		return m.BuilderPath
+	}
+	return ""
+}
+
+func (m *SoftwareConfig_ChromeOS) GetBuildNumber() uint32 {
+	if m != nil {
+		return m.BuildNumber
+	}
+	return 0
+}
+
+func (m *SoftwareConfig_ChromeOS) GetBuildType() string {
+	if m != nil {
+		return m.BuildType
+	}
+	return ""
+}
+
+func (m *SoftwareConfig_ChromeOS) GetChromeMilestone() uint32 {
+	if m != nil {
+		return m.ChromeMilestone
+	}
+	return 0
+}
+
+func (m *SoftwareConfig_ChromeOS) GetDescription() string {
+	if m != nil {
+		return m.Description
+	}
+	return ""
+}
+
+func (m *SoftwareConfig_ChromeOS) GetKeyset() string {
+	if m != nil {
+		return m.Keyset
+	}
+	return ""
+}
+
+func (m *SoftwareConfig_ChromeOS) GetName() string {
+	if m != nil {
+		return m.Name
+	}
+	return ""
+}
+
+func (m *SoftwareConfig_ChromeOS) GetPatchNumber() string {
+	if m != nil {
+		return m.PatchNumber
+	}
+	return ""
+}
+
+func (m *SoftwareConfig_ChromeOS) GetTrack() string {
+	if m != nil {
+		return m.Track
+	}
+	return ""
+}
+
+func (m *SoftwareConfig_ChromeOS) GetVersion() string {
+	if m != nil {
+		return m.Version
+	}
+	return ""
+}
+
+type SoftwareConfig_OS struct {
+	BuildId              string   `protobuf:"bytes,1,opt,name=build_id,json=buildId,proto3" json:"build_id,omitempty"`
+	Codename             string   `protobuf:"bytes,2,opt,name=codename,proto3" json:"codename,omitempty"`
+	Id                   string   `protobuf:"bytes,3,opt,name=id,proto3" json:"id,omitempty"`
+	Name                 string   `protobuf:"bytes,4,opt,name=name,proto3" json:"name,omitempty"`
+	PrettyName           string   `protobuf:"bytes,5,opt,name=pretty_name,json=prettyName,proto3" json:"pretty_name,omitempty"`
+	VersionId            string   `protobuf:"bytes,6,opt,name=version_id,json=versionId,proto3" json:"version_id,omitempty"`
+	Version              string   `protobuf:"bytes,7,opt,name=version,proto3" json:"version,omitempty"`
+	XXX_NoUnkeyedLiteral struct{} `json:"-"`
+	XXX_unrecognized     []byte   `json:"-"`
+	XXX_sizecache        int32    `json:"-"`
+}
+
+func (m *SoftwareConfig_OS) Reset()         { *m = SoftwareConfig_OS{} }
+func (m *SoftwareConfig_OS) String() string { return proto.CompactTextString(m) }
+func (*SoftwareConfig_OS) ProtoMessage()    {}
+func (*SoftwareConfig_OS) Descriptor() ([]byte, []int) {
+	return fileDescriptor_9bb41260180eeb52, []int{0, 1}
+}
+
+func (m *SoftwareConfig_OS) XXX_Unmarshal(b []byte) error {
+	return xxx_messageInfo_SoftwareConfig_OS.Unmarshal(m, b)
+}
+func (m *SoftwareConfig_OS) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	return xxx_messageInfo_SoftwareConfig_OS.Marshal(b, m, deterministic)
+}
+func (m *SoftwareConfig_OS) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_SoftwareConfig_OS.Merge(m, src)
+}
+func (m *SoftwareConfig_OS) XXX_Size() int {
+	return xxx_messageInfo_SoftwareConfig_OS.Size(m)
+}
+func (m *SoftwareConfig_OS) XXX_DiscardUnknown() {
+	xxx_messageInfo_SoftwareConfig_OS.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_SoftwareConfig_OS proto.InternalMessageInfo
+
+func (m *SoftwareConfig_OS) GetBuildId() string {
+	if m != nil {
+		return m.BuildId
+	}
+	return ""
+}
+
+func (m *SoftwareConfig_OS) GetCodename() string {
+	if m != nil {
+		return m.Codename
+	}
+	return ""
+}
+
+func (m *SoftwareConfig_OS) GetId() string {
+	if m != nil {
+		return m.Id
+	}
+	return ""
+}
+
+func (m *SoftwareConfig_OS) GetName() string {
+	if m != nil {
+		return m.Name
+	}
+	return ""
+}
+
+func (m *SoftwareConfig_OS) GetPrettyName() string {
+	if m != nil {
+		return m.PrettyName
+	}
+	return ""
+}
+
+func (m *SoftwareConfig_OS) GetVersionId() string {
+	if m != nil {
+		return m.VersionId
+	}
+	return ""
+}
+
+func (m *SoftwareConfig_OS) GetVersion() string {
+	if m != nil {
+		return m.Version
+	}
+	return ""
+}
+
+func init() {
+	proto.RegisterType((*SoftwareConfig)(nil), "test.custom_results.graphics.SoftwareConfig")
+	proto.RegisterType((*SoftwareConfig_ChromeOS)(nil), "test.custom_results.graphics.SoftwareConfig.ChromeOS")
+	proto.RegisterType((*SoftwareConfig_OS)(nil), "test.custom_results.graphics.SoftwareConfig.OS")
+}
+
+func init() {
+	proto.RegisterFile("test/custom_results/graphics/software_config.proto", fileDescriptor_9bb41260180eeb52)
+}
+
+var fileDescriptor_9bb41260180eeb52 = []byte{
+	// 639 bytes of a gzipped FileDescriptorProto
+	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x54, 0x41, 0x6f, 0xd3, 0x4c,
+	0x10, 0x55, 0xdc, 0x34, 0x89, 0xc7, 0x4d, 0xbf, 0x4f, 0xab, 0x0a, 0x99, 0x88, 0xaa, 0x01, 0x54,
+	0xa9, 0x70, 0xb0, 0xa5, 0xa2, 0x9e, 0x90, 0x40, 0x50, 0xa9, 0xa2, 0x07, 0xda, 0xe2, 0x54, 0x1c,
+	0xb8, 0x58, 0x1b, 0x7b, 0xe2, 0xac, 0x12, 0x7b, 0xad, 0xdd, 0x0d, 0x28, 0x3f, 0x8d, 0x9f, 0xc5,
+	0x85, 0x33, 0xf2, 0xac, 0x37, 0xa4, 0x97, 0x48, 0xe5, 0xe6, 0x79, 0xf3, 0x66, 0xfc, 0xde, 0xdb,
+	0xb5, 0xe1, 0xdc, 0xa0, 0x36, 0x71, 0xb6, 0xd2, 0x46, 0x96, 0xa9, 0x42, 0xbd, 0x5a, 0x1a, 0x1d,
+	0x17, 0x8a, 0xd7, 0x73, 0x91, 0xe9, 0x58, 0xcb, 0x99, 0xf9, 0xc1, 0x15, 0xa6, 0x99, 0xac, 0x66,
+	0xa2, 0x88, 0x6a, 0x25, 0x8d, 0x64, 0xcf, 0x9a, 0x99, 0xe8, 0xe1, 0x4c, 0xe4, 0x66, 0x46, 0x27,
+	0x85, 0x94, 0xc5, 0x12, 0x63, 0xe2, 0x4e, 0x57, 0xb3, 0xd8, 0x88, 0x12, 0xb5, 0xe1, 0x65, 0x6d,
+	0xc7, 0x47, 0xaf, 0x77, 0xbe, 0xb2, 0xe6, 0xd9, 0x82, 0x17, 0xd8, 0x72, 0x2f, 0x1e, 0x23, 0x2f,
+	0x15, 0xb9, 0x1d, 0x7b, 0xf1, 0x6b, 0x00, 0x87, 0x93, 0xb6, 0x79, 0x49, 0x3d, 0xf6, 0x0e, 0x3c,
+	0x91, 0x87, 0x9d, 0x71, 0xe7, 0x2c, 0x38, 0x8f, 0xa2, 0x5d, 0x0e, 0xa2, 0x87, 0x93, 0xd7, 0x79,
+	0xe2, 0x89, 0x9c, 0xbd, 0x85, 0x20, 0x53, 0xc8, 0x0d, 0xa6, 0x8d, 0x9f, 0xd0, 0xa3, 0x45, 0xa3,
+	0xc8, 0x9a, 0x8d, 0x9c, 0xd9, 0xe8, 0xde, 0x99, 0x4d, 0xc0, 0xd2, 0x1b, 0x80, 0x5d, 0x41, 0xaf,
+	0xe6, 0x0a, 0x2b, 0x13, 0xee, 0xfd, 0x93, 0x80, 0x76, 0x9a, 0x7d, 0x80, 0x41, 0x9b, 0x8f, 0x0e,
+	0xbb, 0xe3, 0xbd, 0xb3, 0xe0, 0xfc, 0x74, 0xf7, 0xa6, 0x3b, 0xcb, 0x4e, 0x36, 0x63, 0xec, 0x14,
+	0x0e, 0x17, 0xa8, 0x2a, 0x5c, 0xa6, 0x0a, 0x97, 0xc8, 0x35, 0x86, 0xfb, 0xe3, 0xce, 0x99, 0x9f,
+	0x0c, 0x2d, 0x9a, 0x58, 0x70, 0x8b, 0xf6, 0x1d, 0x95, 0x16, 0xb2, 0x0a, 0x7b, 0xdb, 0xb4, 0xaf,
+	0x16, 0x64, 0x5f, 0x60, 0x90, 0xcd, 0x95, 0x2c, 0x51, 0xea, 0xb0, 0x4f, 0xd6, 0x2e, 0x1e, 0x63,
+	0x2d, 0xba, 0xa4, 0xe1, 0xdb, 0x49, 0xb2, 0x59, 0xc3, 0xde, 0x83, 0x27, 0x75, 0x38, 0xa0, 0x65,
+	0xf1, 0xa3, 0x96, 0xdd, 0x4e, 0x12, 0x4f, 0x6a, 0xf6, 0x1c, 0x0e, 0xa6, 0x42, 0xea, 0x8d, 0x70,
+	0x9f, 0x84, 0x07, 0x0d, 0xe6, 0x64, 0x1f, 0x03, 0x60, 0xb6, 0x21, 0x00, 0x11, 0x7c, 0xcc, 0xda,
+	0xf6, 0xe8, 0xb7, 0x07, 0x03, 0xa7, 0x8c, 0x1d, 0xc1, 0xfe, 0x54, 0x72, 0x65, 0xef, 0x8e, 0x9f,
+	0xd8, 0x82, 0xbd, 0x84, 0xe1, 0x54, 0xf1, 0x2a, 0x9b, 0xa7, 0xd5, 0xaa, 0x9c, 0xa2, 0xa2, 0x0b,
+	0x31, 0x4c, 0x0e, 0x2c, 0x78, 0x43, 0x18, 0x29, 0x59, 0x89, 0x65, 0x8e, 0x2a, 0xad, 0xb9, 0x99,
+	0xd3, 0xe1, 0x37, 0x4a, 0x2c, 0x76, 0xc7, 0xcd, 0x7c, 0x43, 0x71, 0x6b, 0xba, 0xb4, 0xc6, 0x52,
+	0xda, 0x2d, 0xc7, 0x00, 0x96, 0x62, 0xd6, 0xb5, 0x3b, 0x2d, 0x9f, 0x90, 0xfb, 0x75, 0x8d, 0xec,
+	0x15, 0xfc, 0x6f, 0xb3, 0x4b, 0x4b, 0xb1, 0x44, 0x6d, 0x64, 0x85, 0x74, 0x56, 0xc3, 0xe4, 0x3f,
+	0x8b, 0x7f, 0x76, 0x30, 0x1b, 0x43, 0x90, 0xa3, 0xce, 0x94, 0xa8, 0x4d, 0xe3, 0xbb, 0x6f, 0xe5,
+	0x6c, 0x41, 0xec, 0x09, 0xf4, 0x16, 0xb8, 0xd6, 0x68, 0xe8, 0x00, 0xfc, 0xa4, 0xad, 0x18, 0x83,
+	0x6e, 0xc5, 0x4b, 0x6c, 0xb3, 0xa4, 0xe7, 0x46, 0x7a, 0xcd, 0xcd, 0xdf, 0x04, 0x6c, 0x8c, 0x01,
+	0x61, 0xad, 0xf4, 0x23, 0xd8, 0x37, 0x8a, 0x67, 0x8b, 0x30, 0xb0, 0xd9, 0x51, 0xc1, 0x42, 0xe8,
+	0xbb, 0xe8, 0x0f, 0x08, 0x77, 0xe5, 0xe8, 0x67, 0x07, 0xbc, 0xdb, 0x09, 0x7b, 0x0a, 0x03, 0xeb,
+	0x58, 0xb8, 0xd4, 0xfb, 0x54, 0x5f, 0xe7, 0x6c, 0x04, 0x83, 0x4c, 0xe6, 0x48, 0x62, 0x3c, 0x6a,
+	0x6d, 0x6a, 0x76, 0x48, 0x9f, 0xb8, 0x0d, 0xb9, 0xf9, 0x64, 0x9d, 0xe8, 0xee, 0x96, 0xe8, 0x13,
+	0x08, 0x6a, 0x85, 0xc6, 0xac, 0x53, 0x6a, 0xd9, 0x34, 0xc1, 0x42, 0x37, 0x0d, 0xe1, 0x18, 0xa0,
+	0x55, 0xd3, 0xbc, 0xdd, 0x5e, 0x7a, 0xbf, 0x45, 0xae, 0xf3, 0x6d, 0xed, 0xfd, 0x07, 0xda, 0x3f,
+	0x7e, 0xfa, 0x76, 0x55, 0xc8, 0x88, 0x22, 0x17, 0xab, 0x32, 0x92, 0xaa, 0x88, 0x5d, 0x21, 0x75,
+	0x2c, 0xaa, 0x99, 0xe2, 0xf6, 0x9f, 0x18, 0x17, 0x32, 0xde, 0xf5, 0x5b, 0x9b, 0xf6, 0x88, 0xf6,
+	0xe6, 0x4f, 0x00, 0x00, 0x00, 0xff, 0xff, 0x21, 0xf2, 0x23, 0x5b, 0x9c, 0x05, 0x00, 0x00,
+}
diff --git a/go/test/custom_results/graphics/software_config_id.pb.go b/go/test/custom_results/graphics/software_config_id.pb.go
new file mode 100644
index 0000000..5fac4ee
--- /dev/null
+++ b/go/test/custom_results/graphics/software_config_id.pb.go
@@ -0,0 +1,84 @@
+// Code generated by protoc-gen-go. DO NOT EDIT.
+// source: test/custom_results/graphics/software_config_id.proto
+
+package graphics
+
+import (
+	fmt "fmt"
+	proto "github.com/golang/protobuf/proto"
+	math "math"
+)
+
+// Reference imports to suppress errors if they are not otherwise used.
+var _ = proto.Marshal
+var _ = fmt.Errorf
+var _ = math.Inf
+
+// This is a compile-time assertion to ensure that this generated file
+// is compatible with the proto package it is being compiled against.
+// A compilation error at this line likely means your copy of the
+// proto package needs to be updated.
+const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package
+
+// Uniquely identifies a software configuration.
+type SoftwareConfigId struct {
+	Value                string   `protobuf:"bytes,1,opt,name=value,proto3" json:"value,omitempty"`
+	XXX_NoUnkeyedLiteral struct{} `json:"-"`
+	XXX_unrecognized     []byte   `json:"-"`
+	XXX_sizecache        int32    `json:"-"`
+}
+
+func (m *SoftwareConfigId) Reset()         { *m = SoftwareConfigId{} }
+func (m *SoftwareConfigId) String() string { return proto.CompactTextString(m) }
+func (*SoftwareConfigId) ProtoMessage()    {}
+func (*SoftwareConfigId) Descriptor() ([]byte, []int) {
+	return fileDescriptor_f06b79bed4c1413f, []int{0}
+}
+
+func (m *SoftwareConfigId) XXX_Unmarshal(b []byte) error {
+	return xxx_messageInfo_SoftwareConfigId.Unmarshal(m, b)
+}
+func (m *SoftwareConfigId) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	return xxx_messageInfo_SoftwareConfigId.Marshal(b, m, deterministic)
+}
+func (m *SoftwareConfigId) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_SoftwareConfigId.Merge(m, src)
+}
+func (m *SoftwareConfigId) XXX_Size() int {
+	return xxx_messageInfo_SoftwareConfigId.Size(m)
+}
+func (m *SoftwareConfigId) XXX_DiscardUnknown() {
+	xxx_messageInfo_SoftwareConfigId.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_SoftwareConfigId proto.InternalMessageInfo
+
+func (m *SoftwareConfigId) GetValue() string {
+	if m != nil {
+		return m.Value
+	}
+	return ""
+}
+
+func init() {
+	proto.RegisterType((*SoftwareConfigId)(nil), "test.custom_results.graphics.SoftwareConfigId")
+}
+
+func init() {
+	proto.RegisterFile("test/custom_results/graphics/software_config_id.proto", fileDescriptor_f06b79bed4c1413f)
+}
+
+var fileDescriptor_f06b79bed4c1413f = []byte{
+	// 163 bytes of a gzipped FileDescriptorProto
+	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x32, 0x2d, 0x49, 0x2d, 0x2e,
+	0xd1, 0x4f, 0x2e, 0x2d, 0x2e, 0xc9, 0xcf, 0x8d, 0x2f, 0x4a, 0x2d, 0x2e, 0xcd, 0x29, 0x29, 0xd6,
+	0x4f, 0x2f, 0x4a, 0x2c, 0xc8, 0xc8, 0x4c, 0x2e, 0xd6, 0x2f, 0xce, 0x4f, 0x2b, 0x29, 0x4f, 0x2c,
+	0x4a, 0x8d, 0x4f, 0xce, 0xcf, 0x4b, 0xcb, 0x4c, 0x8f, 0xcf, 0x4c, 0xd1, 0x2b, 0x28, 0xca, 0x2f,
+	0xc9, 0x17, 0x92, 0x01, 0x69, 0xd3, 0x43, 0xd5, 0xa6, 0x07, 0xd3, 0xa6, 0xa4, 0xc1, 0x25, 0x10,
+	0x0c, 0xd5, 0xe9, 0x0c, 0xd6, 0xe8, 0x99, 0x22, 0x24, 0xc2, 0xc5, 0x5a, 0x96, 0x98, 0x53, 0x9a,
+	0x2a, 0xc1, 0xa8, 0xc0, 0xa8, 0xc1, 0x19, 0x04, 0xe1, 0x38, 0x79, 0x44, 0xb9, 0xa5, 0xe7, 0xeb,
+	0x25, 0x67, 0x14, 0xe5, 0xe7, 0x66, 0x96, 0xe6, 0xea, 0xe5, 0x17, 0xa5, 0xeb, 0xc3, 0x38, 0xf9,
+	0xc5, 0xfa, 0x99, 0x79, 0x69, 0x45, 0x89, 0xfa, 0x60, 0x1b, 0xf5, 0xd3, 0xf3, 0xf5, 0xf1, 0x39,
+	0x35, 0x89, 0x0d, 0xac, 0xcc, 0x18, 0x10, 0x00, 0x00, 0xff, 0xff, 0x30, 0x5c, 0x15, 0x66, 0xd1,
+	0x00, 0x00, 0x00,
+}
diff --git a/go/test/custom_results/graphics/software_overrides_config.pb.go b/go/test/custom_results/graphics/software_overrides_config.pb.go
new file mode 100644
index 0000000..e88b5f2
--- /dev/null
+++ b/go/test/custom_results/graphics/software_overrides_config.pb.go
@@ -0,0 +1,86 @@
+// Code generated by protoc-gen-go. DO NOT EDIT.
+// source: test/custom_results/graphics/software_overrides_config.proto
+
+package graphics
+
+import (
+	fmt "fmt"
+	proto "github.com/golang/protobuf/proto"
+	math "math"
+)
+
+// Reference imports to suppress errors if they are not otherwise used.
+var _ = proto.Marshal
+var _ = fmt.Errorf
+var _ = math.Inf
+
+// This is a compile-time assertion to ensure that this generated file
+// is compatible with the proto package it is being compiled against.
+// A compilation error at this line likely means your copy of the
+// proto package needs to be updated.
+const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package
+
+// Next Tag: 2
+type SoftwareOverridesConfig struct {
+	// Packages that were explicitly overriden from the normal system softare.
+	Packages             []*Package `protobuf:"bytes,1,rep,name=packages,proto3" json:"packages,omitempty"`
+	XXX_NoUnkeyedLiteral struct{}   `json:"-"`
+	XXX_unrecognized     []byte     `json:"-"`
+	XXX_sizecache        int32      `json:"-"`
+}
+
+func (m *SoftwareOverridesConfig) Reset()         { *m = SoftwareOverridesConfig{} }
+func (m *SoftwareOverridesConfig) String() string { return proto.CompactTextString(m) }
+func (*SoftwareOverridesConfig) ProtoMessage()    {}
+func (*SoftwareOverridesConfig) Descriptor() ([]byte, []int) {
+	return fileDescriptor_e71e3c9a6580d8a0, []int{0}
+}
+
+func (m *SoftwareOverridesConfig) XXX_Unmarshal(b []byte) error {
+	return xxx_messageInfo_SoftwareOverridesConfig.Unmarshal(m, b)
+}
+func (m *SoftwareOverridesConfig) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	return xxx_messageInfo_SoftwareOverridesConfig.Marshal(b, m, deterministic)
+}
+func (m *SoftwareOverridesConfig) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_SoftwareOverridesConfig.Merge(m, src)
+}
+func (m *SoftwareOverridesConfig) XXX_Size() int {
+	return xxx_messageInfo_SoftwareOverridesConfig.Size(m)
+}
+func (m *SoftwareOverridesConfig) XXX_DiscardUnknown() {
+	xxx_messageInfo_SoftwareOverridesConfig.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_SoftwareOverridesConfig proto.InternalMessageInfo
+
+func (m *SoftwareOverridesConfig) GetPackages() []*Package {
+	if m != nil {
+		return m.Packages
+	}
+	return nil
+}
+
+func init() {
+	proto.RegisterType((*SoftwareOverridesConfig)(nil), "test.custom_results.graphics.SoftwareOverridesConfig")
+}
+
+func init() {
+	proto.RegisterFile("test/custom_results/graphics/software_overrides_config.proto", fileDescriptor_e71e3c9a6580d8a0)
+}
+
+var fileDescriptor_e71e3c9a6580d8a0 = []byte{
+	// 192 bytes of a gzipped FileDescriptorProto
+	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x7c, 0x8e, 0x3f, 0x8b, 0xc2, 0x40,
+	0x10, 0x47, 0x39, 0x0e, 0x8e, 0x23, 0x76, 0x69, 0x14, 0xb1, 0x10, 0x41, 0x10, 0x8b, 0x19, 0xd0,
+	0xd6, 0x46, 0x05, 0xb1, 0x53, 0xb4, 0x13, 0x21, 0xac, 0xeb, 0x66, 0xb3, 0x68, 0x32, 0x61, 0x66,
+	0xa3, 0x5f, 0x5f, 0xcc, 0x1f, 0xc1, 0x26, 0xe5, 0xc0, 0x7b, 0xf3, 0x7e, 0xc1, 0xc2, 0x1b, 0xf1,
+	0xa8, 0x0b, 0xf1, 0x94, 0x46, 0x6c, 0xa4, 0xb8, 0x7b, 0x41, 0xcb, 0x2a, 0x4f, 0x9c, 0x16, 0x14,
+	0x8a, 0xfd, 0x53, 0xb1, 0x89, 0xe8, 0x61, 0x98, 0xdd, 0xd5, 0x48, 0xa4, 0x29, 0x8b, 0x9d, 0x85,
+	0x9c, 0xc9, 0x53, 0x38, 0x78, 0xdb, 0xf0, 0x6d, 0x43, 0x63, 0xf7, 0xa7, 0xad, 0xbf, 0x73, 0xa5,
+	0x6f, 0xca, 0x9a, 0xea, 0xd3, 0xe8, 0x1c, 0x74, 0x8f, 0x75, 0x6c, 0xd7, 0xb4, 0xd6, 0x65, 0x2a,
+	0x5c, 0x06, 0xff, 0x35, 0x2b, 0xbd, 0x9f, 0xe1, 0xef, 0xa4, 0x33, 0x1b, 0x43, 0x5b, 0x17, 0xf6,
+	0x15, 0x7d, 0xf8, 0x68, 0xab, 0xed, 0x69, 0x63, 0x09, 0x74, 0xc2, 0x94, 0xba, 0x22, 0x05, 0x62,
+	0x8b, 0xcd, 0x41, 0x82, 0x2e, 0x8b, 0x59, 0x61, 0xb9, 0x03, 0x2d, 0x61, 0xdb, 0xea, 0xcb, 0x5f,
+	0x89, 0xcd, 0x5f, 0x01, 0x00, 0x00, 0xff, 0xff, 0x87, 0x60, 0xda, 0xd6, 0x38, 0x01, 0x00, 0x00,
+}
diff --git a/go/test/custom_results/graphics/trace.pb.go b/go/test/custom_results/graphics/trace.pb.go
new file mode 100644
index 0000000..0ab2668
--- /dev/null
+++ b/go/test/custom_results/graphics/trace.pb.go
@@ -0,0 +1,257 @@
+// Code generated by protoc-gen-go. DO NOT EDIT.
+// source: test/custom_results/graphics/trace.proto
+
+package graphics
+
+import (
+	fmt "fmt"
+	proto "github.com/golang/protobuf/proto"
+	math "math"
+)
+
+// Reference imports to suppress errors if they are not otherwise used.
+var _ = proto.Marshal
+var _ = fmt.Errorf
+var _ = math.Inf
+
+// This is a compile-time assertion to ensure that this generated file
+// is compatible with the proto package it is being compiled against.
+// A compilation error at this line likely means your copy of the
+// proto package needs to be updated.
+const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package
+
+// Details about a graphics trace file.
+// Next Tag: 10
+type Trace struct {
+	// Global unique trace identifier.
+	Id       *TraceId `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`
+	Filename string   `protobuf:"bytes,2,opt,name=filename,proto3" json:"filename,omitempty"`
+	Size     uint64   `protobuf:"varint,3,opt,name=size,proto3" json:"size,omitempty"`
+	// Source of the trace.
+	Source string `protobuf:"bytes,4,opt,name=source,proto3" json:"source,omitempty"`
+	// Source specific identifier for the program being traced. (eg Steam ID)
+	ApplicationId string `protobuf:"bytes,5,opt,name=application_id,json=applicationId,proto3" json:"application_id,omitempty"`
+	// Number of frames in the trace.
+	FrameCount uint32 `protobuf:"varint,6,opt,name=frame_count,json=frameCount,proto3" json:"frame_count,omitempty"`
+	// The range of frames after the game began to interact.
+	FrameRange *Trace_Range `protobuf:"bytes,7,opt,name=frame_range,json=frameRange,proto3" json:"frame_range,omitempty"`
+	// Frames that are worth checking for pixel correctness.
+	KeyFrames []uint32 `protobuf:"varint,8,rep,packed,name=key_frames,json=keyFrames,proto3" json:"key_frames,omitempty"`
+	// Frames that are worth looping on to gauge performance.
+	LoopFrames           []uint32 `protobuf:"varint,9,rep,packed,name=loop_frames,json=loopFrames,proto3" json:"loop_frames,omitempty"`
+	XXX_NoUnkeyedLiteral struct{} `json:"-"`
+	XXX_unrecognized     []byte   `json:"-"`
+	XXX_sizecache        int32    `json:"-"`
+}
+
+func (m *Trace) Reset()         { *m = Trace{} }
+func (m *Trace) String() string { return proto.CompactTextString(m) }
+func (*Trace) ProtoMessage()    {}
+func (*Trace) Descriptor() ([]byte, []int) {
+	return fileDescriptor_96110b6982059ac3, []int{0}
+}
+
+func (m *Trace) XXX_Unmarshal(b []byte) error {
+	return xxx_messageInfo_Trace.Unmarshal(m, b)
+}
+func (m *Trace) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	return xxx_messageInfo_Trace.Marshal(b, m, deterministic)
+}
+func (m *Trace) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_Trace.Merge(m, src)
+}
+func (m *Trace) XXX_Size() int {
+	return xxx_messageInfo_Trace.Size(m)
+}
+func (m *Trace) XXX_DiscardUnknown() {
+	xxx_messageInfo_Trace.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_Trace proto.InternalMessageInfo
+
+func (m *Trace) GetId() *TraceId {
+	if m != nil {
+		return m.Id
+	}
+	return nil
+}
+
+func (m *Trace) GetFilename() string {
+	if m != nil {
+		return m.Filename
+	}
+	return ""
+}
+
+func (m *Trace) GetSize() uint64 {
+	if m != nil {
+		return m.Size
+	}
+	return 0
+}
+
+func (m *Trace) GetSource() string {
+	if m != nil {
+		return m.Source
+	}
+	return ""
+}
+
+func (m *Trace) GetApplicationId() string {
+	if m != nil {
+		return m.ApplicationId
+	}
+	return ""
+}
+
+func (m *Trace) GetFrameCount() uint32 {
+	if m != nil {
+		return m.FrameCount
+	}
+	return 0
+}
+
+func (m *Trace) GetFrameRange() *Trace_Range {
+	if m != nil {
+		return m.FrameRange
+	}
+	return nil
+}
+
+func (m *Trace) GetKeyFrames() []uint32 {
+	if m != nil {
+		return m.KeyFrames
+	}
+	return nil
+}
+
+func (m *Trace) GetLoopFrames() []uint32 {
+	if m != nil {
+		return m.LoopFrames
+	}
+	return nil
+}
+
+type Trace_Range struct {
+	Start                uint32   `protobuf:"varint,1,opt,name=start,proto3" json:"start,omitempty"`
+	End                  uint32   `protobuf:"varint,2,opt,name=end,proto3" json:"end,omitempty"`
+	XXX_NoUnkeyedLiteral struct{} `json:"-"`
+	XXX_unrecognized     []byte   `json:"-"`
+	XXX_sizecache        int32    `json:"-"`
+}
+
+func (m *Trace_Range) Reset()         { *m = Trace_Range{} }
+func (m *Trace_Range) String() string { return proto.CompactTextString(m) }
+func (*Trace_Range) ProtoMessage()    {}
+func (*Trace_Range) Descriptor() ([]byte, []int) {
+	return fileDescriptor_96110b6982059ac3, []int{0, 0}
+}
+
+func (m *Trace_Range) XXX_Unmarshal(b []byte) error {
+	return xxx_messageInfo_Trace_Range.Unmarshal(m, b)
+}
+func (m *Trace_Range) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	return xxx_messageInfo_Trace_Range.Marshal(b, m, deterministic)
+}
+func (m *Trace_Range) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_Trace_Range.Merge(m, src)
+}
+func (m *Trace_Range) XXX_Size() int {
+	return xxx_messageInfo_Trace_Range.Size(m)
+}
+func (m *Trace_Range) XXX_DiscardUnknown() {
+	xxx_messageInfo_Trace_Range.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_Trace_Range proto.InternalMessageInfo
+
+func (m *Trace_Range) GetStart() uint32 {
+	if m != nil {
+		return m.Start
+	}
+	return 0
+}
+
+func (m *Trace_Range) GetEnd() uint32 {
+	if m != nil {
+		return m.End
+	}
+	return 0
+}
+
+type TraceList struct {
+	Value                []*Trace `protobuf:"bytes,1,rep,name=value,proto3" json:"value,omitempty"`
+	XXX_NoUnkeyedLiteral struct{} `json:"-"`
+	XXX_unrecognized     []byte   `json:"-"`
+	XXX_sizecache        int32    `json:"-"`
+}
+
+func (m *TraceList) Reset()         { *m = TraceList{} }
+func (m *TraceList) String() string { return proto.CompactTextString(m) }
+func (*TraceList) ProtoMessage()    {}
+func (*TraceList) Descriptor() ([]byte, []int) {
+	return fileDescriptor_96110b6982059ac3, []int{1}
+}
+
+func (m *TraceList) XXX_Unmarshal(b []byte) error {
+	return xxx_messageInfo_TraceList.Unmarshal(m, b)
+}
+func (m *TraceList) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	return xxx_messageInfo_TraceList.Marshal(b, m, deterministic)
+}
+func (m *TraceList) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_TraceList.Merge(m, src)
+}
+func (m *TraceList) XXX_Size() int {
+	return xxx_messageInfo_TraceList.Size(m)
+}
+func (m *TraceList) XXX_DiscardUnknown() {
+	xxx_messageInfo_TraceList.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_TraceList proto.InternalMessageInfo
+
+func (m *TraceList) GetValue() []*Trace {
+	if m != nil {
+		return m.Value
+	}
+	return nil
+}
+
+func init() {
+	proto.RegisterType((*Trace)(nil), "test.custom_results.graphics.Trace")
+	proto.RegisterType((*Trace_Range)(nil), "test.custom_results.graphics.Trace.Range")
+	proto.RegisterType((*TraceList)(nil), "test.custom_results.graphics.TraceList")
+}
+
+func init() {
+	proto.RegisterFile("test/custom_results/graphics/trace.proto", fileDescriptor_96110b6982059ac3)
+}
+
+var fileDescriptor_96110b6982059ac3 = []byte{
+	// 373 bytes of a gzipped FileDescriptorProto
+	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x92, 0xc1, 0x6b, 0xdb, 0x30,
+	0x14, 0xc6, 0x71, 0x1c, 0x67, 0xf1, 0x0b, 0x1e, 0x43, 0x8c, 0x21, 0xc2, 0xc6, 0x4c, 0x46, 0xc0,
+	0x63, 0x20, 0x41, 0x46, 0x0f, 0xbd, 0xb6, 0x10, 0x9a, 0xd2, 0x93, 0xe8, 0xa9, 0x17, 0xa3, 0xda,
+	0x8a, 0x23, 0x62, 0x5b, 0x46, 0x92, 0x0b, 0xe9, 0xbf, 0xd0, 0x7f, 0xba, 0x58, 0x8e, 0x4b, 0x7b,
+	0x49, 0x73, 0x7b, 0xdf, 0xf7, 0x7e, 0xef, 0xb3, 0x9e, 0x2c, 0x48, 0xac, 0x30, 0x96, 0x66, 0xad,
+	0xb1, 0xaa, 0x4a, 0xb5, 0x30, 0x6d, 0x69, 0x0d, 0x2d, 0x34, 0x6f, 0x76, 0x32, 0x33, 0xd4, 0x6a,
+	0x9e, 0x09, 0xd2, 0x68, 0x65, 0x15, 0xfa, 0xd9, 0x91, 0xe4, 0x23, 0x49, 0x06, 0x72, 0xfe, 0xef,
+	0xf3, 0x9c, 0x54, 0xe6, 0x7d, 0xd4, 0xe2, 0xc5, 0x87, 0xe0, 0xbe, 0xb3, 0xd0, 0x05, 0x8c, 0x64,
+	0x8e, 0xbd, 0xd8, 0x4b, 0x66, 0xab, 0x25, 0x39, 0xf5, 0x05, 0xe2, 0x06, 0x36, 0x39, 0x1b, 0xc9,
+	0x1c, 0xcd, 0x61, 0xba, 0x95, 0xa5, 0xa8, 0x79, 0x25, 0xf0, 0x28, 0xf6, 0x92, 0x90, 0xbd, 0x69,
+	0x84, 0x60, 0x6c, 0xe4, 0xb3, 0xc0, 0x7e, 0xec, 0x25, 0x63, 0xe6, 0x6a, 0xf4, 0x03, 0x26, 0x46,
+	0xb5, 0x3a, 0x13, 0x78, 0xec, 0xe8, 0xa3, 0x42, 0x4b, 0xf8, 0xca, 0x9b, 0xa6, 0x94, 0x19, 0xb7,
+	0x52, 0xd5, 0xa9, 0xcc, 0x71, 0xe0, 0xfa, 0xd1, 0x3b, 0x77, 0x93, 0xa3, 0xdf, 0x30, 0xdb, 0x6a,
+	0x5e, 0x89, 0x34, 0x53, 0x6d, 0x6d, 0xf1, 0x24, 0xf6, 0x92, 0x88, 0x81, 0xb3, 0xae, 0x3b, 0x07,
+	0xdd, 0x0e, 0x80, 0xe6, 0x75, 0x21, 0xf0, 0x17, 0xb7, 0xcf, 0xdf, 0x33, 0xf6, 0x21, 0xac, 0x1b,
+	0x38, 0x66, 0xb9, 0x1a, 0xfd, 0x02, 0xd8, 0x8b, 0x43, 0xea, 0x1c, 0x83, 0xa7, 0xb1, 0x9f, 0x44,
+	0x2c, 0xdc, 0x8b, 0xc3, 0xda, 0x19, 0xdd, 0x59, 0x4a, 0xa5, 0x9a, 0xa1, 0x1f, 0xba, 0x3e, 0x74,
+	0x56, 0x0f, 0xcc, 0x29, 0x04, 0x7d, 0xd0, 0x77, 0x08, 0x8c, 0xe5, 0xda, 0xba, 0xeb, 0x8d, 0x58,
+	0x2f, 0xd0, 0x37, 0xf0, 0x45, 0x9d, 0xbb, 0x5b, 0x8b, 0x58, 0x57, 0x2e, 0xd6, 0x10, 0xba, 0xb3,
+	0xdc, 0x49, 0x63, 0xd1, 0x25, 0x04, 0x4f, 0xbc, 0x6c, 0x05, 0xf6, 0x62, 0x3f, 0x99, 0xad, 0xfe,
+	0x9c, 0xb1, 0x03, 0xeb, 0x27, 0xae, 0x6e, 0x1e, 0xd6, 0x85, 0x22, 0xd9, 0x4e, 0xab, 0x4a, 0xb6,
+	0x15, 0x51, 0xba, 0xa0, 0x83, 0x50, 0x86, 0xca, 0x7a, 0xab, 0x39, 0x75, 0xff, 0x9f, 0x16, 0x8a,
+	0x9e, 0x7a, 0x2e, 0x8f, 0x13, 0x87, 0xfd, 0x7f, 0x0d, 0x00, 0x00, 0xff, 0xff, 0x2f, 0xb0, 0x35,
+	0x75, 0x9d, 0x02, 0x00, 0x00,
+}
diff --git a/go/test/custom_results/graphics/trace_id.pb.go b/go/test/custom_results/graphics/trace_id.pb.go
new file mode 100644
index 0000000..5ca040a
--- /dev/null
+++ b/go/test/custom_results/graphics/trace_id.pb.go
@@ -0,0 +1,83 @@
+// Code generated by protoc-gen-go. DO NOT EDIT.
+// source: test/custom_results/graphics/trace_id.proto
+
+package graphics
+
+import (
+	fmt "fmt"
+	proto "github.com/golang/protobuf/proto"
+	math "math"
+)
+
+// Reference imports to suppress errors if they are not otherwise used.
+var _ = proto.Marshal
+var _ = fmt.Errorf
+var _ = math.Inf
+
+// This is a compile-time assertion to ensure that this generated file
+// is compatible with the proto package it is being compiled against.
+// A compilation error at this line likely means your copy of the
+// proto package needs to be updated.
+const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package
+
+// Uniquely identifies a trace used for replay tests.
+type TraceId struct {
+	Value                string   `protobuf:"bytes,1,opt,name=value,proto3" json:"value,omitempty"`
+	XXX_NoUnkeyedLiteral struct{} `json:"-"`
+	XXX_unrecognized     []byte   `json:"-"`
+	XXX_sizecache        int32    `json:"-"`
+}
+
+func (m *TraceId) Reset()         { *m = TraceId{} }
+func (m *TraceId) String() string { return proto.CompactTextString(m) }
+func (*TraceId) ProtoMessage()    {}
+func (*TraceId) Descriptor() ([]byte, []int) {
+	return fileDescriptor_571f68198e362eb7, []int{0}
+}
+
+func (m *TraceId) XXX_Unmarshal(b []byte) error {
+	return xxx_messageInfo_TraceId.Unmarshal(m, b)
+}
+func (m *TraceId) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	return xxx_messageInfo_TraceId.Marshal(b, m, deterministic)
+}
+func (m *TraceId) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_TraceId.Merge(m, src)
+}
+func (m *TraceId) XXX_Size() int {
+	return xxx_messageInfo_TraceId.Size(m)
+}
+func (m *TraceId) XXX_DiscardUnknown() {
+	xxx_messageInfo_TraceId.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_TraceId proto.InternalMessageInfo
+
+func (m *TraceId) GetValue() string {
+	if m != nil {
+		return m.Value
+	}
+	return ""
+}
+
+func init() {
+	proto.RegisterType((*TraceId)(nil), "test.custom_results.graphics.TraceId")
+}
+
+func init() {
+	proto.RegisterFile("test/custom_results/graphics/trace_id.proto", fileDescriptor_571f68198e362eb7)
+}
+
+var fileDescriptor_571f68198e362eb7 = []byte{
+	// 150 bytes of a gzipped FileDescriptorProto
+	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xd2, 0x2e, 0x49, 0x2d, 0x2e,
+	0xd1, 0x4f, 0x2e, 0x2d, 0x2e, 0xc9, 0xcf, 0x8d, 0x2f, 0x4a, 0x2d, 0x2e, 0xcd, 0x29, 0x29, 0xd6,
+	0x4f, 0x2f, 0x4a, 0x2c, 0xc8, 0xc8, 0x4c, 0x2e, 0xd6, 0x2f, 0x29, 0x4a, 0x4c, 0x4e, 0x8d, 0xcf,
+	0x4c, 0xd1, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x92, 0x01, 0x29, 0xd6, 0x43, 0x55, 0xac, 0x07,
+	0x53, 0xac, 0x24, 0xcf, 0xc5, 0x1e, 0x02, 0x52, 0xef, 0x99, 0x22, 0x24, 0xc2, 0xc5, 0x5a, 0x96,
+	0x98, 0x53, 0x9a, 0x2a, 0xc1, 0xa8, 0xc0, 0xa8, 0xc1, 0x19, 0x04, 0xe1, 0x38, 0x79, 0x44, 0xb9,
+	0xa5, 0xe7, 0xeb, 0x25, 0x67, 0x14, 0xe5, 0xe7, 0x66, 0x96, 0xe6, 0xea, 0xe5, 0x17, 0xa5, 0xeb,
+	0xc3, 0x38, 0xf9, 0xc5, 0xfa, 0x99, 0x79, 0x69, 0x45, 0x89, 0xfa, 0x60, 0x8b, 0xf4, 0xd3, 0xf3,
+	0xf5, 0xf1, 0xb9, 0x2b, 0x89, 0x0d, 0xac, 0xcc, 0x18, 0x10, 0x00, 0x00, 0xff, 0xff, 0xdc, 0xc0,
+	0xa9, 0x37, 0xbe, 0x00, 0x00, 0x00,
+}
diff --git a/src/test/custom_results/graphics/machine.proto b/src/test/custom_results/graphics/machine.proto
new file mode 100644
index 0000000..e81f896
--- /dev/null
+++ b/src/test/custom_results/graphics/machine.proto
@@ -0,0 +1,26 @@
+// Copyright 2020 The Chromium OS Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+syntax = "proto3";
+
+package test.custom_results.graphics;
+
+option go_package = "go.chromium.org/chromiumos/infra/proto/go/test/custom_results/graphics";
+
+import "google/protobuf/timestamp.proto";
+import "test/custom_results/graphics/machine_id.proto";
+
+// Next Tag: 5
+message Machine {
+  // Global unique machine identifier.
+  MachineId name = 1;
+
+  google.protobuf.Timestamp create_time = 2;
+
+  // Identity of owner.
+  string owner = 3;
+
+  // Hardware identification.
+  string hwid = 4;
+}
diff --git a/src/test/custom_results/graphics/machine_id.proto b/src/test/custom_results/graphics/machine_id.proto
new file mode 100644
index 0000000..1959b03
--- /dev/null
+++ b/src/test/custom_results/graphics/machine_id.proto
@@ -0,0 +1,14 @@
+// Copyright 2020 The Chromium OS Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+syntax = "proto3";
+
+package test.custom_results.graphics;
+
+option go_package = "go.chromium.org/chromiumos/infra/proto/go/test/custom_results/graphics";
+
+// Uniquely identifies a machine.
+message MachineId {
+  string value = 1;
+}
diff --git a/src/test/custom_results/graphics/package.proto b/src/test/custom_results/graphics/package.proto
new file mode 100644
index 0000000..13e0dc4
--- /dev/null
+++ b/src/test/custom_results/graphics/package.proto
@@ -0,0 +1,30 @@
+// Copyright 2020 The Chromium OS Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+syntax = "proto3";
+
+package test.custom_results.graphics;
+
+option go_package = "go.chromium.org/chromiumos/infra/proto/go/test/custom_results/graphics";
+
+import "google/protobuf/timestamp.proto";
+
+// Next Tag: 7
+message Package {
+  string name = 1;
+  string version = 2;
+
+  // Hash of last commit in git repo.
+  string git_hash = 3;
+
+  // Git branch package was build from.
+  string branch = 4;
+
+  // Commit date of last commit in git repo.
+  google.protobuf.Timestamp commit_date = 5;
+
+  // For packages coming from git, indicate if the build was generated
+  // with a dirty git repo.
+  bool repo_dirty = 6;
+}
diff --git a/src/test/custom_results/graphics/result.proto b/src/test/custom_results/graphics/result.proto
new file mode 100644
index 0000000..04e8dd1
--- /dev/null
+++ b/src/test/custom_results/graphics/result.proto
@@ -0,0 +1,106 @@
+// Copyright 2020 The Chromium OS Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+syntax = "proto3";
+
+package test.custom_results.graphics;
+
+option go_package = "go.chromium.org/chromiumos/infra/proto/go/test/custom_results/graphics";
+
+import "google/protobuf/timestamp.proto";
+import "test/custom_results/graphics/machine_id.proto";
+import "test/custom_results/graphics/result_id.proto";
+import "test/custom_results/graphics/software_config_id.proto";
+import "test/custom_results/graphics/software_overrides_config.proto";
+import "test/custom_results/graphics/trace_id.proto";
+
+// Result of a single test, trace, or benchmark run.
+// Next Tag: 19
+message Result {
+  // Global unique result identifier.
+  ResultId id = 1;
+
+  // When the result started and finished being collected.
+  google.protobuf.Timestamp start_time = 2;
+  google.protobuf.Timestamp end_time = 3;
+
+  // Machine which generated the result.
+  MachineId machine = 4;
+
+  // Installed software at the time the result was collected.
+  SoftwareConfigId software_config = 5;
+
+  enum ExecutionEnvironment {
+    UNKNOWN = 0;
+    HOST = 1;
+    TERMINA = 2;
+    CROSTINI = 3;
+    STEAM = 4;
+    ARC = 5;
+    ARCVM = 6;
+    CROUTON = 7;
+    CROSVM = 8;
+  }
+  ExecutionEnvironment execution_environment = 6;
+
+  // Lab or user originating this result.
+  // Format:
+  // - lab/LABNAME
+  // - user/USERNAME
+  string invocation_source = 7;
+
+  // Details on the invocation if it was generated as part of a test.
+  // TODO(davidriley): Flesh these out better.
+  // TODO(davidriley): Record test status and error messages.
+  string test_id = 17;
+  string test_name = 8;
+  string test_job_id = 9;
+
+  // Command line used invoke the test.
+  string command_line = 10;
+
+  // Thing being tested.
+  string benchmark = 11;
+  TraceId trace = 12;
+
+  // TODO(davidriley): This unit could be made into a separate Message
+  // a) This stanza is directly part of TraceResult with TraceResult repeated.
+  // b) This stanze becomes a separate repeated Message within TraceResult.
+  // c) This stanza becomes a separate Message with TraceResultId link to them.
+  // Next Tag: 7
+  message Metric {
+    string name = 1;
+    uint64 index = 2;
+    double value = 3;
+    string units = 4;
+    bool larger_is_better = 5;
+    bool externally_gathered = 6;
+  }
+
+  // fps, frames, time
+  // usec for frame N
+  // cpu/gpu utilization/frequency
+  repeated Metric metrics = 13;
+
+  // Identify the most interesting metric to show by default for a given result.
+  string primary_metric_name = 14;
+
+  // General non-numeric details collected about the environment or system
+  // state.  eg Interesting environment variables, glxinfo info.
+  // Next Tag: 4
+  message Label {
+    string name = 1;
+    string value = 2;
+    string grouping = 3;
+  }
+  repeated Label labels = 15;
+
+  // Software that was explicitly overriden from the normal system software
+  // for a given result.
+  SoftwareOverridesConfig overrides = 18;
+}
+
+message ResultList {
+  repeated Result value = 1;
+}
diff --git a/src/test/custom_results/graphics/result_id.proto b/src/test/custom_results/graphics/result_id.proto
new file mode 100644
index 0000000..5d9f779
--- /dev/null
+++ b/src/test/custom_results/graphics/result_id.proto
@@ -0,0 +1,14 @@
+// Copyright 2020 The Chromium OS Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+syntax = "proto3";
+
+package test.custom_results.graphics;
+
+option go_package = "go.chromium.org/chromiumos/infra/proto/go/test/custom_results/graphics";
+
+// Uniquely identifies a test result.
+message ResultId {
+  string value = 1;
+}
diff --git a/src/test/custom_results/graphics/software_config.proto b/src/test/custom_results/graphics/software_config.proto
new file mode 100644
index 0000000..f9b38c5
--- /dev/null
+++ b/src/test/custom_results/graphics/software_config.proto
@@ -0,0 +1,65 @@
+// Copyright 2020 The Chromium OS Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+syntax = "proto3";
+
+package test.custom_results.graphics;
+
+option go_package = "go.chromium.org/chromiumos/infra/proto/go/test/custom_results/graphics";
+
+import "google/protobuf/timestamp.proto";
+import "test/custom_results/graphics/package.proto";
+import "test/custom_results/graphics/software_config_id.proto";
+
+// Software configuration of installed software on a device.
+// Next Tag: 11
+message SoftwareConfig {
+  // Global unique software configuration identifier.
+  SoftwareConfigId id = 1;
+
+  google.protobuf.Timestamp create_time = 2;
+
+  // TODO(davidriley): Decide if the hierarchy of the software config should
+  // be expressed with parent pointers or as part of the run.
+  // TODO(davidriley): How to handle same system invoked as chroot or VM?
+  // TODO(davidriley): How to handle crosvm vs qemu.
+
+  // For nested systems, the software configuration of the host system.
+  SoftwareConfigId parent = 3;
+
+  repeated Package packages = 4;
+
+  string kernel_release = 5;
+  string kernel_version = 6;
+
+  message ChromeOS {
+    string board = 1;
+    uint32 branch_number = 2;
+    string builder_path = 3;
+    uint32 build_number = 4;
+    string build_type = 5;
+    uint32 chrome_milestone = 6;
+    string description = 7;
+    string keyset = 8;
+    string name = 9;
+    string patch_number = 10;
+    string track = 11;
+    string version = 12;
+  }
+  ChromeOS chromeos = 7;
+
+  message OS {
+    string build_id = 1;
+    string codename = 2;
+    string id = 3;
+    string name = 4;
+    string pretty_name = 5;
+    string version_id = 6;
+    string version = 7;
+  }
+  OS os = 8;
+
+  string bios_version = 9;
+  string ec_version = 10;
+}
diff --git a/src/test/custom_results/graphics/software_config_id.proto b/src/test/custom_results/graphics/software_config_id.proto
new file mode 100644
index 0000000..f04e8e5
--- /dev/null
+++ b/src/test/custom_results/graphics/software_config_id.proto
@@ -0,0 +1,14 @@
+// Copyright 2020 The Chromium OS Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+syntax = "proto3";
+
+package test.custom_results.graphics;
+
+option go_package = "go.chromium.org/chromiumos/infra/proto/go/test/custom_results/graphics";
+
+// Uniquely identifies a software configuration.
+message SoftwareConfigId {
+  string value = 1;
+}
diff --git a/src/test/custom_results/graphics/software_overrides_config.proto b/src/test/custom_results/graphics/software_overrides_config.proto
new file mode 100644
index 0000000..4d8d616
--- /dev/null
+++ b/src/test/custom_results/graphics/software_overrides_config.proto
@@ -0,0 +1,17 @@
+// Copyright 2020 The Chromium OS Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+syntax = "proto3";
+
+package test.custom_results.graphics;
+
+option go_package = "go.chromium.org/chromiumos/infra/proto/go/test/custom_results/graphics";
+
+import "test/custom_results/graphics/package.proto";
+
+// Next Tag: 2
+message SoftwareOverridesConfig {
+  // Packages that were explicitly overriden from the normal system softare.
+  repeated Package packages = 1;
+}
diff --git a/src/test/custom_results/graphics/trace.proto b/src/test/custom_results/graphics/trace.proto
new file mode 100644
index 0000000..484c2de
--- /dev/null
+++ b/src/test/custom_results/graphics/trace.proto
@@ -0,0 +1,51 @@
+// Copyright 2020 The Chromium OS Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+syntax = "proto3";
+
+package test.custom_results.graphics;
+
+option go_package = "go.chromium.org/chromiumos/infra/proto/go/test/custom_results/graphics";
+
+import "test/custom_results/graphics/trace_id.proto";
+
+// Details about a graphics trace file.
+// Next Tag: 10
+message Trace {
+  // Global unique trace identifier.
+  TraceId id = 1;
+  string filename = 2;
+  uint64 size = 3;
+
+  // Source of the trace.
+  string source = 4;
+
+  // Source specific identifier for the program being traced. (eg Steam ID)
+  string application_id = 5;
+
+  // Number of frames in the trace.
+  uint32 frame_count = 6;
+
+  message Range {
+    uint32 start = 1;
+    uint32 end = 2;
+  }
+
+  // The range of frames after the game began to interact.
+  Range frame_range = 7;
+
+  // Frames that are worth checking for pixel correctness.
+  repeated uint32 key_frames = 8;
+
+  // Frames that are worth looping on to gauge performance.
+  repeated uint32 loop_frames = 9;
+
+  // TODO(davidriley): Add GL/Vulkan and profile.
+  // TODO(davidriley): Add extensions used.
+  // TODO(davidriley): Add compressed size?
+}
+
+message TraceList {
+  repeated Trace value = 1;
+}
diff --git a/src/test/custom_results/graphics/trace_id.proto b/src/test/custom_results/graphics/trace_id.proto
new file mode 100644
index 0000000..071e04c
--- /dev/null
+++ b/src/test/custom_results/graphics/trace_id.proto
@@ -0,0 +1,14 @@
+// Copyright 2020 The Chromium OS Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+syntax = "proto3";
+
+package test.custom_results.graphics;
+
+option go_package = "go.chromium.org/chromiumos/infra/proto/go/test/custom_results/graphics";
+
+// Uniquely identifies a trace used for replay tests.
+message TraceId {
+  string value = 1;
+}