* This means e.g. the D3D11 back-end can accept DXBC directly if the UI can
provide it, or compile from HLSL as before.
* More importantly, the Vulkan back-end can take SPIR-V compiled from any
source, or compile from GLSL as before as a fall-back.
* This will allow the backend to specify both the native format (e.g. SPIR-V,
DXBC) as well as a language it might be able to internally compile (GLSL or
HLSL).
* The caller will then able to decide for itself whether it wants to compile to
native format and pass that down, or pass the language down and let it be
built internally.
* Currently BuildTargetShader still only accepts shader source.
* 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.
* Hooking is now done the same way across platform, with different OS
implementations.
* Regardless of how exactly hooks are implemented, we register libraries to hook
and functions to hook within those libraries, and provide a location to store
the original/onwards function pointer. This allows hooking to work whether
it's done using import hooking that doesn't modify target libraries (so using
dlsym or GetProcAddress will return the same value for the onwards function
pointer) or whether it's implemented with prologue patching and trampolines,
where we'd create an infinite loop if we did that.
* We also provide stronger guarantees - the original function pointers will
_always_ be made available as soon as the library is loaded, whether hooked or
not, no exceptions. This means less uncertainty in hooking code about when or
how onward functions will be available.
* OS-specific hook functions are changed to just be implementations of
LibraryHooks functions rather than indirected through macros and pre-processor
definitions.
* In this commit we provide some temporary functions providing the old interface
to reduce churn - the library-specific hook code will be updated shortly after
* 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.
* Any time the replay types serialisation change, the remote server becomes
incompatible. We're not going to add backwards compatibility to that system,
so we need to break it every time.
* Really the version should be bumped any time renderdoc_serialise.inl changes,
but we don't have an auto-incrementing revision to use.
* This option has always been a mixed bag - when originally written captures
weren't compressed at all so saving the cost of a initial contents on a
gbuffer would have a significant savings.
* Now with compression the savings are lesser, and it's a source of
bugs/confusion for the case where either a bug is caused by leaking data from
the previous frame or worse still the contents are discarded incorrectly.
* D3D11 will now behave as the other APIs will - saving initial contents
whenever needed even if they seem like they might not be used.
* On GL shader reflection is mutable but only between different events
(we can expect it to be consistent/cacheable for a single event).
* We don't want to delete shader reflection pointers out from under the
UI, and it's not feasible to invalidate all pointers it might hold at
any point - e.g. previous to this change when a ReplayLog happens.
* Instead we just add another dimension to the cache key and allow the
cache to bloat more on GL, preserving possibly redundant reflection
objects.
* If android studio or other android tools are open when a package is
launched for debugging, they greedily jump on it and connect which
prevents us from connecting.
* If the export doesn't need buffers, we export directly from the loaded
capture file instead of re-loading it.
* Add progress bars for the load step so it shows what's happening
instead of looking stalled.
* Reduce compression rate on XML+ZIP buffers as it took too long trying
to compress when exporting large captures.
* Previously we were relying on the pipeline info create to initialise
the reflection for an entry point, now we do it on demand wherever it
is needed.
* We can't reliably know when we can safely remove the layer property
at capture time because it's impossible to know if an android app will
use vulkan or not. So instead we fall back to unsetting it whenever we
need to - before opening a capture or when shutting down the remote
server (in case after capturing, no frame capture was actually opened)
* This means that if the UI crashes without unsetting it, we will poison
the state, but this seems unavoidable.
* This helps on android where we might fail to create the preview window
if our app isn't in the front, but we still want to let the base loop
know that we're done previewing and let it go back to the generic
splash screen.
* We assume that if the user injected libVkLayer_GLES_RenderDoc.so then
it's either a vulkan app and that's sufficient, or they linked
against it.
* Injecting our libraries over the top of that could cause problems -
at worst crashes, or at best we could end up with nested hooking with
double overhead, or the loaded renderdoc library won't be the one that
hooks and the workflow will break.
* Android::StartAndroidPackageForCapture can take a long time, and we
want to preserve the connection, so we spin up a temporary thread to
continually Ping().
* This allows more flexible construction of what params/resources need
to be saved with initial contents data, as well as allowing better
type safety where possible by using driver-specific types for the
stored data.
* Especially it tidies up the ugly 'all data that tags along must be
a written into a single allocated byte pointer'.
* The initial content struct is responsible for destroying itself and
freeing any data.
* We also make the frame counting consistent: Frame 0 is the frame from
device initialisation to first present, Frame 1 is from first present
to second, and so on after that.