Skip to content

Add MESA_map_buffer_client_pointer.#678

Open
Guy1524 wants to merge 1 commit intoKhronosGroup:mainfrom
Guy1524:map_buffer_client_pointer
Open

Add MESA_map_buffer_client_pointer.#678
Guy1524 wants to merge 1 commit intoKhronosGroup:mainfrom
Guy1524:map_buffer_client_pointer

Conversation

@Guy1524
Copy link

@Guy1524 Guy1524 commented Feb 25, 2026

This extension's purpose is for Wine (https://winehq.org), which runs 32-bit Windows applications with 64-bit system libraries, to be able to implement glMapBuffer such that the returned pointer is in the 32-bit address range.

Currently, Wine will set up a CPU storage for the buffer from which it copies the contents on glUnmapBuffer. For persistent maps, it currently uses either Vulkan resource sharing with VK_EXT_map_memory_placed, or AMD_pinned_memory.

These approaches can't work for legacy maps with the same speed, since they move buffer upload management to the application side, which can't for example provide staging buffers to avoid unnecessary synchronization.

For more details on the problem space, see
https://gitlab.freedesktop.org/mesa/mesa/-/issues/14254
and
https://lists.freedesktop.org/archives/mesa-dev/2024-October/226323.html

This extension should address the problem going forward by allowing Wine to provide 32-bit address ranges to the driver, onto which BOs can be mapped.

In OOM situations, it is on the application (Wine) to get the unused address ranges back from the driver and free them, as firstly, a callback extensions seems to be undesireable, and more importantly, WINE has a better idea of what constitutes an OOM, namely when 32-bit address range runs out, which the 64-bit driver has no awareness of.

Proof-of-concept RadeonSI implementation: https://gitlab.freedesktop.org/Guy1524/mesa/-/commit/829c099c16c4fbea27812705c6527a0ab1d1ba98

Wine branch: https://gitlab.winehq.org/dlesho/wine/-/commits/map_buffer_client_pointer

@zmike
Copy link
Contributor

zmike commented Feb 25, 2026

You can get the next free extension number with cd extensions ; ./nextfree.py

@Guy1524 Guy1524 force-pushed the map_buffer_client_pointer branch from 8787926 to 4abf4b8 Compare February 26, 2026 09:00
@marekolsak
Copy link

It looks good to me.

@Guy1524 Guy1524 force-pushed the map_buffer_client_pointer branch from 4abf4b8 to d0655c9 Compare March 5, 2026 14:44
@Guy1524 Guy1524 marked this pull request as ready for review March 5, 2026 14:46
@Guy1524
Copy link
Author

Guy1524 commented Mar 5, 2026

It looks good to me.

Good to hear. I've asked Jacek, who's worked on the Wine side of this code for other solutions to take a look as well before this gets pushed.

Additionally, there's a few decisions I made that might be review worthy:

  • The only efficient way to implement this extension is re-mapping BOs to multiple virtual addresses, otherwise sub-allocated BOs would have to be moved around at glMapBuffer time. This shouldn't be a problem on linux drivers, where as far as I know we are just dealing with an FD that can be mmap'd multiple times, but correct me if I'm wrong.

  • I only added MAP_CLIENT_POINTER_BIT_MESA flag to glMapBufferRange's access, not to glBufferStorage's flags. This is because, as least in the case of non persistent maps, the driver may have more information at glMapBuffer time where it wants to place the buffer (if it's using a staging buffer or cpu storage). We could though add the flag to glBufferStorage and define the driver's retention of the range as the lifetime of the buffer, and then drivers could place at-least persistent maps in client pointer ranges without remapping later. I'm open either way

  • BUFFER_CLIENT_POINTER_SIZE_MESA is the way the app gets the size needed for a new mapping when there's not enough. In my implementation it's the size of the real BO behind the buffer mapping, and having it as a buffer parameter may create confusion to implementors that the mapping is in any way tied to the specific buffer. We could also have this as global context to be returned in AddClientPointerRange for example. I decided for the buffer parameter option as many of the other parameters follow the paradigm of being set my MapBuffer.

  • I wrote into the spec that ReleaseClientPointerRangeMESA requires buffers in a range to be unmapped and Flush to be called before it is guarenteed to return back a given range. This is a reflection of my experience implementing the extension in Mesa, where with the threaded context, glUnmapBuffer is queued on a thread and not performed immediately. Alternatively we could just flush in the ReleaseClientPointerRangeMESA implementation, as this shouldn't be called too often.

If a buffer is mapped with the MAP_CLIENT_POINTER_BIT_MESA flag, the
returned pointer will be in a range provided by the application through

void AddClientPointerRangeMESA( void *addr, sizeiptr size );

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this state global or per-buffer?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

global, the same range can fit multiple buffers, and stay around for new mappings after the buffer has been unmapped

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know if it has to be stated somewhere in the spec that it's global, but stating it would perhaps be better than leaving it up to the reader to figure out.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've updated the wording to make the global state more clear

@Guy1524 Guy1524 force-pushed the map_buffer_client_pointer branch from d0655c9 to 6d9e364 Compare March 6, 2026 09:09
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

Successfully merging this pull request may close these issues.

3 participants