* Instead of passing the resource handle itself to GetSize_InitialState or
Serialise_InitialState, we pass the Id, ResourceRecord, and prepared initial
contents. All of these can survive past the destruction of the resource.
* Removes the need for AllowDeletedResource_InitialState() - it's always allowed
now.
* Need_InitialStateChunk is also refactored but it's only used on D3D11
currently and potentially will be removed in future.
* This was used for two things:
- UAVs on D3D11, which we can just mark dirty at creation as we do
with things on D3D12/Vulkan where we know we'll always want initial
states.
- Texture views/Texture buffers on GL, where we check if the texture
was referenced and force initial states for the underlying data
store. This requires a bit more work but can still be achieved by a
GL-specific force-inclusion pass on the frame references.
* This option will now toggle on the behaviour to fill undefined buffer contents
with a marker value, both if they're created without data (it will be zero
filled instead) or mapped with discard (it will keep the old contents
instead).
* There were too many hard to find problems or misconceptions about the buffer
filling for it to be useful. Now it will be opt-in instead.
* This is a backwards-incompatible change, so it's done here before v1.0
so that we can freely break compatibility and not need to define a lot
of ugly compatibility code.
* The primary motivation is to make the serialised data more uniform
and have fewer special cases where the serialised form is naturally
defined from the functions/structs in question.
* There are still some special cases or variances but they should be
more isolated and only where really necessary.
* Remove some cases in the D3D12 struct serialising where we were
directly serialising child struct members in the parent struct.
* We now try to match argument/struct member order as closely as
possible.
* Serialising an array with a count no longer reads the count back out
into that variable, counts must be serialised separately. This means
all members/arguments are explicitly present in the structured data
and also eliminates the awkward case where a count needed to be
serialised separately after an array if we want to have the count be
a valid number even if the array could be NULL. It also means we don't
need the FIXED_COUNT() macro since array lengths can be plain values
and don't have to be a reference type.
* If we don't track their lifetimes specifically, then we can end up
with the situation where an application makes more state objects over
the course of its rendering than is legal (there can only be a max
4096 unique state objects of each time). This could happen if an
application creates state objects each frame with slight variances,
but then releases them again.
* ID3D11Device::CreateInputLayout will fail if we pass a NULL descriptor
array pointer, even though 0xdeadbeef will work so it doesn't actually
use the pointer at all.
* 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.
* In many cases (particularly on D3D11/D3D12) the replay would simply
forward functions as-is to the debug manager for implementation. This
meant that change any of those function signatures required more
tedious copy-pasting than was necessary, and didn't make much sense.
* Now the replay class is responsible for implementing all the
functionality and owns any debug-only API resources, but can still use
the debug manager for any indirect utility functions like caching,
etc.
* The API resources are better organised by task in the replay class
rather than being all over the place.
* Finally on vulkan, added some helper functions to reduce the
boilerplate involved in initialising objects.
* Instead of replaying predication, we now always skip it during replay,
so all objects will render. This is much more consistent and
understandable behaviour instead of things mysteriously disappearing
with no obvious reason why.
* We track the predication that would have happened and replay Begin/End
pairs so that we can know if the predication *would* have failed.
* This is displayed in the UI (currently in the raster state, for lack
of a better location) with the pass/fail that would have happened.
* This information can feed into other places for analysis like the
pixel history.
* This is a *very* light-touch analytics system that will track the
simplest and most anonymous statistics that can be useful in
determining which features are most used or perhaps underused, and
where it's best to direct development attention.
* It is entirely implemented in the UI layer, no analytics-gathering
code exists in the library that's injected into programs, and of
course no capture data (screenshots, resource contents, shaders, etc
etc) is transmitted.
* Once it's turned on, it will apply to both development and release
builds. It tracks stats over a month, and then at the beginning of a
new month it sends the previous data.
* When the user first starts up a build with analytics if there's no
previous analytics database then they are informed of the new code and
asked to approve it. They have the option of selecting to manually
verify any sent reports, or just opt-ing out entirely.
* For a few primary cases, we check to see if the API call failed (or is
looking like it will fail, in the case of vulkan) and bail out. This
will cause the capture to fail to load.
* In each function, we check that serialisation succeeded before going
on to actually call into the API. If something went wrong, then we
bail out and fail to load the capture.
* Reported by Coverity Scan - most of these are not an issue and a
couple of them are coverity getting really confused (like seeing a
pointer being assigned to NULL and a count to 0, then a few lines
later declaring that a loop 0..count will dereference the pointer).
* However it's harmless in all cases to add a bit of robustness to keep
the analysis happy.
* 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.
* Note that while this is public and uses std::string, because it's a
template with specialisations in a .inl the string never crosses a
module boundary - each including module has its own implementation.
* This will be used as part of the upcoming serialisation refactor.
* Some POD structs are still given ToStr implementations as we haven't
yet switched over the serialisation system to expect all structs to
have serialise functions.
* This avoids having to go throug the pool checking when we know
concretely what type we're looking up, we just need to cast to the
wrapped type and fetch it.
* This allows better identification of a shader from its reflection
bundle. The entry point was already 'optionally' in the debug info
struct which is no longer a great location for it.
* For APIs where the entry point isn't contractual and it might not be
listed, instead we just fall back to 'main'. This means that the UI
or anyone fetching the info can be guaranteed that some sensible entry
point will be listed.
* Also for the debug info, remove the 'entryFile' index and instead just
guarantee that as much as possible the entry point will be in the
first file in the list.
* If we create non-wrapped objects for debugging purposes like states
and scratch buffers, then this can interact poorly with the device
context which expects all objects bound to it to be wrapped.
* In particular if the pixel history is running and binds an unwrapped
rasterizer state, then tries to replay a draw which is a command list
execute the current device context pipeline state is saved (to be
restored at the end of the command list) and when querying the current
state an unwrapped object is found and everything blows up.
* There wasn't really a good reason for using unwrapped objects. The
primary reason to do so is to avoid polluting captures but little of
this code runs at capture time. We can also filter out debug-only
objects at replay time by ensuring only things with a valid original
ID are returned.
* Note we also need to allow for state objects in the capture to be
duplicates of debug states we created. We already handled this for
blend states but apparently not for other types of states.
* Previously they were only set when replaying a recorded SetPrivateData
which meant any blob paths specified in the private blob part didn't
have the search paths configured for locating relative paths.
* Only one major piece of functionality is unimplemented and stubbed out
- WriteToSubresource and ReadFromSubresource in concert with passing
a NULL D3D11_MAPPED_SUBRESOURCE parameter to ID3D11DeviceContext::Map.
* The main improvement is that instead of just callstack resolving DB
and frame capture data, some arbtirary number of sections can be
included, for e.g. adding notes or saving the bookmarks or whatever
use the user wants.
* Sections (namely the frame capture data) can now be (de)compressed on
I/O, which leads to much smaller file sizes.
* Also the default internal alignment has changed from 16 to 64 to be
more future proof (I decided not to go with completely arbitrary
alignment).
* A path for loading previous version logs remains and will be removed
at some point in the future, maybe a version or two down the line.
* This is a slightly simpler implementation of the above pull request.
Only the disassembly is done lazily since everything else is pretty
much always requested during log reading.
* I didn't measure much difference of this but I think it depends on
having a lot of shaders with heavyweight shader debug info.