Prepare for actually serialising pNext pointers in 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 commit is contained in:
baldurk
2018-04-24 18:38:08 +01:00
parent 0fbeace478
commit e9a47112d4
2 changed files with 328 additions and 85 deletions
+37
View File
@@ -271,6 +271,24 @@ void AppendModifiedChainedStruct(byte *&tempMem, VkStruct *outputStruct,
nextChainTail = (VkGenericStruct *)outputStruct;
}
template <typename VkStruct>
const VkGenericStruct *FindNextStruct(const VkStruct *haystack, VkStructureType needle)
{
if(!haystack)
return NULL;
const VkGenericStruct *next = (const VkGenericStruct *)haystack->pNext;
while(next)
{
if(next->sType == needle)
return next;
next = next->pNext;
}
return NULL;
}
enum class MemoryScope : uint8_t
{
InitialContents,
@@ -602,7 +620,9 @@ DECLARE_REFLECTION_STRUCT(VkBindImageMemoryInfoKHR);
DECLARE_DESERIALISE_TYPE(VkDeviceCreateInfo);
DECLARE_DESERIALISE_TYPE(VkBufferCreateInfo);
DECLARE_DESERIALISE_TYPE(VkBufferViewCreateInfo);
DECLARE_DESERIALISE_TYPE(VkImageCreateInfo);
DECLARE_DESERIALISE_TYPE(VkImageViewCreateInfo);
DECLARE_DESERIALISE_TYPE(VkBindSparseInfo);
DECLARE_DESERIALISE_TYPE(VkSubmitInfo);
DECLARE_DESERIALISE_TYPE(VkDescriptorSetAllocateInfo);
@@ -610,15 +630,32 @@ DECLARE_DESERIALISE_TYPE(VkFramebufferCreateInfo);
DECLARE_DESERIALISE_TYPE(VkRenderPassCreateInfo);
DECLARE_DESERIALISE_TYPE(VkRenderPassBeginInfo);
DECLARE_DESERIALISE_TYPE(VkCommandBufferBeginInfo);
DECLARE_DESERIALISE_TYPE(VkCommandPoolCreateInfo);
DECLARE_DESERIALISE_TYPE(VkCommandBufferAllocateInfo);
DECLARE_DESERIALISE_TYPE(VkPipelineCacheCreateInfo);
DECLARE_DESERIALISE_TYPE(VkPipelineLayoutCreateInfo);
DECLARE_DESERIALISE_TYPE(VkShaderModuleCreateInfo);
DECLARE_DESERIALISE_TYPE(VkGraphicsPipelineCreateInfo);
DECLARE_DESERIALISE_TYPE(VkComputePipelineCreateInfo);
DECLARE_DESERIALISE_TYPE(VkDescriptorPoolCreateInfo);
DECLARE_DESERIALISE_TYPE(VkQueryPoolCreateInfo);
DECLARE_DESERIALISE_TYPE(VkSemaphoreCreateInfo);
DECLARE_DESERIALISE_TYPE(VkEventCreateInfo);
DECLARE_DESERIALISE_TYPE(VkFenceCreateInfo);
DECLARE_DESERIALISE_TYPE(VkSamplerCreateInfo);
DECLARE_DESERIALISE_TYPE(VkMemoryAllocateInfo);
DECLARE_DESERIALISE_TYPE(VkMemoryBarrier);
DECLARE_DESERIALISE_TYPE(VkBufferMemoryBarrier);
DECLARE_DESERIALISE_TYPE(VkImageMemoryBarrier);
DECLARE_DESERIALISE_TYPE(VkWriteDescriptorSet);
DECLARE_DESERIALISE_TYPE(VkCopyDescriptorSet);
DECLARE_DESERIALISE_TYPE(VkDescriptorSetLayoutCreateInfo);
DECLARE_DESERIALISE_TYPE(VkDescriptorUpdateTemplateCreateInfoKHR);
DECLARE_DESERIALISE_TYPE(VkMappedMemoryRange);
DECLARE_DESERIALISE_TYPE(VkSwapchainCreateInfoKHR);
DECLARE_DESERIALISE_TYPE(VkDebugMarkerMarkerInfoEXT);
DECLARE_DESERIALISE_TYPE(VkBindBufferMemoryInfoKHR);
DECLARE_DESERIALISE_TYPE(VkBindImageMemoryInfoKHR);
DECLARE_REFLECTION_ENUM(VkFlagWithNoBits);
DECLARE_REFLECTION_ENUM(VkQueueFlagBits);
+291 -85
View File
@@ -119,80 +119,156 @@ void DoSerialiseViaResourceId(SerialiserType &ser, type &el)
SERIALISE_VK_HANDLES();
template <typename SerialiserType>
void DoSerialise(SerialiserType &ser, VkGenericStruct &el)
{
SERIALISE_MEMBER(sType);
SERIALISE_MEMBER_OPT(pNext);
RDCERR("Unexpected VkGenericStruct being serialised!");
// here we'd switch on sType to serialise the rest of the members
}
// pNext structure type dispatch
#define HANDLE_PNEXT() \
/* we can ignore all external memory extension structs entirely. We don't need to */ \
/* serialise or replay it as we won't actually use external memory and will just create */ \
/* normal memory to replay with. */ \
\
/* VK_NV_external_memory / VK_NV_external_memory_win32 */ \
PNEXT_IGNORE(VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO_NV) \
PNEXT_IGNORE(VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO_NV) \
PNEXT_IGNORE(VK_STRUCTURE_TYPE_IMPORT_MEMORY_WIN32_HANDLE_INFO_NV) \
PNEXT_IGNORE(VK_STRUCTURE_TYPE_EXPORT_MEMORY_WIN32_HANDLE_INFO_NV) \
\
/* VK_NV_win32_keyed_mutex */ \
PNEXT_IGNORE(VK_STRUCTURE_TYPE_WIN32_KEYED_MUTEX_ACQUIRE_RELEASE_INFO_NV) \
\
/* VK_KHR_external_memory / ..._fd / .._win32 */ \
PNEXT_IGNORE(VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO_KHR) \
PNEXT_IGNORE(VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO_KHR) \
PNEXT_IGNORE(VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_BUFFER_CREATE_INFO_KHR) \
PNEXT_IGNORE(VK_STRUCTURE_TYPE_IMPORT_MEMORY_WIN32_HANDLE_INFO_KHR) \
PNEXT_IGNORE(VK_STRUCTURE_TYPE_EXPORT_MEMORY_WIN32_HANDLE_INFO_KHR) \
PNEXT_IGNORE(VK_STRUCTURE_TYPE_IMPORT_MEMORY_FD_INFO_KHR) \
\
/* VK_KHR_external_semaphore / .._fd / ..._win32 */ \
PNEXT_IGNORE(VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_CREATE_INFO_KHR) \
PNEXT_IGNORE(VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_WIN32_HANDLE_INFO_KHR) \
\
/* we don't create real swapchains on replay, so we can ignore surface counters */ \
/* VK_EXT_display_control */ \
PNEXT_IGNORE(VK_STRUCTURE_TYPE_SWAPCHAIN_COUNTER_CREATE_INFO_EXT) \
\
/* for now we don't serialise dedicated memory on replay as it's only a performance */ \
/* hint, and is only required in conjunction with shared memory (which we don't */ \
/* replay). In future it might be helpful to serialise this for informational purposes. */ \
\
/* VK_NV_dedicated_allocation */ \
PNEXT_IGNORE(VK_STRUCTURE_TYPE_DEDICATED_ALLOCATION_MEMORY_ALLOCATE_INFO_NV) \
PNEXT_IGNORE(VK_STRUCTURE_TYPE_DEDICATED_ALLOCATION_IMAGE_CREATE_INFO_NV) \
PNEXT_IGNORE(VK_STRUCTURE_TYPE_DEDICATED_ALLOCATION_BUFFER_CREATE_INFO_NV) \
\
/* VK_KHR_dedicated_allocation */ \
PNEXT_IGNORE(VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO_KHR)
template <typename SerialiserType>
static void SerialiseNext(SerialiserType &ser, VkStructureType &sType, const void *&pNext)
{
// this is the parent sType, serialised here for convenience
ser.Serialise("sType", sType);
// we just serialise a dummy pointer to preserve it here.
VkGenericStruct *dummy = NULL;
ser.SerialiseNullable("pNext", dummy);
if(ser.IsReading())
{
// default to a NULL pNext
pNext = NULL;
}
else
{
if(pNext == NULL)
return;
// serialise a nullable next type, to tell us the type of object that's serialised. This is
// hidden as it doesn't correspond to the actual pNext, it's just metadata to help us launch the
// serialisation.
VkStructureType *nextType = NULL;
ser.SerialiseNullable("pNext", nextType);
// most common case - no pNext serialised. Bail immediately
if(nextType == NULL)
{
// fixup the structured data, set the type to void*
ser.TypedAs("void *");
return;
}
// hide and rename the pNextType if we got something - we'll want the pNext below to be the only
// thing user-facing.
ser.Named("pNextType").Hidden();
// any pNext structs that we ignore should not be present on reading - print an error
#define PNEXT_IGNORE(StructType) \
case StructType: RDCERR("Serialised ignore struct %s", ToStr(*nextType).c_str()); break;
// if we come across a struct we should process, then serialise a pointer to it.
#define PNEXT_STRUCT(StructType, StructName) \
case StructType: \
{ \
StructName *nextStruct = NULL; \
ser.SerialiseNullable("pNext", nextStruct); \
pNext = nextStruct; \
break; \
}
// this serialises the pNext with the right type, as nullable. We already know from above that
// there IS something here, so the nullable is redundant but convenient
switch(*nextType)
{
HANDLE_PNEXT();
default:
{
RDCERR("Unexpected/unhandled next structure type %s", ToStr(*nextType).c_str());
break;
}
}
// delete the type itself. Any pNext we serialised is saved in the pNext pointer and will be
// deleted in DeserialiseNext()
delete nextType;
// note, we don't have to serialise more of the chain - this is recursive, if there was more of
// the pNext chain it would be done recursively above
}
else // ser.IsWriting()
{
// any pNext structs that we ignore, just break and keep walking the chain
#undef PNEXT_IGNORE
#define PNEXT_IGNORE(StructType) \
case StructType: break;
// if we come across a struct we should process, then serialise a pointer to its type (to tell the
// reading serialisation what struct is coming up), then a pointer to it.
// We don't have to go any further, the act of serialising this struct will walk the chain further,
// so we can return immediately.
#undef PNEXT_STRUCT
#define PNEXT_STRUCT(StructType, StructName) \
case StructType: \
{ \
VkStructureType *nextType = &next->sType; \
ser.SerialiseNullable("pNextType", nextType); \
StructName *actual = (StructName *)next; \
ser.SerialiseNullable("pNext", actual); \
return; \
}
// walk the pNext chain, skipping any structs we don't care about serialising.
VkGenericStruct *next = (VkGenericStruct *)pNext;
while(next)
{
// we can ignore this entirely, we don't need to serialise or replay it as we won't
// actually use external memory. Unwrapping, if necessary, happens elsewhere
if(next->sType == VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO_NV ||
next->sType == VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO_NV ||
next->sType == VK_STRUCTURE_TYPE_IMPORT_MEMORY_WIN32_HANDLE_INFO_NV ||
next->sType == VK_STRUCTURE_TYPE_EXPORT_MEMORY_WIN32_HANDLE_INFO_NV ||
next->sType == VK_STRUCTURE_TYPE_WIN32_KEYED_MUTEX_ACQUIRE_RELEASE_INFO_NV ||
next->sType == VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO_KHR ||
next->sType == VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO_KHR ||
next->sType == VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_BUFFER_CREATE_INFO_KHR ||
next->sType == VK_STRUCTURE_TYPE_IMPORT_MEMORY_WIN32_HANDLE_INFO_KHR ||
next->sType == VK_STRUCTURE_TYPE_EXPORT_MEMORY_WIN32_HANDLE_INFO_KHR ||
next->sType == VK_STRUCTURE_TYPE_IMPORT_MEMORY_FD_INFO_KHR ||
next->sType == VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_CREATE_INFO_KHR ||
next->sType == VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_WIN32_HANDLE_INFO_KHR)
switch(next->sType)
{
// do nothing
}
// likewise we don't create real swapchains, so we can ignore surface counters
else if(next->sType == VK_STRUCTURE_TYPE_SWAPCHAIN_COUNTER_CREATE_INFO_EXT)
{
// do nothing
}
// for now we don't serialise dedicated memory on replay as it's only a performance hint,
// and is only required in conjunction with shared memory (which we don't replay). In future
// it might be helpful to serialise this for informational purposes.
else if(next->sType == VK_STRUCTURE_TYPE_DEDICATED_ALLOCATION_MEMORY_ALLOCATE_INFO_NV ||
next->sType == VK_STRUCTURE_TYPE_DEDICATED_ALLOCATION_IMAGE_CREATE_INFO_NV ||
next->sType == VK_STRUCTURE_TYPE_DEDICATED_ALLOCATION_BUFFER_CREATE_INFO_NV ||
next->sType == VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO_KHR)
{
// do nothing
}
else
{
RDCERR("Unrecognised extension structure type %d", next->sType);
HANDLE_PNEXT();
default:
{
RDCERR("Unrecognised extension structure type %s", ToStr(next->sType).c_str());
break;
}
}
// walk to the next item if we didn't serialise the current one
next = (VkGenericStruct *)next->pNext;
}
// if we got here, either pNext was NULL (common) or we skipped the whole chain. Serialise a
// NULL structure type to indicate that.
VkStructureType *dummy = NULL;
ser.SerialiseNullable("pNext", dummy);
}
}
@@ -204,6 +280,17 @@ static void SerialiseNext(SerialiserType &ser, VkStructureType &sType, void *&pN
pNext = (void *)tmpNext;
}
static inline void DeserialiseNext(const void *pNext)
{
if(pNext == NULL)
return;
// walk the chain, deserialising from the tail back
const VkGenericStruct *gen = (const VkGenericStruct *)pNext;
DeserialiseNext(gen->pNext);
delete gen;
}
template <typename SerialiserType>
void DoSerialise(SerialiserType &ser, VkAllocationCallbacks &el)
{
@@ -479,9 +566,12 @@ void DoSerialise(SerialiserType &ser, VkDeviceCreateInfo &el)
template <>
void Deserialise(const VkDeviceCreateInfo &el)
{
RDCASSERT(el.pNext == NULL); // otherwise delete
DeserialiseNext(el.pNext);
for(uint32_t i = 0; i < el.queueCreateInfoCount; i++)
{
DeserialiseNext(el.pQueueCreateInfos[i].pNext);
delete[] el.pQueueCreateInfos[i].pQueuePriorities;
}
delete[] el.pQueueCreateInfos;
delete[] el.ppEnabledExtensionNames;
delete[] el.ppEnabledLayerNames;
@@ -516,7 +606,7 @@ void DoSerialise(SerialiserType &ser, VkBufferCreateInfo &el)
template <>
void Deserialise(const VkBufferCreateInfo &el)
{
RDCASSERT(el.pNext == NULL); // otherwise delete
DeserialiseNext(el.pNext);
delete[] el.pQueueFamilyIndices;
}
@@ -533,6 +623,12 @@ void DoSerialise(SerialiserType &ser, VkBufferViewCreateInfo &el)
SERIALISE_MEMBER(range);
}
template <>
void Deserialise(const VkBufferViewCreateInfo &el)
{
DeserialiseNext(el.pNext);
}
template <typename SerialiserType>
void DoSerialise(SerialiserType &ser, VkImageCreateInfo &el)
{
@@ -569,7 +665,7 @@ void DoSerialise(SerialiserType &ser, VkImageCreateInfo &el)
template <>
void Deserialise(const VkImageCreateInfo &el)
{
RDCASSERT(el.pNext == NULL); // otherwise delete
DeserialiseNext(el.pNext);
delete[] el.pQueueFamilyIndices;
}
@@ -595,6 +691,12 @@ void DoSerialise(SerialiserType &ser, VkImageViewCreateInfo &el)
SERIALISE_MEMBER(subresourceRange);
}
template <>
void Deserialise(const VkImageViewCreateInfo &el)
{
DeserialiseNext(el.pNext);
}
template <typename SerialiserType>
void DoSerialise(SerialiserType &ser, VkSparseMemoryBind &el)
{
@@ -663,7 +765,7 @@ void DoSerialise(SerialiserType &ser, VkBindSparseInfo &el)
template <>
void Deserialise(const VkBindSparseInfo &el)
{
RDCASSERT(el.pNext == NULL); // otherwise delete
DeserialiseNext(el.pNext);
delete[] el.pWaitSemaphores;
for(uint32_t i = 0; i < el.bufferBindCount; i++)
delete[] el.pBufferBinds[i].pBinds;
@@ -706,7 +808,7 @@ void DoSerialise(SerialiserType &ser, VkSubmitInfo &el)
template <>
void Deserialise(const VkSubmitInfo &el)
{
RDCASSERT(el.pNext == NULL); // otherwise delete
DeserialiseNext(el.pNext);
delete[] el.pWaitSemaphores;
delete[] el.pCommandBuffers;
delete[] el.pSignalSemaphores;
@@ -730,7 +832,7 @@ void DoSerialise(SerialiserType &ser, VkFramebufferCreateInfo &el)
template <>
void Deserialise(const VkFramebufferCreateInfo &el)
{
RDCASSERT(el.pNext == NULL); // otherwise delete
DeserialiseNext(el.pNext);
delete[] el.pAttachments;
}
@@ -804,7 +906,7 @@ void DoSerialise(SerialiserType &ser, VkRenderPassCreateInfo &el)
template <>
void Deserialise(const VkRenderPassCreateInfo &el)
{
RDCASSERT(el.pNext == NULL); // otherwise delete
DeserialiseNext(el.pNext);
delete[] el.pAttachments;
for(uint32_t i = 0; i < el.subpassCount; i++)
{
@@ -835,7 +937,7 @@ void DoSerialise(SerialiserType &ser, VkRenderPassBeginInfo &el)
template <>
void Deserialise(const VkRenderPassBeginInfo &el)
{
RDCASSERT(el.pNext == NULL); // otherwise delete
DeserialiseNext(el.pNext);
delete[] el.pClearValues;
}
@@ -1008,6 +1110,12 @@ void DoSerialise(SerialiserType &ser, VkCommandPoolCreateInfo &el)
SERIALISE_MEMBER(queueFamilyIndex);
}
template <>
void Deserialise(const VkCommandPoolCreateInfo &el)
{
DeserialiseNext(el.pNext);
}
template <typename SerialiserType>
void DoSerialise(SerialiserType &ser, VkCommandBufferAllocateInfo &el)
{
@@ -1019,6 +1127,12 @@ void DoSerialise(SerialiserType &ser, VkCommandBufferAllocateInfo &el)
SERIALISE_MEMBER(commandBufferCount);
}
template <>
void Deserialise(const VkCommandBufferAllocateInfo &el)
{
DeserialiseNext(el.pNext);
}
template <typename SerialiserType>
void DoSerialise(SerialiserType &ser, VkCommandBufferInheritanceInfo &el)
{
@@ -1046,7 +1160,9 @@ void DoSerialise(SerialiserType &ser, VkCommandBufferBeginInfo &el)
template <>
void Deserialise(const VkCommandBufferBeginInfo &el)
{
RDCASSERT(el.pNext == NULL); // otherwise delete
DeserialiseNext(el.pNext);
if(el.pInheritanceInfo)
DeserialiseNext(el.pInheritanceInfo->pNext);
delete el.pInheritanceInfo;
}
@@ -1074,6 +1190,12 @@ void DoSerialise(SerialiserType &ser, VkQueryPoolCreateInfo &el)
SERIALISE_MEMBER_TYPED(VkQueryPipelineStatisticFlagBits, pipelineStatistics);
}
template <>
void Deserialise(const VkQueryPoolCreateInfo &el)
{
DeserialiseNext(el.pNext);
}
template <typename SerialiserType>
void DoSerialise(SerialiserType &ser, VkSemaphoreCreateInfo &el)
{
@@ -1083,6 +1205,12 @@ void DoSerialise(SerialiserType &ser, VkSemaphoreCreateInfo &el)
SERIALISE_MEMBER_TYPED(VkFlagWithNoBits, flags);
}
template <>
void Deserialise(const VkSemaphoreCreateInfo &el)
{
DeserialiseNext(el.pNext);
}
template <typename SerialiserType>
void DoSerialise(SerialiserType &ser, VkEventCreateInfo &el)
{
@@ -1092,6 +1220,12 @@ void DoSerialise(SerialiserType &ser, VkEventCreateInfo &el)
SERIALISE_MEMBER_TYPED(VkFlagWithNoBits, flags);
}
template <>
void Deserialise(const VkEventCreateInfo &el)
{
DeserialiseNext(el.pNext);
}
template <typename SerialiserType>
void DoSerialise(SerialiserType &ser, VkFenceCreateInfo &el)
{
@@ -1101,6 +1235,12 @@ void DoSerialise(SerialiserType &ser, VkFenceCreateInfo &el)
SERIALISE_MEMBER_TYPED(VkFenceCreateFlagBits, flags);
}
template <>
void Deserialise(const VkFenceCreateInfo &el)
{
DeserialiseNext(el.pNext);
}
template <typename SerialiserType>
void DoSerialise(SerialiserType &ser, VkSamplerCreateInfo &el)
{
@@ -1125,6 +1265,12 @@ void DoSerialise(SerialiserType &ser, VkSamplerCreateInfo &el)
SERIALISE_MEMBER(unnormalizedCoordinates);
}
template <>
void Deserialise(const VkSamplerCreateInfo &el)
{
DeserialiseNext(el.pNext);
}
template <typename SerialiserType>
void DoSerialise(SerialiserType &ser, VkPipelineShaderStageCreateInfo &el)
{
@@ -1193,7 +1339,7 @@ void DoSerialise(SerialiserType &ser, VkPipelineCacheCreateInfo &el)
template <>
void Deserialise(const VkPipelineCacheCreateInfo &el)
{
RDCASSERT(el.pNext == NULL); // otherwise delete
DeserialiseNext(el.pNext);
FreeAlignedBuffer((byte *)el.pInitialData);
}
@@ -1213,7 +1359,7 @@ void DoSerialise(SerialiserType &ser, VkPipelineLayoutCreateInfo &el)
template <>
void Deserialise(const VkPipelineLayoutCreateInfo &el)
{
RDCASSERT(el.pNext == NULL); // otherwise delete
DeserialiseNext(el.pNext);
delete[] el.pSetLayouts;
delete[] el.pPushConstantRanges;
}
@@ -1246,7 +1392,7 @@ void DoSerialise(SerialiserType &ser, VkShaderModuleCreateInfo &el)
template <>
void Deserialise(const VkShaderModuleCreateInfo &el)
{
RDCASSERT(el.pNext == NULL); // otherwise delete
DeserialiseNext(el.pNext);
FreeAlignedBuffer((byte *)el.pCode);
}
@@ -1287,6 +1433,12 @@ void DoSerialise(SerialiserType &ser, VkMemoryAllocateInfo &el)
SERIALISE_MEMBER(memoryTypeIndex);
}
template <>
void Deserialise(const VkMemoryAllocateInfo &el)
{
DeserialiseNext(el.pNext);
}
template <typename SerialiserType>
void DoSerialise(SerialiserType &ser, VkMemoryBarrier &el)
{
@@ -1297,6 +1449,12 @@ void DoSerialise(SerialiserType &ser, VkMemoryBarrier &el)
SERIALISE_MEMBER_TYPED(VkAccessFlagBits, dstAccessMask);
}
template <>
void Deserialise(const VkMemoryBarrier &el)
{
DeserialiseNext(el.pNext);
}
template <typename SerialiserType>
void DoSerialise(SerialiserType &ser, VkBufferMemoryBarrier &el)
{
@@ -1318,6 +1476,12 @@ void DoSerialise(SerialiserType &ser, VkBufferMemoryBarrier &el)
SERIALISE_MEMBER(size);
}
template <>
void Deserialise(const VkBufferMemoryBarrier &el)
{
DeserialiseNext(el.pNext);
}
template <typename SerialiserType>
void DoSerialise(SerialiserType &ser, VkImageMemoryBarrier &el)
{
@@ -1340,6 +1504,12 @@ void DoSerialise(SerialiserType &ser, VkImageMemoryBarrier &el)
SERIALISE_MEMBER(subresourceRange);
}
template <>
void Deserialise(const VkImageMemoryBarrier &el)
{
DeserialiseNext(el.pNext);
}
template <typename SerialiserType>
void DoSerialise(SerialiserType &ser, VkGraphicsPipelineCreateInfo &el)
{
@@ -1370,27 +1540,27 @@ void DoSerialise(SerialiserType &ser, VkGraphicsPipelineCreateInfo &el)
template <>
void Deserialise(const VkGraphicsPipelineCreateInfo &el)
{
RDCASSERT(el.pNext == NULL); // otherwise delete
DeserialiseNext(el.pNext);
if(el.pVertexInputState)
{
RDCASSERT(el.pVertexInputState->pNext == NULL); // otherwise delete
DeserialiseNext(el.pVertexInputState->pNext);
delete[] el.pVertexInputState->pVertexBindingDescriptions;
delete[] el.pVertexInputState->pVertexAttributeDescriptions;
delete el.pVertexInputState;
}
if(el.pInputAssemblyState)
{
RDCASSERT(el.pInputAssemblyState->pNext == NULL); // otherwise delete
DeserialiseNext(el.pInputAssemblyState->pNext);
delete el.pInputAssemblyState;
}
if(el.pTessellationState)
{
RDCASSERT(el.pTessellationState->pNext == NULL); // otherwise delete
DeserialiseNext(el.pTessellationState->pNext);
delete el.pTessellationState;
}
if(el.pViewportState)
{
RDCASSERT(el.pViewportState->pNext == NULL); // otherwise delete
DeserialiseNext(el.pViewportState->pNext);
if(el.pViewportState->pViewports)
delete[] el.pViewportState->pViewports;
if(el.pViewportState->pScissors)
@@ -1399,36 +1569,36 @@ void Deserialise(const VkGraphicsPipelineCreateInfo &el)
}
if(el.pRasterizationState)
{
RDCASSERT(el.pRasterizationState->pNext == NULL); // otherwise delete
DeserialiseNext(el.pRasterizationState->pNext);
delete el.pRasterizationState;
}
if(el.pMultisampleState)
{
RDCASSERT(el.pMultisampleState->pNext == NULL); // otherwise delete
DeserialiseNext(el.pMultisampleState->pNext);
delete el.pMultisampleState->pSampleMask;
delete el.pMultisampleState;
}
if(el.pDepthStencilState)
{
RDCASSERT(el.pDepthStencilState->pNext == NULL); // otherwise delete
DeserialiseNext(el.pDepthStencilState->pNext);
delete el.pDepthStencilState;
}
if(el.pColorBlendState)
{
RDCASSERT(el.pColorBlendState->pNext == NULL); // otherwise delete
DeserialiseNext(el.pColorBlendState->pNext);
delete[] el.pColorBlendState->pAttachments;
delete el.pColorBlendState;
}
if(el.pDynamicState)
{
RDCASSERT(el.pDynamicState->pNext == NULL); // otherwise delete
DeserialiseNext(el.pDynamicState->pNext);
if(el.pDynamicState->pDynamicStates)
delete[] el.pDynamicState->pDynamicStates;
delete el.pDynamicState;
}
for(uint32_t i = 0; i < el.stageCount; i++)
{
RDCASSERT(el.pStages[i].pNext == NULL); // otherwise delete
DeserialiseNext(el.pStages[i].pNext);
if(el.pStages[i].pSpecializationInfo)
{
FreeAlignedBuffer((byte *)el.pStages[i].pSpecializationInfo->pData);
@@ -1455,8 +1625,8 @@ void DoSerialise(SerialiserType &ser, VkComputePipelineCreateInfo &el)
template <>
void Deserialise(const VkComputePipelineCreateInfo &el)
{
RDCASSERT(el.pNext == NULL); // otherwise delete
RDCASSERT(el.stage.pNext == NULL); // otherwise delete
DeserialiseNext(el.pNext);
DeserialiseNext(el.stage.pNext);
if(el.stage.pSpecializationInfo)
{
FreeAlignedBuffer((byte *)(el.stage.pSpecializationInfo->pData));
@@ -1487,7 +1657,7 @@ void DoSerialise(SerialiserType &ser, VkDescriptorPoolCreateInfo &el)
template <>
void Deserialise(const VkDescriptorPoolCreateInfo &el)
{
RDCASSERT(el.pNext == NULL); // otherwise delete
DeserialiseNext(el.pNext);
delete[] el.pPoolSizes;
}
@@ -1505,7 +1675,7 @@ void DoSerialise(SerialiserType &ser, VkDescriptorSetAllocateInfo &el)
template <>
void Deserialise(const VkDescriptorSetAllocateInfo &el)
{
RDCASSERT(el.pNext == NULL); // otherwise delete
DeserialiseNext(el.pNext);
delete[] el.pSetLayouts;
}
@@ -1627,7 +1797,7 @@ void DoSerialise(SerialiserType &ser, VkWriteDescriptorSet &el)
template <>
void Deserialise(const VkWriteDescriptorSet &el)
{
RDCASSERT(el.pNext == NULL); // otherwise delete
DeserialiseNext(el.pNext);
if(el.pImageInfo)
delete[] el.pImageInfo;
if(el.pBufferInfo)
@@ -1655,6 +1825,12 @@ void DoSerialise(SerialiserType &ser, VkCopyDescriptorSet &el)
SERIALISE_MEMBER(descriptorCount);
}
template <>
void Deserialise(const VkCopyDescriptorSet &el)
{
DeserialiseNext(el.pNext);
};
template <typename SerialiserType>
void DoSerialise(SerialiserType &ser, VkPushConstantRange &el)
{
@@ -1687,7 +1863,7 @@ void DoSerialise(SerialiserType &ser, VkDescriptorSetLayoutCreateInfo &el)
template <>
void Deserialise(const VkDescriptorSetLayoutCreateInfo &el)
{
RDCASSERT(el.pNext == NULL); // otherwise delete
DeserialiseNext(el.pNext);
for(uint32_t i = 0; i < el.bindingCount; i++)
if(el.pBindings[i].pImmutableSamplers)
delete[] el.pBindings[i].pImmutableSamplers;
@@ -1714,6 +1890,12 @@ void DoSerialise(SerialiserType &ser, VkMappedMemoryRange &el)
SERIALISE_MEMBER(size);
}
template <>
void Deserialise(const VkMappedMemoryRange &el)
{
DeserialiseNext(el.pNext);
}
template <typename SerialiserType>
void DoSerialise(SerialiserType &ser, VkBufferImageCopy &el)
{
@@ -1880,6 +2062,12 @@ void DoSerialise(SerialiserType &ser, VkSwapchainCreateInfoKHR &el)
SERIALISE_MEMBER_EMPTY(oldSwapchain);
}
template <>
void Deserialise(const VkSwapchainCreateInfoKHR &el)
{
DeserialiseNext(el.pNext);
}
template <typename SerialiserType>
void DoSerialise(SerialiserType &ser, VkDebugMarkerMarkerInfoEXT &el)
{
@@ -1890,6 +2078,12 @@ void DoSerialise(SerialiserType &ser, VkDebugMarkerMarkerInfoEXT &el)
SERIALISE_MEMBER(color);
}
template <>
void Deserialise(const VkDebugMarkerMarkerInfoEXT &el)
{
DeserialiseNext(el.pNext);
}
// this isn't a real vulkan type, it's our own "anything that could be in a descriptor"
// structure that
template <typename SerialiserType>
@@ -1976,7 +2170,7 @@ void DoSerialise(SerialiserType &ser, VkDescriptorUpdateTemplateCreateInfoKHR &e
template <>
void Deserialise(const VkDescriptorUpdateTemplateCreateInfoKHR &el)
{
RDCASSERT(el.pNext == NULL); // otherwise delete
DeserialiseNext(el.pNext);
delete[] el.pDescriptorUpdateEntries;
}
@@ -1991,6 +2185,12 @@ void DoSerialise(SerialiserType &ser, VkBindBufferMemoryInfoKHR &el)
SERIALISE_MEMBER(memoryOffset);
}
template <>
void Deserialise(const VkBindBufferMemoryInfoKHR &el)
{
DeserialiseNext(el.pNext);
}
template <typename SerialiserType>
void DoSerialise(SerialiserType &ser, VkBindImageMemoryInfoKHR &el)
{
@@ -2002,6 +2202,12 @@ void DoSerialise(SerialiserType &ser, VkBindImageMemoryInfoKHR &el)
SERIALISE_MEMBER(memoryOffset);
}
template <>
void Deserialise(const VkBindImageMemoryInfoKHR &el)
{
DeserialiseNext(el.pNext);
}
INSTANTIATE_SERIALISE_TYPE(VkOffset2D);
INSTANTIATE_SERIALISE_TYPE(VkExtent2D);
INSTANTIATE_SERIALISE_TYPE(VkMemoryType);