Refactor graphics interop around RAII-mapped buffers#1701
Refactor graphics interop around RAII-mapped buffers#1701rparolin wants to merge 8 commits intoNVIDIA:mainfrom
Conversation
|
Auto-sync is disabled for draft pull requests in this repository. Workflows must be run manually. Contributors can view more details about this message here. |
|
Auto-sync is disabled for ready for review pull requests in this repository. Workflows must be run manually. Contributors can view more details about this message here. |
|
/ok to test |
|
|
/ok to test |
cpcloud
left a comment
There was a problem hiding this comment.
Thanks for the refactor here — the GraphicsResource(Buffer) direction looks good overall.
Requesting changes for two behavior issues called out inline:
close()currently unmaps on stream 0 even when mapping happened on a non-default stream, which can break stream-ordering guarantees.__enter__returnsselfeven when unmapped, allowing context-manager usage wherehandle/sizeare invalid.
Please address these and I’m happy to re-review.
|
ping @rparolin. happy to fix this up if you want. |
Yeah and thinking about it more, I suspect this is a must:
I will ask internally if it's context-independent or not, but it's not a blocker. |
|
Thanks for the discussion here. I'd like to propose an alternative approach that I think addresses both of Phillip's concerns and Leo's observation about Proposal: Use the We already have a C++ handle layer (
Concrete design:
Benefits:
This is the same pattern we use for memory pool allocations, where the pointer handle captures the pool handle and stream for proper cleanup ordering. Thoughts? |
|
+1 to @Andy-Jost's design. Looks solid. |
|
FYI
it is context-dependent.
Modifying Can we sketch a bit how the user code would look like with this proposal? The changes in this PR were motivated by the sketch in here: #1608 (comment). Rob asked the right question there. Inheritance is probably not necessary, as long as the same UX can be delivered. |
cpcloud
left a comment
There was a problem hiding this comment.
The GraphicsResource(Buffer) direction still looks good overall, but I can’t approve this yet because two blocking behavior issues remain in the cleanup/context-manager paths called out inline: close() still ignores the mapping stream, and __enter__() still allows unmapped context-manager usage. I also reran pixi run pytest tests/test_graphics.py -q locally; it passes, but the current test coverage does not catch either case, so please add targeted regressions when you fix them.
|
@rparolin Do you want to fire off an agent to implement @Andy-Jost's design? Probably could make pretty short work of it. |
|
@cpcloud made the requested changes and aligned with @Andy-Jost recommendations. Please re-review. Thanks! |
cpcloud
left a comment
There was a problem hiding this comment.
Re-reviewed the latest graphics follow-up changes. The earlier context-manager and stream-ordering concerns look addressed, and passes in my environment.
Thanks! |
Summary
GraphicsResourceinherit fromBufferGraphicsResourceresponsible for registration/unregistration only;map()now returns a mappedBufferGraphicsResourceHandleandStreamHandleand callscuGraphicsUnmapResources(...)on releasewith resource.map(stream=s) as buf:by givingBuffercontext-manager supportwith GraphicsResource.from_gl_buffer(vbo) as resource:for automatic resource cleanup andwith GraphicsResource.from_gl_buffer(vbo, stream=s) as buf:for register-and-map-in-one-step usagemap()/unmap()and keepsGraphicsResource.handleas the rawCUgraphicsResourcehandleMotivation
Review feedback pointed toward Andy Jost's
resource_handlesdirection rather than turningGraphicsResourceinto a mutableBuffer.This version follows the same ownership model used elsewhere in
cuda_core: the mapped pointer owns unmap lifetime, and the resource registration owns unregister lifetime. That keeps stream-ordered cleanup in the handle layer, avoids changingGraphicsResource.handlesemantics based on mapping state, and removes the need to treat an unmapped resource as a partially validBuffer.Key changes
map()creates a realBufferfrom a new mapped-graphics device pointer handle. The handle deleter captures the graphics resource and mapping stream, and unmaps on release.GraphicsResourceno longer inherits fromBuffer; it tracks registration state, forwardsunmap()/close()to the active mapped buffer, and keeps a strong reference to that buffer sois_mapped,unmap(), and double-map protection remain correct even if callers drop their own Python reference.with resource.map(stream=s) as buf:still works and automatically unmaps on exit.with GraphicsResource.from_gl_buffer(vbo, stream=s) as buf:registers, maps on entry, and unregisters on exit.with GraphicsResource.from_gl_buffer(vbo) as resource:scopes the registration lifetime and closes automatically on exit, avoiding a manualresource.close().map()/unmap()again acceptstream=Noneand use the default stream, andGraphicsResource.handleonce again exposes the raw graphics-resource handle.