* This is based on the GAPID method of injection, using the same steps
to connect with JDWP and debug the application, breakpointing on key
init-time steps to patch vulkan layer search paths and load libraries
from our installed apk.
* We diverge by then using PLT hooks instead of trampolines to hook the
EGL/GL calls - and so we also hook dlopen.
* This should work on any debuggable application - not currently checked
but does not replace/break any of the previous injection, which can
still work.
* Instead of checking on the filename, we look for a specially named
exported symbol somewhere in a module that's already loaded.
* This allows us to mark the python module as a replay program, so if
it's loaded into the python interpreter it will be able to use the
replay API.
* Using OS-specific append writing functions instead of simple fopen/
fwrite/fclose we can guarantee that multiple processes writing to the
same log file won't trash or interleave their log output.
* To make the logs readable the PID is now included along with the
project/timestamp.
* After that, we make sure that when we launch a program we set the
output log to the same file as the parent UI. This keeps all the logs
together and removes user confusion over which logfile is needed.
* We also move all of RenderDoc's temporary files under a RenderDoc
folder in the temp folder, instead of scattering the files in the root
Notes
======
- With no clean way to do string comparisons in the C preprocessor, have a define per-platform. This avoids the clever string concatenation for determining the OS-specic bits, and allows SN-DBS to distribute builds without custom rewrite rules.
- Fix up instances of WIN32, etc., in non-3rdparty sources to refer to this.
- Move the per-platform specific bits into their own subdirs.
* This is kind of arbitrary at the moment, but in future when D3D12 and
Vulkan drivers appear, not everyone who builds RenderDoc will want to
build all drivers, so making them separate projects makes it more easy
to disable/remove them.
* The core class is now responsible for tracking the active window and
cycling through, so it can cycle through multiple APIs.
* For GL we only set up associations for capturable windows, and only
those that present (since helper windows are often created). Since
GL doesn't really have a 'this window is done rendering' call, we just
decay old windows that haven't presented in >5 seconds.
* Also on GL, legacy/uncapturable windows aren't associated so they will
not cycle to at all.
* The embedding API now expects a device pointer and window handle to
set active window or start/end a capture. You can still pass NULLs if
there is only one API active.
* If CreateContextAttribs is not used to create the context, the overlay
will run in super-duper old mode using immediate mode calls and fixed
function pipeline. This way it should display on (in theory) any GL
app. Capturing will be prevented.
* Compatibility profile contexts are still allowed, but a warning is
displayed in the overlay.
* If CreateContextAttribs is used to create a < 3.2 version context, we
go down the same path as for legacy contexts, except with an accurate
overlay message (just that the version isn't supported).
* Note at the time of committing there are still some warnings in MS
headers that you might need to suppress in a couple of files.
* 3rd party code just has the warnings suppressed for ease of merging.
* The majority of warning fixes were for local variables shadowing
other locals, function parameters, or members. In most cases they
weren't a problem, but in some cases it was potentially dangerous!
* 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.
* Doesn't compile yet! Just splitting this up logically so the change is
a bit easier to digest.
* I've commented and organised a bit better the gl_hookset.h hook list.
* The function hooks are set up for all of the ARB_dsa entry points.
Those that are semnatically identical to EXT_dsa are set up as aliases
(with EXT_ being canonical, so we can fall back if ARB_dsa isn't
supported - see comments in gl_hookset.h).
* Implemented the new functions except for the glTexture* family and the
glCreate* family. No deduplication of code yet.
* As with EXT_dsa we "promote" to the DSA function for serialisation,
but since unlike EXT_dsa we can't assume ARB_dsa is present, instead
we emulate those functions that we might use unconditionally but may
not be present.
* It's not exactly feature parity but it's a start, and any UI would use
this under the hood.
* This means at least linux has a semi user-friendly way to launch and
capture programs - it's limited but you can just use
$ ./bin/renderdoccmd -c /path/to/program "argument string"
from the root of the repository.
* Logfile and capture options (which can't be set yet, but you could easily
hack in something to set them in renderdoccmd.cpp) are passed via
environment variables to the child process.
* To remove renderdoc (e.g. if the API version doesn't match what is
expected), user code can call RENDERDOC_Shutdown() to remove the running
thread and undo any library hooks, then unload the dynamic library.
* This still isn't recommended as there could be unexpected side-effects,
and it will definitely break if this happens after any APIs have been
initialised, but it's an option.
* I will assume for now that any wgl functions I don't explicitly hook have
no effect on the captured frame and we can safely just let them straight
through to the real function.
* Now instead of returning NULL for entry points that we don't support and
hoping the application will handle that or error out, instead we return
a function that will log an error if it is ever called, and then pass
through to the real function. In most cases, the capture will probably be
broken as whichever function isn't saved.
* hookset.pl is much faster too, it outputs the whole gl_hookset_defs.h
file and doesn't do multiple searches over the whole set of headers in
official/ for each function.
* When a compatibility context is created (via the old CreateContext, or
via an appropriate CreateContextAttribs call), we can still do the vendor
checks but we want to make sure we perform them again if we ever create a
core profile context. Note that actually *using* a compatibility context
isn't supported at the moment, but this won't explicitly break that.
* This lets us detect if the FBO/VAO behaviour is different from the main
spec, and so we won't miss deletes or other events if the context is
different since we'll treat them as shared like any other object.
* We create fake backbuffer as SRGB if the original default backbuffer was
SRGB in the program.
* All of our output backbuffers are also SRGB, and we enable
GL_FRAMEBUFFER_SRGB when writing to them.
* Add the 'fake' srgb curve applied to linear data to display it as if it
were srgb, which tends to look intuitively correct even if it's not 100%
accurate. See the behaviour existing in D3D11 already.
* This means that all APIs pass byte string types. ALL strings everywhere
in the entire codebase must be assumed to be and treated as UTF-8 content
not ASCII.
* Gets rid of all the horrible %hs specifiers that caused warnings on
linux! Hooray.
* We convert to wide strings, or use wide characters, only when necessary
to use the Win32 API. Some windows specific code will stay in wide chars
just for convenience.
* Files are already serialised as UTF-8 strings for linux/windows binary
compatibility, so this change doesn't break backwards compatibility.
* There was a report of renderdoccmd.exe doing --cap32for64 in an infinite
loop on itself (each process trying to inject the previous). I'm not sure
how this could get started, but assuming this was happening automatically
for 'hook into children', try to break the infinite loop by refusing to
inject into our own exes.
* This is a bit complex. If an application has a global symbol e.g.
GLENABLE glEnable; as their function pointers that they fill out from
glXGetProcAddress, then OUR glEnable global function gets replaced with
that symbol. It's weird. But it means crashes if we try and return the
address of that symbol as a function pointer.
* However it's also possible to get the reverse problem - if an application
has a shared library that has those symbols expecting them to be function
pointers, those symbols will get overridden with our global functions
and it will mean an instant crash when they try to assign to those func
ptrs.
* I'm not sure if there is an ideal fix to this Catch-22, as we also need
to export these bare functions in case someone just plain links against
libGL and expects them to be there, with no GetProcAddress/dlsym funny
business.