* When multiple buffers are aliased over the same heap memory, they'll have the
same GPU base address. Our mapping needs to ensure it removes the right entry
when a resource is released.
* On GL/D3D11 we delay the start of the 'first frame' until a swapchain has been
created for D3D11, or an attribs-created context has been created for GL. This
makes it more useful and doesn't fire when creating devices/contexts for
enumeration or trampolining.
* On Vulkan/D3D12 the first device that's created is useful, so we can start
capturing immediately once it's available.
* When a descriptor table is unbounded in the root signature we don't want to
pass potentially multiple 100k descriptors through just because they're
technically available.
* Instead use the declared array size of the last register in the space (since a
descriptor table in the RS might correspond to multiple HLSL variables) to
limit which registers are actually available, which is possibly orders of
magnitude less.
* Even if a struct isn't trivial (e.g. it contains a constructor) it can still
be trivially copyable (just POD with memcpy), or trivially destructable (with
no destructor). Make sure we don't fall back to slower copies/destroys for
this case as it's relatively common.
* When we have a cached buffer that already has the map contents, reserialising
the byte buffer is pointless as we don't use it for anything.
* The serialise involves allocating a buffer, memcpy'ing it, then freeing it
which can add up for large map writes.
* We now take a more vulkan-like approach, by forcing READ_BIT on for
buffers/maps that are coherent, and leaving it alone while idle. During
capture we do the same memcmp & save updates as before.
* This is signifcantly faster while idle, though still slow to capture due to
the number of sync points in GL (per draw). Roughly scales with O(m*n) where m
= number of bytes of memory coherently mapped and n = number of draws in a
frame.
* This gives a one-click way to run the last capture, if it's not
complex/regular enough to be worth saving to a settings file on its own.
* Doesn't save much if you're selecting an exe as the previous exe location is
remembered, but if you also have command line parameters or a working
directory it can help.
* This is the only way in GL to do rendering from one mip to another. We handle
it and display the whole texture even if it's temporarily constricted, and
display the mip state in the pipeline viewer.
* If the mip state is constricted at the start of the frame capture, only mips
0..MAX will be visible at all and other mips will be assumed to not be valid.