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

Avoiding unnecessary buffer copies #107

Open
dlight opened this issue Oct 12, 2019 · 5 comments
Open

Avoiding unnecessary buffer copies #107

dlight opened this issue Oct 12, 2019 · 5 comments
Labels
improvement An internal improvement question Further information is requested

Comments

@dlight
Copy link
Contributor

dlight commented Oct 12, 2019

I submitted #104 to avoid copying the buffer every time I submit a texture to the gpu, but it turns out that each gpu backend receives a &image::DynamicImage and performs another copy anyway. (well one copy is better than two, but still)

on the gfx backend it always performs a copy (even if the image already is rgba)

on the wpu backend it always performs a copy too, even if it's already gbra (also: why do the two backends use a different color order for textures?)

For the opengl backend: I can't find it.

Well it's unavoidable to perform copies if the image isn't the right format, but it can be avoided if it is. But copying on some backends and not on others doesn't sound good, so I'm not sure if there's something that can be done.

(Anyway, my point of view is: the more optimized coffee is, the more people can get away with poorly optimized game code.)

@hecrj
Copy link
Owner

hecrj commented Oct 12, 2019

How often are you submitting a new texture to the GPU? You should try to reduce this as much as possible. Image::from_image is meant to be used for resource loading.

If you are producing individual pixels in your update logic, Coffee is probably not a good fit for your use case. Coffee allows you to load and draw sprites, quads, meshes, and UI widgets easily by leveraging the GPU. It is not optimized for drawing individual pixels. For something like that, you will probably have a better time with something like minifb.

If you are only loading resources every once in a while, I do not think an additional copy will matter unless you are dealing with a lot of images. We should probably perform some benchmarks (see #13) and profile it before optimizing anything, specially when there is not a clear way to go about it.

@hecrj hecrj added improvement An internal improvement question Further information is requested labels Oct 12, 2019
@dlight
Copy link
Contributor Author

dlight commented Oct 12, 2019

How often are you submitting a new texture to the GPU?

I don't know yet!

We should probably perform some benchmarks and profile it before optimizing anything, specially when there is not a clear way to go about it.

Fair enough.

@hecrj
Copy link
Owner

hecrj commented Oct 12, 2019

The wgpu backend has this line since the first release, which is quite ugly:

layers.iter().cloned().flatten().cloned().collect();

When I wrote this, I was just starting with Rust and I didn't focus much on performance, given that it's a method that should be used rarely, so there is definitely room for improvement/micro-optimization (see #7).

@dlight
Copy link
Contributor Author

dlight commented Oct 13, 2019

The last cloned is definitively unneeded, because collect already allocates a new memory buffer (so .cloned().collect() copies the stuff, then copies again to the collected container - in this case, Vec).

IIRC the first one (.iter().cloned()) is sometimes needed to workaround the borrow checker, but not this time, since you are collecting (thus you own the result)

Lol, I did test on the opengl backend, not vulkan

@dlight
Copy link
Contributor Author

dlight commented Oct 13, 2019

About graphics::Image::from_image: if we could ensure tha all backends always receive rgba buffers when uploading textures, then receiving

pub fn from_image(gpu: &mut Gpu, image: &image::RgbaImage) -> Result<Image>

Is probably a cleaner API: anyone that already have an RgbaImage can just pass it &image, and people that have some other kind of image shouldn't be too worried to call &image.convert() (which allocates an rgba buffer). It feels rusty, in the same way that having to call .clone() and .cloned() when needed is.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
improvement An internal improvement question Further information is requested
Projects
None yet
Development

No branches or pull requests

2 participants