* VK_EXT_astc_decode_mode
* VK_EXT_swapchain_colorspace - this will cause slight artifacts as we won't
interpret pixels in the right color space, but it's minor.
* VK_EXT_validation_cache - we don't serialise this but we do allow it during
capture and pass-through straight. We don't wrap the VkValidationCacheEXT
object at all which makes support simpler.
* VK_EXT_external_memory_dma_buf - this is just a new memory type for external
memory, we don't need to do anything special to handle it.
* VK_AMD_mixed_attachment_samples & VK_AMD_shader_core_properties - these are
no-op once enabled
* Many shader-only extensions:
- VK_AMD_gpu_shader_int16
- VK_AMD_shader_fragment_mask
- VK_AMD_image_load_store_lod
- VK_AMD_texture_gather_bias_lod
- VK_NV_compute_shader_derivatives
- VK_NV_fragment_shader_barycentric
- VK_NV_geometry_shader_passthrough
- VK_NV_sample_mask_override_coverage
- VK_NV_shader_image_footprint
- VK_NV_shader_subgroup_partitioned
- VK_NV_viewport_array2
* This reads the argument once during load exactly when the draw itself
executes. We read just before the draw in case the draw itself would modify
the params (which is likely invalid, but something we should avoid).
* Rather than not serialising structs that we aren't interested in, we serialise
them (as best as we can in some cases) so that the information is available to
the user. Also if in future we decide to replay them they are available.
* We also now replay dedicated allocation extension use.
* We handle non-suffixed promoted functions but assume that calling
forward to either the promoted function or the old KHR extension is
equivalent.
* By this nature we won't record which function the user called, be that
extension or promoted, it will just be reported as the core function.
* Remove KHR suffixes from function names, enums, etc for promoted
extensions when serialising/stringising.
* We report no support for Ycbcr conversions by snooping the physical
device feature query.
* Just to be safe, we support pass-through/ignore implementations of
most of the functions and pNext structs.
* Any struct with a pNext pointer gets a Deserialise function, to clean
up any dynamically allocated chains.
* The mechanism is as follows:
- On writing, walk the pNext chain (assuming there is one) and skip
any structs we don't care to serialise.
- When we reach a struct we do want to serialise, save a nullable (i.e
optional) VkStructureType* for it, then recurse and serialise the
nullable casted struct.
- If there is no pNext (or none we care about) we serialise a NULL
VkStructureType*
- On reading, we serialise the VkStructureType*. If it's NULL, rename
it to look like a void *pNext = NULL.
- If it's not NULL, use the structure type to serialise a nullable
struct of the right type, and recurse.
* The pNext chain is dynamically allocated, which is why it gets cleaned
up in the Deserialise() function.
* 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.
* By default this is off as it will continually add more and more
messages each time the frame is replayed. It could be useful to turn
on to
* We also enable VK_EXT_debug_report any time it's available, not just
when we're enabling the validation layers.
* There's weird behaviour seen where after binding a descriptor set with
an offset, subsequent work in other command buffers doesn't behave
correctly. Re-binding the descriptor set with a 0 offset seems to fix
it, so I assume the offset is leaking and applying to subsequent
binds that don't have any dynamic offsets.
* Currently we only have structured data for the CPU-side calls, but we
want to display the information for the individual selectable GPU-side
commands.
* So we add a new fake virtual chunk and insert it with data pulled from
the GPU information, and any meta-data like the offset of that
command.
* 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.
* Previously we'd cache a copy of each command buffer at load time, and
submit it any time we're not partially re-recording. This has a couple
of drawbacks though:
- Technically we do some things that invalidate those command buffers,
like updating descriptor sets (with initial state application) and
so for 100% correctness we'd need to re-record.
- It also means that any edits we apply, like modified shaders, don't
properly apply to the whole frame, they only apply to whichever
command buffer is currently being partially recorded.
* We refactor out the 're-record all commands' behaviour previously
reserved just for applying GPU counters, and use that for re-recording
any command buffers that are wholly or partially submitted. Note that
it's still true that only one primary and one secondary at most are
actually *partially* re-recorded. The others are re-recorded in their
entirety.
* This makes API-agnostic processing over strucutred data a *little*
easier. At least it's possible to differentiate initialisation from
frame capture chunks.
* 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.
* This also includes serialising vulkan handles as Ids by type instead
of using a macro as before.
* In contrast to the old code, we serialise handles as the wrapped type
since e.g. when serialising a command buffer in a vkCmd* function we
want to get back the wrapped type. This means some structs need to be
unwrapped on replay when before they were "pre-unwrapped" after the
serialisation, but this isn't a big deal.
* 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.