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

Temporary buffers #12

Open
kvark opened this issue Mar 21, 2023 · 2 comments
Open

Temporary buffers #12

kvark opened this issue Mar 21, 2023 · 2 comments
Labels
enhancement New feature or request

Comments

@kvark
Copy link
Owner

kvark commented Mar 21, 2023

There is often a need to create a buffer knowing that it's going to perish on the next submit. Exposing a nice API for this is, however, not trivial. I could see at least 3 different approaches:

  1. Just add temporary: bool flag to struct BufferDesc and allocate accordingly. This helps with performance of small allocations, but it doesn't have with ergonomics: the user still has to know when to delete the buffers.
  2. Add something like CommandEncoder::create_temporary_buffer, which would automatically manage its lifetime and destroy whenever the underlying command pool is reset. As nice as this sounds from the ergonomics point of view, it has implementation caveats:
    - the logic of tracking temporary buffers is backend-agnostic. We could try moving it into a shared implementation, it's not a lot of code.
    - when inside a transfer pass (or any other), we can't borrow CommandEncoder even immutably... We could re-expose this method on the encoders.
    - in Vulkan backend, the command encoder doesn't have access to memory. Could be exposed?
  3. Expose a buffer belt primitive in a satellite library. Good thing is that it's fairly versatile. Bad thing is that the API is still not as nice.
@kvark kvark added the enhancement New feature or request label Mar 21, 2023
@kvark
Copy link
Owner Author

kvark commented Nov 21, 2023

Somewhat addressed by 36109ea with the addition of FramePacer and FrameResources

@kvark
Copy link
Owner Author

kvark commented Jul 9, 2024

I've been prototyping this a bit, and still haven't found a concise and efficient solution.

I believe, something like create_temporary_buffer would be ideal for the user. Some of the downside I expressed in the original issue may not really be that important:

  • logic of tracking doesn't have to be backend-agnostic. It's much easier to do it specific for backends:
    • Vulkan can free resources whenever this command buffer is reset
    • Metal can either use references to resources from a command buffer, or possibly just have a callback assigned to an encoder to execute when it's done. And the callback would just release some references.
    • OpenGL would delete temporary buffers right after recording the commands, letting the driver do it.
  • it's probably OK to just have it outside of passes

The lack of access to memory is still a problem. We could refactor it to have access to memory by adding an indirection, which is probably OK. What bothers me is that this approach wouldn't be most efficient anyway. The most efficient one is to do a buffer belt, basically. Now that's mostly backend-agnostic, and is already exposed. But it's not as nice to use.

There is a reduced scope function that we can expose though - something like CommandEncoder::add_temporary_buffer(buffer). It would attach the lifetime of a buffer to the command encoder, using all the same backend-specific ways to delete it properly. This is straightforward to implement, but it doesn't quite solve the problem. If the user is allocating a buffer themselves, they don't get the "TRANSIENT" flag in Vulkan. One would still have something like a buffer belt, unless they are lazy. And with a buffer belt you don't really want to destroy those buffers, you'd want to re-use them instead. So the new function wouldn't help.

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

No branches or pull requests

1 participant