On 2 July 2016 at 08:49, Patrick Rudolph <siro(a)das-labor.org> wrote:
It makes
logical sense to me that mapping a buffer with both DISCARD and
NOOVERWRITE would effectively ignore NOOVERWRITE. I've noticed that at
least some engines will map a part of a buffer with NOOVERWRITE and draw
with that part, map the next part of the buffer with NOOVERWRITE and
draw with that part, etc, then after the last part of the buffer it maps
with DISCARD to get new memory and keep going while the previous buffer
memory is handled asynchronously by the driver or card.
I notice that wined3d has some parts where it ignores/removes DISCARD,
so it may not be a good idea to leave both DISCARD and NOOVERWRITE set.
In such a case, the driver will get NOOVERWRITE for a part of the buffer
that's still in use. It would probably be better to remove NOOVERWRITE
when both DISCARD and NOOVERWRITE are set.
Both flags are independent of each other and provide useful information
to the OpenGL driver. The driver knows best how to map the resource.
By passing NOOVERWRITE and DISCARD it's likely going to use NOOVERWRITE,
as it's even less overhead than DISCARD.
I don't think that WINE should drop flags, except there's a driver bug
that can't be fixed (in the near future).
The patch is at the very least questionable.
The way NOOVERWRITE/DISCARD are normally intended to be used is for
streaming vertex data from the CPU to the GPU. NOOVERWRITE means the
application promises it won't touch data that may be in use by the
GPU, DISCARD means the application doesn't need the contents of the
buffer any more, and it can go away after the GPU is done with it. In
practice this means applications use NOOVERWRITE to append to the
buffer until it's full, and then use DISCARD to get a new block of
video memory.
It's unclear what should happen when the application specifies both,
but "have the driver pick one" seems unlikely to be what the
application intended. In particular, if the application specified
NOOVERWRITE because it determined (somehow, e.g. using fences) that
it's not going to touch any data in use by the GPU, DISCARD is
redundant and would lead to the driver doing unnecessary work if it
picked DISCARD. On the other hand, if the application didn't make that
determination and the driver picks NOOVERWRITE, the application is
potentially going to write over data still in use by the GPU and cause
geometry corruption. Finally, there the possibility that Windows
filters invalid flag combinations like Wine currently does, and
picking either DISCARD or NOOVERWRITE will break an application that
depends on that.
It could very well be the case that "DISCARD | NOOVERWRITE" behaves
like e.g. just "DISCARD", but having the driver just pick one of them
is almost certainly the wrong thing to do. Like so many other things,
determining the correct behaviour would require some tests. This is of
course one of the harder things to write tests for, but I don't think
it's impossible.