Conversation
gapis/resolve/metrics.go
Outdated
|
|
||
| } | ||
|
|
||
| // FIXME DO NOT MERGE: Not sure where the best spot for this is, it can't go in gapis/api because api can't depend on service |
There was a problem hiding this comment.
This is likely not the best spot for this interface, maybe it should go in gapis/service along with the MemoryLayout proto definition?
There was a problem hiding this comment.
It most likely belongs in gapis/api. This is similar to the Mesh API: gapis/api/mesh.go.
There was a problem hiding this comment.
Ok, and then the Metrics proto definition should be moved to gapis/api/service.proto?
cmd/gapit/memory.go
Outdated
|
|
||
| type bindingSlice []*service.MemoryBinding | ||
|
|
||
| func (bindings bindingSlice) BindingLess(i, j int) bool { |
There was a problem hiding this comment.
Does it need to be public? If so, consider adding documenting.
cmd/gapit/memory.go
Outdated
|
|
||
| func (bindings bindingSlice) BindingLess(i, j int) bool { | ||
| if bindings[i].Offset < bindings[j].Offset { | ||
| return true |
There was a problem hiding this comment.
Could simply, up to you
if bindings[i].Offset != bindings[j].Offset {
return bindings[i].Offset < bindings[j].Offset
}
cmd/gapit/memory.go
Outdated
| active[handle] = struct{}{} | ||
| } | ||
|
|
||
| if len(active) > 1 && i < len(points)-1 { |
There was a problem hiding this comment.
Could also do
for _, p := range points[:len(points)-1] above
gapis/api/vulkan/memory_layout.go
Outdated
| // allocations, and which resources are bound to which locations in memory. | ||
| func (a API) MemoryLayout(st *api.GlobalState) (*service.MemoryLayout, error) { | ||
| s := GetState(st) | ||
| allocations := []*service.MemoryAllocation{} |
There was a problem hiding this comment.
Consider pre-allocating with an appropriate length if it is known
cmd/gapit/flags.go
Outdated
| } | ||
| MemoryFlags struct { | ||
| Gapis GapisFlags | ||
| At flags.U64Slice `help:"command/subcommand index to get the state after. Empty for last"` |
There was a problem hiding this comment.
Looks like this is about memory layout not the state block?
cmd/gapit/memory.go
Outdated
|
|
||
| type bindingSlice []*service.MemoryBinding | ||
|
|
||
| func (bindings bindingSlice) BindingLess(i, j int) bool { |
gapis/api/vulkan/memory_layout.go
Outdated
| s := GetState(st) | ||
| allocations := []*service.MemoryAllocation{} | ||
| // Serialize data on all allocations into protobufs | ||
| for handle, info := range *(s.DeviceMemories().Map) { |
There was a problem hiding this comment.
Prefer to s.DeviceMemories().All()
gapis/api/vulkan/memory_layout.go
Outdated
| typ = service.MemoryBinding_IMAGE | ||
| size = image.MemoryRequirements().Size() | ||
| } else { | ||
| return nil, fmt.Errorf("Bound object %v is not a buffer or an image", handle) |
There was a problem hiding this comment.
I remember for sparse image and buffers, we didn't register the binding info on the memory object, only the buffer/image object. So we probably want to have a TODO or Note here to say some cases are not handled yet.
gapis/service/service.proto
Outdated
| } | ||
|
|
||
| // The description of the memory layout of the API state | ||
| message MemoryLayout { |
There was a problem hiding this comment.
Feel MemoryLayout name is a little bit confusing in GAPID, as we use this name for 'alignment, data width' things also. May be something like: MemoryUsage?
@AWoloszyn @ben-clayton @pmuetschard Any better idea or just using MemoryLayout is fine?
There was a problem hiding this comment.
What about 'MemoryBreakdown'?
There was a problem hiding this comment.
That is a fair point, overloading terms may not serve us well.
MemoryBreakdown is fine with me. Even a MemoryUsage (although people may expect a single number out of that).
gapis/service/service.proto
Outdated
| // The device this allocation was made on | ||
| uint64 device = 1; | ||
| // The memory type this allocation is from | ||
| uint32 memory_type = 2; |
There was a problem hiding this comment.
Looks like this is more like memory_type_index? But index also sounds too Vulkan specific, I'm not sure if in GL world there is a thing like type index.
There was a problem hiding this comment.
Yes, it is memory type index in Vulkan, I didn't want to make it overspecific to Vulkan though.
There was a problem hiding this comment.
GL works a bit differently, since all memory is implicit. The allocations will be 1:1 with the resources.
I would expect something like "memory_type" to be "GL_IMAGE or GL_BUFFER" most likely.
gapis/service/service.proto
Outdated
| // Constant index for looking up the flag values with the path.ConstantSet endpoint | ||
| uint32 constant_set = 4; | ||
| // The API specific ID for this allocation | ||
| uint64 id = 5; |
There was a problem hiding this comment.
Is this Id used? And should we name it 'handle'?
There was a problem hiding this comment.
@ben-clayton suggested separated id and name for bindings, wasn't sure if it would also be useful for allocations. Open to using either id or handle, not sure which is a more descriptive name.
There was a problem hiding this comment.
I have a small preference for Handle. It more closely maps to how I view things. (That is not to say my view is right).
There was a problem hiding this comment.
Would you prefer to also keep name or is just handle good enough?
There was a problem hiding this comment.
I think keeping the name is fine. It means we can use debug names if assigned.
gapis/service/service.proto
Outdated
| // The offset of the mapping into the source allocation, in bytes | ||
| uint64 offset = 2; | ||
| // The address on the host that this memory is bound to | ||
| uint64 host_address = 3; |
There was a problem hiding this comment.
I would prefer mapped_address rather than host_address since the host address doesn't have to necessarily be fixed for the entire applications lifetime (The driver is free to return different addresses for different mappings).
gapis/service/service.proto
Outdated
| } | ||
|
|
||
| // A buffer/image that is bound to part of a memory allocation | ||
| message MemoryBinding { |
There was a problem hiding this comment.
Before we finalize this API we should figure out how this should look for sparse binding, since a single image can be bound to multiple locations.
There was a problem hiding this comment.
This might mean another binding type of 'SparseImageBlock', which will define
x, y, w, h, mip_level, array_layer
Then we would also need SparseImageMetadata and SparseImageMipTail
Lastly we would need SparseBufferBlock
There was a problem hiding this comment.
We also need some way to describe opaque sparse image binding blocks. Could probably do that by setting x, y, w, h = (~0, ~0, 0, 0).
There was a problem hiding this comment.
SparseImageBlock also needs an aspect flags field
There was a problem hiding this comment.
Hmm, I think it's actually better to have a separate type for opaque image block bindings
8b87ec5 to
21390c6
Compare
|
Added proto definition for sparse types, implementation isn't done yet |
gapis/api/service.proto
Outdated
| uint32 array_layer = 6; | ||
|
|
||
| // The aspect(s) of the image this block is from (colour, depth, etc.) | ||
| uint32 aspects = 7; |
There was a problem hiding this comment.
Can we use something other than a uint32_t here. Preferably a repeated field so we can have multiple aspects that have a proper name.
There was a problem hiding this comment.
Something like repeated string or do we still want to keep the values? repeated Aspect; message Aspect { uint32 value; string name; }
There was a problem hiding this comment.
I think? this will work (we might be using an old version of proto but
enum AspectType {
COLOR,
DEPTH,
STENCIL
}
repeated AspectType
There was a problem hiding this comment.
COLOR, DEPTH, STENCIL are pretty standard across all graphics APIs so I dont mind having them in the proto.
There was a problem hiding this comment.
Alright, metadata is technically also a vulkan aspect but I suppose it shouldn't show up except in SparseImageMetadataMipTail, where we've already distinguished it from regular mip tail.
|
|
||
| // Which type of object is using this memory, and any extra associated data | ||
| // with that. | ||
| oneof type { |
There was a problem hiding this comment.
I am not sure if we can do this in Proto, but for consistency (and forward compatibility) can we make a BufferBinding and ImageBinding message, even if they are empty.
AWoloszyn
left a comment
There was a problem hiding this comment.
Only a couple minor nits, other than that looks good.
|
Thanks! |
- Endpoint allows for different types of metrics to be requested at a certain command index - Only memory layout metrics are supported for now
Prints reported data out as well as computes memory aliasing and displays aliased regions
- Dumps info on allocations, mappings, and image/buffer/sparse resource bindings
af84cda to
b8a7c30
Compare
|
Example outputs of |
ben-clayton
left a comment
There was a problem hiding this comment.
Please feel free to follow up these late review comments in later CLs.
| } | ||
|
|
||
| message Metrics { | ||
| oneof metrics { |
There was a problem hiding this comment.
Instead of having this as a oneof, I'd suggest having memory_breakdown as a regular field.
Then instead of having an enum for the single metrics you want, the interface can be a list of bool flags for the bits of info the client wants. That way the client can fetch everything it cares about in a single RPC.
| uint32 memory_type = 2; | ||
| // Flags describing properties of the allocation, e.g. whether it's device | ||
| // local, whether it's host visible, etc. | ||
| uint32 flags = 3; |
There was a problem hiding this comment.
Part of the goal with this RPC interface is that the client should never have to have intimate knowledge of the actual graphics API. This breaks the abstraction.
I can see two ways of solving this:
- Have a repeated string field of API flags as names.
- Making another message with fields like
IsHostVisible, etc. However this makes it hard to reproduce the true vulkan names.
There was a problem hiding this comment.
It was originally a repeated string field of API flag names, but @AWoloszyn suggested using uint32 along with the allocation_flags_index field to fetch the flag names from ConstantSets
There was a problem hiding this comment.
Ah okay, please can you document that the flags relate to bitfields in the constant sets then?
This was not obvious.
There was a problem hiding this comment.
Good point, sure.
| return "" | ||
| } | ||
| strs := make([]string, len(aspects)) | ||
| for i, asp := range aspects { |
There was a problem hiding this comment.
You can add a Format() method on the type so that this automatically handled by the fmt package.
There are many examples of this here.
| fmt.Printf("\t\tBlock Extent: (%v, %v)\n", | ||
| info.Width, info.Height) | ||
| fmt.Printf("\t\tMip Level: %v\n", info.MipLevel) | ||
| fmt.Printf("\t\tArray Layer: %v\n", info.ArrayLayer) |
There was a problem hiding this comment.
Nit: There is the text/tabwriter package that does automatic alignment of text into columns. It also deals with emitting whitespace instead of tab characters (which many terminals will struggle with).
| // Flags describing properties of the allocation, e.g. whether it's device | ||
| // local, whether it's host visible, etc. | ||
| uint32 flags = 3; | ||
| // Constant index for looking up the flag values with the path.ConstantSet endpoint |
There was a problem hiding this comment.
Of course, I now see it is mentioned here. I of course didn't look here. :)
There was a problem hiding this comment.
Although now that you point this out I think this field is duplicating the work of allocation_flags_index in MemoryBreakdown. That should be fixed.
Recommended changes by @ben-clayton in google#1954 - Change Metrics proto to not be oneof, and change path.Metrics to have a flag per type instead of an enum - Remove redudancy on flags ConstantSet index, and document better - Add aspectList type with Format method - Use text/tabwriter in cmd/gapit/memory
Recommended changes by @ben-clayton in #1954 - Change Metrics proto to not be oneof, and change path.Metrics to have a flag per type instead of an enum - Remove redudancy on flags ConstantSet index, and document better - Add aspectList type with Format method - Use text/tabwriter in cmd/gapit/memory
This creates a GAPIS service endpoint to get memory layout information at a given point in a trace, and implement it for Vulkan. It also adds a gapit verb to print out this information textually, along with information about aliased regions. No visual representation exists for now, just a text report.