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