* When we figure out which event a marker region should jump to if you
select the parent, we want to pick the last valid event ID that isn't
just a label. However previously this was being done by iterating over
the children and picking the last one and assuming there would be a
node of that index - which isn't true in the case where some drawcalls
were entirely omitted. It would either index out of bounds, or index
incorrectly.
* This shader is necessary for the MSAA-to-array copying functionality
used, and without it we bind a NULL vertex shader and can end up with
driver crashes.
* The UAV array is provided as we expect it - with UAVs from 0 onwards
even if their 'slots' are 4, 5, 6 etc or whatever. UAVStartSlot is
the slot of the 0th UAV.
* Also in many places OpenGL is now advertised as full support, since it
is pretty close by now and needs people to jump on it full-time and
use it in anger.
* I doubt anyone will notice the file->open filter unless they look for
it so it's no good for 'discovering' the image viewing capability, but
it might be convenient for people who know about it.
* This means the redeclarations are a bit more flexible if a shader
(like a geometry shader) redeclares one already, but not the other,
we'll only substitute in the missing one.
* Note this code is still a bit flakey e.g. in edge cases like if
someone puts "in gl_PerVertex" in a comment, then it will fail.
I want to avoid putting a full parser in, but perhaps stripping the
source of any comments is a reasonable future step.
* GL doesn't seem to support reading both depth and stencil channels
from a single texture, so we need to do a second pass to read back
the stencil component
* For range maps, similar to glFlushMappedBufferRange, we assume the
user selected the range deliberately and we upload it all. We only
find a difference range for whole-buffer maps (of large enough
buffers). This includes glMapBuffer(), by definition.
* Also, the comparison point is between the map pointer, so we have to
offset the shadow pointer to compare it against to get accurate
results.
* glBufferStorage was less of a problem as it was immutable but the data
that got uploaded was uninitialised memory, it is now filled with 0xdd
* glBufferData could be used to invalidate a whole buffer, by passing
NULL as data for an existing buffer. This caused a mismatch where the
driver could (legally) have the same data, but our serialised copy
was random uninitialised memory. The diff was done against the 'real'
data but on serialise the base data was different, causing invalid
data to be used.
* glBufferData isn't only used for creation, it is often used to upload
new data to a buffer, which means that during the captured frame any
're-create' type calls should go into the context record.
* We need to copy the X display (by fetching its connection string and
calling XOpenDisplay), so that if the Display* we had gets closed then
nothing will crash.
* Also in the HLSL version, we were indexing off the end of an array
since we were drawing 5 lines but only had 4 verts in the array.
Oops!
* We can remove D3D's OutlineStripVB, as we're doing it all in the
shader.
* The unpack parameters are ignored for compressed images unless the
compressed width, height, depth and size parameters are set (whichever
are required for the given unpack param). So we roll this into our
calculation of the fast path, which means that we only use them in
UnpackCompressed if they are valid.
* This can happen when we're copying from a source program to a dest
program where the source is non-separable and had an attribute
optimised out entirely, but the destination is separable and so still
wants that attribute. In this case it'll come out in the wash and
we can just skip it.
* We used to switch to the context that the object was created on and
fetch initial state there, but this isn't safe e.g. the switch
operation could fail if the context was active on another thread.
Instead we queue up such objects to have their data fetched the next
time we see the context made current.
* If we never get the initial state for that object we assume that
context is never used, so it's OK to just not have initial states -
it's marked as invalid so we don't try to restore those states on
replay.
* Note: this obviously falls down in the even that the context is
already current on another thread and we just get commands from there
without an explicit 'MakeCurrent' call. But we already don't handle
that as we don't detect that and log the state change (or properly
handle multithreaded commands), so it's not any worse support.
* Apparently although there are no errors thrown if you pass
GL_ALL_BARRIER_BITS (0xffffffff), if you remove a bit then an error
will be thrown for unrecognised bits :(.
* Since it's not harmful to leave in the mapped buffer bit we just let
it remain.
* We need a context to be current when the frame capture happens so that
we can fetch initial contents and such. This is a hack as there's no
guarantee it's correct or will work, but we temporarily make the last
context that was active on this thread active again, to fetch our
data.
* This could break if that context is active elsewhere, or isn't a valid
context (ie. maybe it was a temporary context used to fetch func
pointers).
* A better fix would be to delay any GL work we need to do until the
next time a good context becomes current, but that becomes dicey in
itself.
* Note that we serialise out the new render state any time we reach a
MakeCurrent call, so we can safely 'skip' the initial render state
at the start of a frame.
* We can't just link ALL programs as separable to be safe, since this
hits the same problem of some shaders not being valid as separable :(.
* This should fix the case where a separable program with initial state
was failing to link before, without breaking non-separable programs.
* These are placed a little conservatively to be sure we pick up changes
* They're placed on any drawcall, any buffer copy operation, any texture
data operation that can source from a buffer via pixel unpack buffers,
any texture copy or read (like framebuffer blits) since the buffer
could be a texture buffer. Also on any function that returns the
contents of a texture or buffer.
* Should support coherent & non-coherent persistent maps (coherent
coming with a fair performance hit).
* Slightly changed the method from the one planned - coherent maps don't
need to actually be mapped coherently. Since we're inserting a manual
sync & copy point all over the place, we can map the underlying GL
buffer as non-coherent and flush explicit, then just do the flushes
when we do the copies.
* Still need to add all those implicit sync point calls, and I'm sure
there are plenty of bugs in this implementation.
* The documentation also describes how persistent maps will be handled
in the code to follow.
* There are a couple of edge-case bugfixes here that turned up as I was
writing up how everything should work:
- a high traffic resource wasn't being marked as dirty, which probably
wouldn't ever break as if we ever acted on it being high traffic, we
would mark it dirty, but better to be explicit.
- fetching initial shadow storage contents in capframe, we need to
fill the whole buffer, not just the mapped region.
- if a flush explicit map were non-invalidating, it could be
intercepted even while idle, but then the flush calls would have
been discarded and never gone anywhere while idle. Instead we just
explicitly don't intercept flush explicit maps except while
capturing
* glMapBuffer can just be expressed in terms of glMapBufferRange, this
simplifies the flow a bit.
* We can also romeve a couple of map statuses, as they're no longer
used.
* Also, buffer creation chunks must go into the resource record, not the
context record, in case a buffer is created in the frame that's
captured.
* This should be impossible, as Map() is only valid after glBufferData
or glBufferStorage, and both of those will unconditionally set a data
pointer to backing store.
* This was always a problem, but may have been hidden in some cases by
lack of DSA type use causing a late bind-to-create. e.g. in a VAO we
might have been binding an element array buffer that caused a bind-to-
create on the VAO. Now we do it in the glGen functions to ensure the
objects are fully initialised.
* For the most part these are identical to the equivalent glGen*.
* For textures, we bake in the current type immediately, for buffers we
would ideally want a type but the glCreateBuffers doesn't take one (it
then gets renamed/retyped).
* Since this would be another duplicated set of code, move the variants
into common functions - each of the variants (ARB_dsa, EXT_dsa,
non-DSA and possibly MultiTex) calls into a common function just with
a different resource record.
* Handling the ARB/EXT dsa differences on the texture calls, the target
parameter is set to GL_NONE for the ARB dsa calls (which lack a target
parameter). Then in the serialise replay part, if the target is
GL_NONE we use the ARB variant and otherwise use the EXT variant.
See the comments at the top of gl_texture_funcs.cpp
* For functions with common code that needs to happen on replay, we pass
the resource's ID instead of its record, to be compatible with replay
where there are no records. To save time & unnecessary queries, also
force all internal texture creates on replay to happen through the
DSA interfaces so we don't have to go looking up the texture via
selectors.