Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Obtaining slices of primitive and struct lists #97

Closed
Ralith opened this issue Jul 14, 2018 · 9 comments
Closed

Obtaining slices of primitive and struct lists #97

Ralith opened this issue Jul 14, 2018 · 9 comments

Comments

@Ralith
Copy link
Contributor

Ralith commented Jul 14, 2018

I'm trying to use capnp to represent geometry for upload to a GPU. I want to decompress data from disk into a driver-supplied staging buffer, and then submit transfer commands to asynchronously DMA the data of interest directly into GPU memory. The data is formatted as a capnp struct containing a List(UInt16) and a List(Vertex) where Vertex contains nothing but Float32 fields.

It's my understanding that both of these lists are guaranteed to be laid out in a GPU-friendly way (i.e. dense and contiguous) and can therefore be used directly once copied, but the generated API forces me to instead decompress to CPU memory, then painstakingly copy each element to the staging buffer by hand. Some way to get a &[u8] of any struct or primitive list would allow for greater efficiency. For now I'm working around the issue by using Data instead of the list types, but this represents an undesired weakening of the schema.

@dwrensha
Copy link
Member

capnproto-c++ has AnyStruct and AnyList with methods for getting byte buffers:

https://github.com/capnproto/capnproto/blob/30c7d54bc3761fae0e47b6addc6d4d0cce0cd2fa/c%2B%2B/src/capnp/any.h#L469

https://github.com/capnproto/capnproto/blob/30c7d54bc3761fae0e47b6addc6d4d0cce0cd2fa/c%2B%2B/src/capnp/any.h#L652

These should be straightforward to port to capnproto-rust. I'm not sure when I'll have time to add them, but maybe you'd like to give it a go? I think maybe the hardest part will be working out how the traits should fit together to allow e.g. an any_struct::Reader to be constructed from any foo::Reader, where foo is a struct. capnproto-c++ uses some fancy template magic to accomplish that.

@dwrensha
Copy link
Member

It's my understanding that both of these lists are guaranteed to be laid out in a GPU-friendly way (i.e. dense and contiguous)

That's correct as long as the messages are constructed with the same version of the schema that you're using to read them. Messages from a newer version of the schema (perhaps with Vertex gaining some new fields) may have a different layout.

@Ralith
Copy link
Contributor Author

Ralith commented Jul 14, 2018

These should be straightforward to port to capnproto-rust. I'm not sure when I'll have time to add them, but maybe you'd like to give it a go?

I'll tinker with it, thanks! A reasonable model for the API is about what I needed to get started.

Messages from a newer version of the schema (perhaps with Vertex gaining some new fields) may have a different layout.

Yeah, what I'd really like here is a way to express a flat, inextensible struct type like flatbuffers has. This would also make much of my schema considerably more concise, as I wouldn't have to manually inline vectors/matrices/quaternions/etc every time they arise. In lieu of capnp growing such a feature, this'll have to do.

@ishitatsuyuki
Copy link

I'm planning to implement this. Is there any tricky part that I should take care of? Please let me know.

@ishitatsuyuki
Copy link

Actually, my intent of obtaining slices of structs, is to use the binary_search function. So in my case I don't need the data to be dense.

However, it seems that @Ralith has a stricter requirement on data layout? I'm not sure what type of slice you're expecting here. You wrote &[u8] but how would you pass that to the graphics API (without transmuting)?

@Ralith
Copy link
Contributor Author

Ralith commented Sep 24, 2018

I meant what I said. Graphics APIs consume untyped data; the API can't very well statically know the type signatures of your shaders.

@dwrensha
Copy link
Member

dwrensha commented Dec 2, 2018

f76c02c adds a new IntoInternalStructReader trait that should make it possible to construct an any_struct::Reader from any struct. (Note, though, that mod any_struct does not exist yet.) Then some any_struct::Reader::get_data_section() and any_struct::Reader::get_pointer_section() methods could provide access to the raw byte buffer.

Additionally, we could do something similar with IntoInternalListReader and mod any_list, with a any_list::Reader::get_raw_bytes() method.

@dwrensha
Copy link
Member

dwrensha commented Dec 9, 2018

I've pushed 6683d7a, which adds the functionality in a new module named raw.

Upon further reflection (see capnproto/capnproto#770 (comment)) I decided that any_struct and any_list are not the correct places to put this functionality.

@dwrensha dwrensha closed this as completed Dec 9, 2018
@Ralith
Copy link
Contributor Author

Ralith commented Dec 9, 2018

That looks perfect, thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants