* Historically we always expected a live resource, but with descriptors that can
be stale we can have a lot of queries where it's fine to just get NULL back if
the resource doesn't exist.
* Nothing interesting/useful is supported here, we just add new interfaces that
we recognise even though the user can't use them since we don't report support
for the new features.
* This also makes it easier to track future changes when we're not behind.
* We already handle the case where e.g. D3D12_RENDER_TARGET_VIEW_DESC is NULL
and we need to substitute in a typed descriptor for backbuffers. We didn't
handle the case where
* 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.
* This reduces code complexity and divergence between the backends, as well as
prevents internal resources in captures from being included when 'Ref All
Resources' is enabled.
* 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.
* This can happen if the resource was not included in the capture, but
there was a descriptor passed (i.e. not NULL desc which is handled
separately) which specifies some parameters, but leaves the format
as UNKNOWN.
* When referencing all resources we use this function to determine what
should be excluded, and in this case we want to make sure that e.g.
the device record and any swapchain records are included, but the
queue/list records or frame capture record should be omitted as they
will be included specially.
* This doesn't actually fix any problems, but a couple of crash reports
exposed the fact that we try to use the result of CreateDescriptorHeap
before checking for errors - this leads to a crash and hides the real
problem.
* 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').