On Mon, Feb 8, 2010 at 11:51 PM, Luca Barbieri <luca.barbi...@gmail.com> wrote:
>> Map/unmap make it all the way to the user's program, and there will
>> likely be cases where user code maps/unmaps a buffer multiple times
>> before drawing. The current transfer semantics can handle that with
>> zero-copy if the state tracker does the right thing with it.
>
> OpenGL does not allow you to map textures and when other APIs exposes
> map/unmap, I think the API unmap is always supposed to actually change
> the texture (this is also the case for OpenGL mapping of buffers),
> which transfer unmap does not do, since it is done by destroy.
>
> Thus, API map must be implemented with transfer create+map and API
> unmap must be implemented with transfer unmap+destroy, defeating the
> purpose of having them separate.

Well, if I understood Keith correctly pipe_transfers will apply to all
buffers, not just textures. Anyhow, If I recall you can glMapBuffer a
PBO as many times as you want and the transfer to the actual texture
only occurs when glTexImage2D is called. In an API like D3D that has
texture lock(x,y,w,h)/unlock() operations IIRC there's no requirement
that unlock() flushes anything. I think they even keep track of dirty
rects for lock/unlock and upload the minimal enclosing rect during
validation in such cases. Instead of combining create/map and
unmap/destroy it would be better to make map more powerful.

> If the API says otherwise, with merged functions, you can just remove
> the calls to map/unmap and have equivalent behavior.
> Basically the only thing you lose is the ability to unmap and then
> remap the transfer while using it.
> On many drivers this is a no-op, and where it actually does a munmap
> and mmap, you just decrease performance for no significant benefits.

That would make map_buffer_range() kind of useless wouldn't it? You
would allocate a transfer the size of the entire buffer and ignore the
range param. If you wanted to allocate a transfer at every
map_buffer_range() instead you would miss an opportunity to coalesce a
bunch of map/unmaps together. Potentially someone could update the
entire buffer in many small ranges.

> In fact, I think in the whole Mesa/Gallium codebase, get_tex_transfer
> is always immediately followed by transfer_map, and likewise for unmap
> and destroy.

To me it makes sense to optimize at least two things for transfers:
the size of the transfer buffer and the amount of data transferred.
Transfer creation can deal with the size of the buffer, map/unmap with
a range/rect param can deal with the amount of data being transferred.
If you know ahead of time the subset of data being considered you can
create a transfer to cover only that range, if not you can create a
transfer to cover the entire buffer. At map/unmap time if you know the
subset of data being read/written you can optimize the amount of data
being transferred, especially in the write-only case where you can
keep track of the dirty ranges and possibly combine them to fewer
uploads. If you combine create+map and unmap+destroy you end up
limiting yourself for no reason other than minor convenience.

>> If performance matters transfer creation can be made cheaper by not
>> malloc'ing. Transfers aren't refcounted anyway so I don't see much of
>> a benefit in forcing them to be dynamically allocated.
>
> The problem is that usually you have driver specific data after
> pipe_transfer, so the size is not known by the state tracker.
>
> A possible improvement could be to add a "private" pointer to
> pipe_transfer and make it a structure allocated by the caller and
> passed by reference to transfer_create.
>
> Then, drivers implementing transfers by just giving a pointer to the
> texture do not need private data, and others need to allocate the
> temporary buffer anyway, and the private transfer structure allocation
> is cheap compared to that.
>
> Basically pipe_transfer would become a "cookie" returned by create+map
> for use by unmap+destroy to flush the temporary buffer, if present.
>

What I was actually imagining was letting the driver specify the size
of its pipe_transfer objects (this size would have to be consistent)
and letting the caller allocate the space so that the caller could
either allocate the transfers once [or abuse alloca() if applicable]
and the driver could simply init/cleanup the transfer data members
every time it was required. A little less clean, but maybe worth it
for objects that get created/destroyed potentially many times per
frame.

------------------------------------------------------------------------------
The Planet: dedicated and managed hosting, cloud storage, colocation
Stay online with enterprise data centers and the best network in the business
Choose flexible plans and management services without long-term contracts
Personal 24x7 support from experience hosting pros just a phone call away.
http://p.sf.net/sfu/theplanet-com
_______________________________________________
Mesa3d-dev mailing list
Mesa3d-dev@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/mesa3d-dev

Reply via email to