* We instead always have 3rdparty/ in the relevant include search paths and rely
on that. Each library still has its own unique base dir within 3rdparty to
clarify where the include is coming from.
* There was a gap between stopping active capturing (meaning newly created
buffers are given an extra refcount) and releasing the extra refcount. Any
newly created buffers in that gap would still be released but that would mean
one of the application's ref's is removed, possibly destroying a buffer by
mistake.
* Instead we keep a specific list of buffers that we're extending so that we
know that the buffers we release are exactly those we gave extra refs to.
* We need to make sure we can still look up GPU addresses for buffers that were
destroyed during the frame, otherwise we might get the wrong contents for
descriptors.
* When we replace a shader in GL there are a few knock-ons: we need to replace
the programs that use this shader, and then from there we need to replace the
pipelines that use the program. We also need to beware of programs created
with glCreateShaderProgramv which refer to themselves as both a program and a
shader.
* Previously we'd look at the edited shader, then recurse and look at programs,
then recurse and look at pipelines. We'd try to remember which one replaced
which so we could undo it again.
* Now we just do this in subsequent passes since there is only a one-way
dependency: First replace the shader as needed, then update any programs and
either replace or remove replacement as needed, and finally update any
pipelines.
* On Vulkan and D3D12 it's simpler as we just have shaders -> pipelines but the
same principle applies.
* Most of the interfaces are not supported - protected sessions, raytracing,
etc.
* We also split apart the 1/2/3/4 wrapped implementations to avoid uber files.
* 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.
* The problem with storing resource pointers in descriptors is that it can be
invalidated without detection - a kind of A-B-A problem - if the resource is
deleted and then another resource is allocated with the same pointer.
* Descriptor creation in D3D12 is extremely complex and there are many ways a
resource could become incompatible with the descriptor metadata struct.
Detecting all possible ways a new resource could be incompatible is not
feasible.
* As a solution, we store the ResourceId which we know is immutable, serialise
via the pointer, and keep the live ResourceId on replay. If the resource was
deleted, the serialisation will fail because we look up the pointer at the
point of serialise, and a deleted resource will end up being NULL.
* To try and abstract this away and avoid potential confusion with the
ResourceIds, we make the descriptor contents private and provide accessors.
* We enforce a naming scheme more strongly - types, member functions,
and enum values must be UpperCaseCamel, and member variables must be
lowerCaseCamel. No underscores allowed.
* eventId not eventID or EID, and Id preferred to ID in general. Also
for resourceId.
* Removed some lingering hungarian m_Foo naming.
* Some pipeline state structs that are almost identical between the
different APIs are pulled out into common structs. Where something
doesn't make sense (e.g. viewport enable for vulkan) it will just be
set to a sensible default (in that case always true).
* Changed scissors to be x/y & width/height instead of sometimes
left/top/right/bottom
* Abbreviations are discouraged, e.g. operation not op, function not
func.
* For Vulkan and D3D12, we now create a dummy command buffer to ensure
that there's actually a chunk available to correspond to the command
buffer that gets submitted or recorded to.
* Since buffers can be referenced indirectly on the GPU by their GPU
address, there's no feasible way to know if the buffer is actually
used or not. If an ExecuteIndirect is seen at all we just have to
pessimistically include all buffers.
* Generally textures take up the bulk of VRAM usage, so this likely
won't be too bad.
* We unwrap objects and track residency state, and when preparing init
states if necessary then we make those resources resident and sync the
list execute so we can evict them again immediately afterwards.
* On replay, all resources are created and left as resident, which could
go over the budget available. If a frame uses close to or more than
its total budget over the course of a frame this could fail. One fix
to that would be to track referenced resources in command lists at
replay time, and only make resident what we need for each list and
execute them in isolation, then evict right after (so all frame
resources are 'default evicted').
* We make shaders into fake resources with IDs, so they can be
identified individually (for replacement, fetching reflection data,
and things like that). This is a little but ugly but worth it for the
simplicity it will provide everywhere else.