From 1569a6f0dd7f290211009c29349ddb4753ee6210 Mon Sep 17 00:00:00 2001 From: baldurk Date: Fri, 25 May 2018 17:51:21 +0100 Subject: [PATCH] Serialise all structs in pNext and discard at replay time * 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. --- renderdoc/driver/vulkan/vk_common.cpp | 301 +++++- renderdoc/driver/vulkan/vk_common.h | 96 +- renderdoc/driver/vulkan/vk_serialise.cpp | 926 ++++++++++++++++-- renderdoc/driver/vulkan/vk_stringise.cpp | 107 ++ .../driver/vulkan/wrappers/vk_cmd_funcs.cpp | 18 + .../driver/vulkan/wrappers/vk_misc_funcs.cpp | 10 +- .../driver/vulkan/wrappers/vk_queue_funcs.cpp | 116 +-- .../vulkan/wrappers/vk_resource_funcs.cpp | 40 +- .../driver/vulkan/wrappers/vk_sync_funcs.cpp | 33 +- 9 files changed, 1393 insertions(+), 254 deletions(-) diff --git a/renderdoc/driver/vulkan/vk_common.cpp b/renderdoc/driver/vulkan/vk_common.cpp index 9cf949b20..33ad6642f 100644 --- a/renderdoc/driver/vulkan/vk_common.cpp +++ b/renderdoc/driver/vulkan/vk_common.cpp @@ -297,6 +297,8 @@ size_t GetNextPatchSize(const void *pNext) memSize += sizeof(VkDedicatedAllocationMemoryAllocateInfoNV); else if(next->sType == VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO) memSize += sizeof(VkMemoryDedicatedAllocateInfo); + else if(next->sType == VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_FLAGS_INFO) + memSize += sizeof(VkMemoryAllocateFlagsInfo); else if(next->sType == VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO_NV) memSize += sizeof(VkExportMemoryAllocateInfoNV); else if(next->sType == VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO) @@ -328,12 +330,34 @@ size_t GetNextPatchSize(const void *pNext) RDCERR("Support for VK_KHR_external_memory_win32 not compiled in"); #endif - // vkSamplerCreateInfo + // VkSamplerCreateInfo else if(next->sType == VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_INFO) memSize += sizeof(VkSamplerYcbcrConversionInfo); else if(next->sType == VK_STRUCTURE_TYPE_SAMPLER_REDUCTION_MODE_CREATE_INFO_EXT) memSize += sizeof(VkSamplerReductionModeCreateInfoEXT); + // VkSemaphoreCreateInfo + else if(next->sType == VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_CREATE_INFO) + memSize += sizeof(VkExportSemaphoreCreateInfoKHR); +#ifdef VK_KHR_external_semaphore_win32 + else if(next->sType == VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_WIN32_HANDLE_INFO_KHR) + memSize += sizeof(VkExportSemaphoreWin32HandleInfoKHR); +#else + else if(next->sType == VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_WIN32_HANDLE_INFO_KHR) + RDCERR("Support for VK_KHR_external_memory_win32 not compiled in"); +#endif + + // VkFenceCreateInfo + else if(next->sType == VK_STRUCTURE_TYPE_EXPORT_FENCE_CREATE_INFO) + memSize += sizeof(VkExportFenceCreateInfoKHR); +#ifdef VK_KHR_external_fence_win32 + else if(next->sType == VK_STRUCTURE_TYPE_EXPORT_FENCE_WIN32_HANDLE_INFO_KHR) + memSize += sizeof(VkExportFenceWin32HandleInfoKHR); +#else + else if(next->sType == VK_STRUCTURE_TYPE_EXPORT_FENCE_WIN32_HANDLE_INFO_KHR) + RDCERR("Support for VK_KHR_external_memory_win32 not compiled in"); +#endif + // VkImageCreateInfo else if(next->sType == VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO) memSize += sizeof(VkExternalMemoryImageCreateInfo); @@ -344,6 +368,14 @@ size_t GetNextPatchSize(const void *pNext) else if(next->sType == VK_STRUCTURE_TYPE_DEDICATED_ALLOCATION_IMAGE_CREATE_INFO_NV) memSize += sizeof(VkDedicatedAllocationImageCreateInfoNV); + // VkBufferCreateInfo + else if(next->sType == VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_BUFFER_CREATE_INFO) + memSize += sizeof(VkExternalMemoryBufferCreateInfoKHR); + else if(next->sType == VK_STRUCTURE_TYPE_DEDICATED_ALLOCATION_BUFFER_CREATE_INFO_NV) + memSize += sizeof(VkDedicatedAllocationBufferCreateInfoNV); + else if(next->sType == VK_STRUCTURE_TYPE_BIND_BUFFER_MEMORY_DEVICE_GROUP_INFO) + memSize += sizeof(VkBindBufferMemoryDeviceGroupInfo); + // VkBindImageMemoryInfo else if(next->sType == VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_SWAPCHAIN_INFO_KHR) memSize += sizeof(VkBindImageMemorySwapchainInfoKHR); @@ -352,35 +384,83 @@ size_t GetNextPatchSize(const void *pNext) else if(next->sType == VK_STRUCTURE_TYPE_BIND_IMAGE_PLANE_MEMORY_INFO) memSize += sizeof(VkBindImagePlaneMemoryInfo); + // VkSwapchainCreateInfoKHR + else if(next->sType == VK_STRUCTURE_TYPE_SWAPCHAIN_COUNTER_CREATE_INFO_EXT) + memSize += sizeof(VkSwapchainCounterCreateInfoEXT); + else if(next->sType == VK_STRUCTURE_TYPE_DEVICE_GROUP_SWAPCHAIN_CREATE_INFO_KHR) + memSize += sizeof(VkDeviceGroupSwapchainCreateInfoKHR); + + // VkDeviceQueueCreateInfo + else if(next->sType == VK_STRUCTURE_TYPE_DEVICE_QUEUE_GLOBAL_PRIORITY_CREATE_INFO_EXT) + memSize += sizeof(VkDeviceQueueGlobalPriorityCreateInfoEXT); + + // VkSubmitInfo + else if(next->sType == VK_STRUCTURE_TYPE_PROTECTED_SUBMIT_INFO) + memSize += sizeof(VkProtectedSubmitInfo); + else if(next->sType == VK_STRUCTURE_TYPE_DEVICE_GROUP_SUBMIT_INFO) + memSize += sizeof(VkDeviceGroupSubmitInfo); + +#if defined(VK_KHR_win32_keyed_mutex) || defined(VK_NV_win32_keyed_mutex) + else if(next->sType == VK_STRUCTURE_TYPE_WIN32_KEYED_MUTEX_ACQUIRE_RELEASE_INFO_NV || + next->sType == VK_STRUCTURE_TYPE_WIN32_KEYED_MUTEX_ACQUIRE_RELEASE_INFO_KHR) + { + // the KHR and NV structs are identical + memSize += sizeof(VkWin32KeyedMutexAcquireReleaseInfoKHR); + + VkWin32KeyedMutexAcquireReleaseInfoKHR *info = (VkWin32KeyedMutexAcquireReleaseInfoKHR *)next; + memSize += info->acquireCount * sizeof(VkDeviceMemory); + memSize += info->releaseCount * sizeof(VkDeviceMemory); + } +#else + else if(next->sType == VK_STRUCTURE_TYPE_WIN32_KEYED_MUTEX_ACQUIRE_RELEASE_INFO_NV || + next->sType == VK_STRUCTURE_TYPE_WIN32_KEYED_MUTEX_ACQUIRE_RELEASE_INFO_KHR) + { + RDCERR("Support for VK_KHR_win32_keyed_mutex / VK_NV_win32_keyed_mutex not compiled in"); + } +#endif + + // VkBindSparseInfo + else if(next->sType == VK_STRUCTURE_TYPE_DEVICE_GROUP_BIND_SPARSE_INFO) + memSize += sizeof(VkDeviceGroupBindSparseInfo); + + // VkCommandBufferBeginInfo + else if(next->sType == VK_STRUCTURE_TYPE_DEVICE_GROUP_COMMAND_BUFFER_BEGIN_INFO) + memSize += sizeof(VkDeviceGroupCommandBufferBeginInfo); + + // VkRenderPassBeginInfo + else if(next->sType == VK_STRUCTURE_TYPE_DEVICE_GROUP_RENDER_PASS_BEGIN_INFO) + memSize += sizeof(VkDeviceGroupRenderPassBeginInfo); + next = next->pNext; } return memSize; } -void PatchNextChain(const char *structName, byte *&tempMem, VkGenericStruct *infoStruct) +void UnwrapNextChain(CaptureState state, const char *structName, byte *&tempMem, + VkGenericStruct *infoStruct) { + // during capture, this walks the pNext chain and either copies structs that can be passed + // straight through, or copies and modifies any with vulkan objects that need to be unwrapped. + // + // during replay, we do the same thing to prepare for dispatching to the driver, but we also strip + // out any structs we don't want to replay - e.g. external memory. This means the data is + // serialised and available for future use and for user inspection, but isn't replayed when not + // necesary. + VkGenericStruct *nextChainTail = infoStruct; const VkGenericStruct *nextInput = (const VkGenericStruct *)infoStruct->pNext; + + // start with an empty chain. Every call to AppendModifiedChainedStruct / CopyNextChainedStruct + // pushes on a new entry, but if there's only one entry in the list and it's one we want to skip, + // this needs to start at NULL. + nextChainTail->pNext = NULL; while(nextInput) { - // unwrap and replace the dedicated allocation struct in the chain - if(nextInput->sType == VK_STRUCTURE_TYPE_DEDICATED_ALLOCATION_MEMORY_ALLOCATE_INFO_NV) - { - const VkDedicatedAllocationMemoryAllocateInfoNV *dedicatedIn = - (const VkDedicatedAllocationMemoryAllocateInfoNV *)nextInput; - VkDedicatedAllocationMemoryAllocateInfoNV *dedicatedOut = - (VkDedicatedAllocationMemoryAllocateInfoNV *)tempMem; - - // copy and unwrap the struct - dedicatedOut->sType = dedicatedIn->sType; - dedicatedOut->buffer = Unwrap(dedicatedIn->buffer); - dedicatedOut->image = Unwrap(dedicatedIn->image); - - AppendModifiedChainedStruct(tempMem, dedicatedOut, nextChainTail); - } - else if(nextInput->sType == VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO) + if(nextInput->sType == VK_STRUCTURE_TYPE_DEDICATED_ALLOCATION_MEMORY_ALLOCATE_INFO_NV || + nextInput->sType == VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO) { + // KHR and NV structs are identical const VkMemoryDedicatedAllocateInfo *dedicatedIn = (const VkMemoryDedicatedAllocateInfo *)nextInput; VkMemoryDedicatedAllocateInfo *dedicatedOut = (VkMemoryDedicatedAllocateInfo *)tempMem; @@ -390,24 +470,33 @@ void PatchNextChain(const char *structName, byte *&tempMem, VkGenericStruct *inf dedicatedOut->buffer = Unwrap(dedicatedIn->buffer); dedicatedOut->image = Unwrap(dedicatedIn->image); + // we replay this AppendModifiedChainedStruct(tempMem, dedicatedOut, nextChainTail); } + else if(nextInput->sType == VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_FLAGS_INFO) + { + CopyNextChainedStruct(tempMem, nextInput, nextChainTail); + } else if(nextInput->sType == VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO_NV) { - CopyNextChainedStruct(tempMem, nextInput, nextChainTail); + if(IsCaptureMode(state)) + CopyNextChainedStruct(tempMem, nextInput, nextChainTail); } else if(nextInput->sType == VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO) { - CopyNextChainedStruct(tempMem, nextInput, nextChainTail); + if(IsCaptureMode(state)) + CopyNextChainedStruct(tempMem, nextInput, nextChainTail); } else if(nextInput->sType == VK_STRUCTURE_TYPE_IMPORT_MEMORY_FD_INFO_KHR) { - CopyNextChainedStruct(tempMem, nextInput, nextChainTail); + if(IsCaptureMode(state)) + CopyNextChainedStruct(tempMem, nextInput, nextChainTail); } else if(nextInput->sType == VK_STRUCTURE_TYPE_EXPORT_MEMORY_WIN32_HANDLE_INFO_KHR) { #ifdef VK_KHR_external_memory_win32 - CopyNextChainedStruct(tempMem, nextInput, nextChainTail); + if(IsCaptureMode(state)) + CopyNextChainedStruct(tempMem, nextInput, nextChainTail); #else RDCERR("Support for VK_KHR_external_memory_win32 not compiled in"); #endif @@ -415,7 +504,8 @@ void PatchNextChain(const char *structName, byte *&tempMem, VkGenericStruct *inf else if(nextInput->sType == VK_STRUCTURE_TYPE_IMPORT_MEMORY_WIN32_HANDLE_INFO_KHR) { #ifdef VK_KHR_external_memory_win32 - CopyNextChainedStruct(tempMem, nextInput, nextChainTail); + if(IsCaptureMode(state)) + CopyNextChainedStruct(tempMem, nextInput, nextChainTail); #else RDCERR("Support for VK_KHR_external_memory_win32 not compiled in"); #endif @@ -423,7 +513,8 @@ void PatchNextChain(const char *structName, byte *&tempMem, VkGenericStruct *inf else if(nextInput->sType == VK_STRUCTURE_TYPE_EXPORT_MEMORY_WIN32_HANDLE_INFO_NV) { #ifdef VK_NV_external_memory_win32 - CopyNextChainedStruct(tempMem, nextInput, nextChainTail); + if(IsCaptureMode(state)) + CopyNextChainedStruct(tempMem, nextInput, nextChainTail); #else RDCERR("Support for VK_NV_external_memory_win32 not compiled in"); #endif @@ -431,7 +522,8 @@ void PatchNextChain(const char *structName, byte *&tempMem, VkGenericStruct *inf else if(nextInput->sType == VK_STRUCTURE_TYPE_IMPORT_MEMORY_WIN32_HANDLE_INFO_NV) { #ifdef VK_NV_external_memory_win32 - CopyNextChainedStruct(tempMem, nextInput, nextChainTail); + if(IsCaptureMode(state)) + CopyNextChainedStruct(tempMem, nextInput, nextChainTail); #else RDCERR("Support for VK_NV_external_memory_win32 not compiled in"); #endif @@ -451,41 +543,93 @@ void PatchNextChain(const char *structName, byte *&tempMem, VkGenericStruct *inf { CopyNextChainedStruct(tempMem, nextInput, nextChainTail); } + else if(nextInput->sType == VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_CREATE_INFO) + { + if(IsCaptureMode(state)) + CopyNextChainedStruct(tempMem, nextInput, nextChainTail); + } + else if(nextInput->sType == VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_WIN32_HANDLE_INFO_KHR) + { +#ifdef VK_KHR_external_semaphore_win32 + if(IsCaptureMode(state)) + CopyNextChainedStruct(tempMem, nextInput, nextChainTail); +#else + RDCERR("Support for VK_KHR_external_semaphore_win32 not compiled in"); +#endif + } + else if(nextInput->sType == VK_STRUCTURE_TYPE_EXPORT_FENCE_CREATE_INFO) + { + if(IsCaptureMode(state)) + CopyNextChainedStruct(tempMem, nextInput, nextChainTail); + } + else if(nextInput->sType == VK_STRUCTURE_TYPE_EXPORT_FENCE_WIN32_HANDLE_INFO_KHR) + { +#ifdef VK_KHR_external_fence_win32 + + if(IsCaptureMode(state)) + CopyNextChainedStruct(tempMem, nextInput, nextChainTail); +#else + RDCERR("Support for VK_KHR_external_fence_win32 not compiled in"); +#endif + } else if(nextInput->sType == VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO) { - CopyNextChainedStruct(tempMem, nextInput, nextChainTail); + if(IsCaptureMode(state)) + CopyNextChainedStruct(tempMem, nextInput, nextChainTail); } else if(nextInput->sType == VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO_NV) { - CopyNextChainedStruct(tempMem, nextInput, nextChainTail); + if(IsCaptureMode(state)) + CopyNextChainedStruct(tempMem, nextInput, nextChainTail); } else if(nextInput->sType == VK_STRUCTURE_TYPE_IMAGE_SWAPCHAIN_CREATE_INFO_KHR) { - const VkImageSwapchainCreateInfoKHR *swapIn = (const VkImageSwapchainCreateInfoKHR *)nextInput; - VkImageSwapchainCreateInfoKHR *swapOut = (VkImageSwapchainCreateInfoKHR *)tempMem; + if(IsCaptureMode(state)) + { + const VkImageSwapchainCreateInfoKHR *swapIn = + (const VkImageSwapchainCreateInfoKHR *)nextInput; + VkImageSwapchainCreateInfoKHR *swapOut = (VkImageSwapchainCreateInfoKHR *)tempMem; - // copy and unwrap the struct - swapOut->sType = swapIn->sType; - swapOut->swapchain = Unwrap(swapIn->swapchain); + // copy and unwrap the struct + swapOut->sType = swapIn->sType; + swapOut->swapchain = Unwrap(swapIn->swapchain); - AppendModifiedChainedStruct(tempMem, swapOut, nextChainTail); + AppendModifiedChainedStruct(tempMem, swapOut, nextChainTail); + } } else if(nextInput->sType == VK_STRUCTURE_TYPE_DEDICATED_ALLOCATION_IMAGE_CREATE_INFO_NV) { CopyNextChainedStruct(tempMem, nextInput, nextChainTail); } + else if(nextInput->sType == VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_BUFFER_CREATE_INFO) + { + if(IsCaptureMode(state)) + CopyNextChainedStruct(tempMem, nextInput, nextChainTail); + } + else if(nextInput->sType == VK_STRUCTURE_TYPE_DEDICATED_ALLOCATION_BUFFER_CREATE_INFO_NV) + { + CopyNextChainedStruct(tempMem, nextInput, + nextChainTail); + } + else if(nextInput->sType == VK_STRUCTURE_TYPE_BIND_BUFFER_MEMORY_DEVICE_GROUP_INFO) + { + CopyNextChainedStruct(tempMem, nextInput, nextChainTail); + } else if(nextInput->sType == VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_SWAPCHAIN_INFO_KHR) { - const VkBindImageMemorySwapchainInfoKHR *swapIn = - (const VkBindImageMemorySwapchainInfoKHR *)nextInput; - VkBindImageMemorySwapchainInfoKHR *swapOut = (VkBindImageMemorySwapchainInfoKHR *)tempMem; + if(IsCaptureMode(state)) + { + const VkBindImageMemorySwapchainInfoKHR *swapIn = + (const VkBindImageMemorySwapchainInfoKHR *)nextInput; + VkBindImageMemorySwapchainInfoKHR *swapOut = (VkBindImageMemorySwapchainInfoKHR *)tempMem; - // copy and unwrap the struct - swapOut->sType = swapIn->sType; - swapOut->swapchain = Unwrap(swapIn->swapchain); + // copy and unwrap the struct + swapOut->sType = swapIn->sType; + swapOut->swapchain = Unwrap(swapIn->swapchain); - AppendModifiedChainedStruct(tempMem, swapOut, nextChainTail); + AppendModifiedChainedStruct(tempMem, swapOut, nextChainTail); + } } else if(nextInput->sType == VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_DEVICE_GROUP_INFO) { @@ -495,6 +639,83 @@ void PatchNextChain(const char *structName, byte *&tempMem, VkGenericStruct *inf { CopyNextChainedStruct(tempMem, nextInput, nextChainTail); } + else if(nextInput->sType == VK_STRUCTURE_TYPE_SWAPCHAIN_COUNTER_CREATE_INFO_EXT) + { + if(IsCaptureMode(state)) + CopyNextChainedStruct(tempMem, nextInput, nextChainTail); + } + else if(nextInput->sType == VK_STRUCTURE_TYPE_DEVICE_GROUP_SWAPCHAIN_CREATE_INFO_KHR) + { + CopyNextChainedStruct(tempMem, nextInput, nextChainTail); + } + else if(nextInput->sType == VK_STRUCTURE_TYPE_DEVICE_QUEUE_GLOBAL_PRIORITY_CREATE_INFO_EXT) + { + CopyNextChainedStruct(tempMem, nextInput, + nextChainTail); + } + else if(nextInput->sType == VK_STRUCTURE_TYPE_PROTECTED_SUBMIT_INFO) + { + if(IsCaptureMode(state)) + CopyNextChainedStruct(tempMem, nextInput, nextChainTail); + } + else if(nextInput->sType == VK_STRUCTURE_TYPE_DEVICE_GROUP_SUBMIT_INFO) + { + CopyNextChainedStruct(tempMem, nextInput, nextChainTail); + } + else if(nextInput->sType == VK_STRUCTURE_TYPE_WIN32_KEYED_MUTEX_ACQUIRE_RELEASE_INFO_NV || + nextInput->sType == VK_STRUCTURE_TYPE_WIN32_KEYED_MUTEX_ACQUIRE_RELEASE_INFO_KHR) + { +#if defined(VK_KHR_win32_keyed_mutex) || defined(VK_NV_win32_keyed_mutex) + if(IsCaptureMode(state)) + { + // KHR and NV structs are identical + const VkWin32KeyedMutexAcquireReleaseInfoKHR *mutexIn = + (const VkWin32KeyedMutexAcquireReleaseInfoKHR *)nextInput; + VkWin32KeyedMutexAcquireReleaseInfoKHR *mutexOut = + (VkWin32KeyedMutexAcquireReleaseInfoKHR *)tempMem; + + // append immediately so tempMem is incremented + AppendModifiedChainedStruct(tempMem, mutexOut, nextChainTail); + + // copy sType and pointers we don't need to patch + mutexOut->sType = mutexIn->sType; + mutexOut->acquireCount = mutexIn->acquireCount; + mutexOut->pAcquireKeys = mutexIn->pAcquireKeys; + mutexOut->pAcquireTimeouts = mutexIn->pAcquireTimeouts; + mutexOut->releaseCount = mutexIn->releaseCount; + mutexOut->pReleaseKeys = mutexIn->pReleaseKeys; + + // allocate unwrapped arrays + VkDeviceMemory *unwrappedAcquires = (VkDeviceMemory *)tempMem; + tempMem += sizeof(VkDeviceMemory) * mutexIn->acquireCount; + VkDeviceMemory *unwrappedReleases = (VkDeviceMemory *)tempMem; + tempMem += sizeof(VkDeviceMemory) * mutexIn->releaseCount; + + // unwrap the arrays + for(uint32_t mem = 0; mem < mutexIn->acquireCount; mem++) + unwrappedAcquires[mem] = Unwrap(mutexIn->pAcquireSyncs[mem]); + for(uint32_t mem = 0; mem < mutexIn->releaseCount; mem++) + unwrappedReleases[mem] = Unwrap(mutexIn->pReleaseSyncs[mem]); + + mutexOut->pAcquireSyncs = unwrappedAcquires; + mutexOut->pReleaseSyncs = unwrappedReleases; + } +#else + RDCERR("Support for VK_KHR_win32_keyed_mutex / VK_NV_win32_keyed_mutex not compiled in"); +#endif + } + else if(nextInput->sType == VK_STRUCTURE_TYPE_DEVICE_GROUP_BIND_SPARSE_INFO) + { + CopyNextChainedStruct(tempMem, nextInput, nextChainTail); + } + else if(nextInput->sType == VK_STRUCTURE_TYPE_DEVICE_GROUP_COMMAND_BUFFER_BEGIN_INFO) + { + CopyNextChainedStruct(tempMem, nextInput, nextChainTail); + } + else if(nextInput->sType == VK_STRUCTURE_TYPE_DEVICE_GROUP_RENDER_PASS_BEGIN_INFO) + { + CopyNextChainedStruct(tempMem, nextInput, nextChainTail); + } else { RDCERR("unrecognised struct %d in %s pNext chain", nextInput->sType, structName); diff --git a/renderdoc/driver/vulkan/vk_common.h b/renderdoc/driver/vulkan/vk_common.h index 307c7de1b..a77f4c112 100644 --- a/renderdoc/driver/vulkan/vk_common.h +++ b/renderdoc/driver/vulkan/vk_common.h @@ -235,7 +235,8 @@ enum VkFlagWithNoBits }; size_t GetNextPatchSize(const void *next); -void PatchNextChain(const char *structName, byte *&tempMem, VkGenericStruct *infoStruct); +void UnwrapNextChain(CaptureState state, const char *structName, byte *&tempMem, + VkGenericStruct *infoStruct); template const VkGenericStruct *FindNextStruct(const VkStruct *haystack, VkStructureType needle) @@ -627,6 +628,33 @@ DECLARE_REFLECTION_STRUCT(VkDebugUtilsLabelEXT); DECLARE_REFLECTION_STRUCT(VkSamplerYcbcrConversionCreateInfo); DECLARE_REFLECTION_STRUCT(VkRenderPassMultiviewCreateInfo); DECLARE_REFLECTION_STRUCT(VkDeviceQueueInfo2); +DECLARE_REFLECTION_STRUCT(VkExportMemoryAllocateInfoNV); +DECLARE_REFLECTION_STRUCT(VkExternalMemoryImageCreateInfoNV); +DECLARE_REFLECTION_STRUCT(VkExternalMemoryImageCreateInfo); +DECLARE_REFLECTION_STRUCT(VkExportMemoryAllocateInfo); +DECLARE_REFLECTION_STRUCT(VkExternalMemoryBufferCreateInfo); +DECLARE_REFLECTION_STRUCT(VkImportMemoryFdInfoKHR); +DECLARE_REFLECTION_STRUCT(VkExportSemaphoreCreateInfo); +DECLARE_REFLECTION_STRUCT(VkExportFenceCreateInfo); +DECLARE_REFLECTION_STRUCT(VkSwapchainCounterCreateInfoEXT); +DECLARE_REFLECTION_STRUCT(VkDedicatedAllocationMemoryAllocateInfoNV); +DECLARE_REFLECTION_STRUCT(VkDedicatedAllocationImageCreateInfoNV); +DECLARE_REFLECTION_STRUCT(VkDedicatedAllocationBufferCreateInfoNV); +DECLARE_REFLECTION_STRUCT(VkMemoryDedicatedAllocateInfo); +DECLARE_REFLECTION_STRUCT(VkDeviceQueueGlobalPriorityCreateInfoEXT); +DECLARE_REFLECTION_STRUCT(VkBindImagePlaneMemoryInfo); +DECLARE_REFLECTION_STRUCT(VkSamplerYcbcrConversionInfo); +DECLARE_REFLECTION_STRUCT(VkDeviceGroupSwapchainCreateInfoKHR); +DECLARE_REFLECTION_STRUCT(VkBindImageMemorySwapchainInfoKHR); +DECLARE_REFLECTION_STRUCT(VkImageSwapchainCreateInfoKHR); +DECLARE_REFLECTION_STRUCT(VkBindImageMemoryDeviceGroupInfo); +DECLARE_REFLECTION_STRUCT(VkBindBufferMemoryDeviceGroupInfo); +DECLARE_REFLECTION_STRUCT(VkDeviceGroupBindSparseInfo); +DECLARE_REFLECTION_STRUCT(VkDeviceGroupSubmitInfo); +DECLARE_REFLECTION_STRUCT(VkDeviceGroupCommandBufferBeginInfo); +DECLARE_REFLECTION_STRUCT(VkDeviceGroupRenderPassBeginInfo); +DECLARE_REFLECTION_STRUCT(VkMemoryAllocateFlagsInfo); +DECLARE_REFLECTION_STRUCT(VkProtectedSubmitInfo); DECLARE_DESERIALISE_TYPE(VkDeviceCreateInfo); DECLARE_DESERIALISE_TYPE(VkBufferCreateInfo); @@ -676,6 +704,62 @@ DECLARE_DESERIALISE_TYPE(VkDebugUtilsLabelEXT); DECLARE_DESERIALISE_TYPE(VkSamplerYcbcrConversionCreateInfo); DECLARE_DESERIALISE_TYPE(VkRenderPassMultiviewCreateInfo); DECLARE_DESERIALISE_TYPE(VkDeviceQueueInfo2); +DECLARE_DESERIALISE_TYPE(VkExportMemoryAllocateInfoNV); +DECLARE_DESERIALISE_TYPE(VkExternalMemoryImageCreateInfoNV); +DECLARE_DESERIALISE_TYPE(VkExportMemoryAllocateInfo); +DECLARE_DESERIALISE_TYPE(VkExternalMemoryBufferCreateInfo); +DECLARE_DESERIALISE_TYPE(VkImportMemoryFdInfoKHR); +DECLARE_DESERIALISE_TYPE(VkExportSemaphoreCreateInfo); +DECLARE_DESERIALISE_TYPE(VkExportFenceCreateInfo); +DECLARE_DESERIALISE_TYPE(VkSwapchainCounterCreateInfoEXT); +DECLARE_DESERIALISE_TYPE(VkDedicatedAllocationMemoryAllocateInfoNV); +DECLARE_DESERIALISE_TYPE(VkDedicatedAllocationImageCreateInfoNV); +DECLARE_DESERIALISE_TYPE(VkDedicatedAllocationBufferCreateInfoNV); +DECLARE_DESERIALISE_TYPE(VkMemoryDedicatedAllocateInfo); +DECLARE_DESERIALISE_TYPE(VkDeviceQueueGlobalPriorityCreateInfoEXT); +DECLARE_DESERIALISE_TYPE(VkBindImagePlaneMemoryInfo); +DECLARE_DESERIALISE_TYPE(VkSamplerYcbcrConversionInfo); +DECLARE_DESERIALISE_TYPE(VkDeviceGroupSwapchainCreateInfoKHR); +DECLARE_DESERIALISE_TYPE(VkBindImageMemorySwapchainInfoKHR); +DECLARE_DESERIALISE_TYPE(VkImageSwapchainCreateInfoKHR); +DECLARE_DESERIALISE_TYPE(VkBindImageMemoryDeviceGroupInfo); +DECLARE_DESERIALISE_TYPE(VkBindBufferMemoryDeviceGroupInfo); +DECLARE_DESERIALISE_TYPE(VkDeviceGroupBindSparseInfo); +DECLARE_DESERIALISE_TYPE(VkDeviceGroupSubmitInfo); +DECLARE_DESERIALISE_TYPE(VkDeviceGroupCommandBufferBeginInfo); +DECLARE_DESERIALISE_TYPE(VkDeviceGroupRenderPassBeginInfo); +DECLARE_DESERIALISE_TYPE(VkMemoryAllocateFlagsInfo); +DECLARE_DESERIALISE_TYPE(VkProtectedSubmitInfo); + +#if defined(VK_KHR_external_memory_win32) || defined(VK_NV_external_memory_win32) +DECLARE_REFLECTION_STRUCT(VkImportMemoryWin32HandleInfoNV); +DECLARE_REFLECTION_STRUCT(VkExportMemoryWin32HandleInfoNV); +DECLARE_REFLECTION_STRUCT(VkImportMemoryWin32HandleInfoKHR); + +DECLARE_DESERIALISE_TYPE(VkImportMemoryWin32HandleInfoNV); +DECLARE_DESERIALISE_TYPE(VkExportMemoryWin32HandleInfoNV); +DECLARE_DESERIALISE_TYPE(VkImportMemoryWin32HandleInfoKHR); +#endif + +#ifdef VK_KHR_external_fence_win32 +DECLARE_REFLECTION_STRUCT(VkExportFenceWin32HandleInfoKHR); + +DECLARE_DESERIALISE_TYPE(VkExportFenceWin32HandleInfoKHR); +#endif + +#ifdef VK_KHR_external_semaphore_win32 +DECLARE_REFLECTION_STRUCT(VkExportSemaphoreWin32HandleInfoKHR); + +DECLARE_DESERIALISE_TYPE(VkExportSemaphoreWin32HandleInfoKHR); +#endif + +#if defined(VK_KHR_win32_keyed_mutex) || defined(VK_NV_win32_keyed_mutex) +DECLARE_REFLECTION_STRUCT(VkWin32KeyedMutexAcquireReleaseInfoNV); +DECLARE_REFLECTION_STRUCT(VkWin32KeyedMutexAcquireReleaseInfoKHR); + +DECLARE_DESERIALISE_TYPE(VkWin32KeyedMutexAcquireReleaseInfoNV); +DECLARE_DESERIALISE_TYPE(VkWin32KeyedMutexAcquireReleaseInfoKHR); +#endif DECLARE_REFLECTION_ENUM(VkFlagWithNoBits); DECLARE_REFLECTION_ENUM(VkQueueFlagBits); @@ -750,4 +834,12 @@ DECLARE_REFLECTION_ENUM(VkChromaLocation); DECLARE_REFLECTION_ENUM(VkDeviceQueueCreateFlagBits); DECLARE_REFLECTION_ENUM(VkSubpassDescriptionFlagBits); DECLARE_REFLECTION_ENUM(VkDescriptorSetLayoutCreateFlagBits); -DECLARE_REFLECTION_ENUM(VkSwapchainCreateFlagBitsKHR); \ No newline at end of file +DECLARE_REFLECTION_ENUM(VkSwapchainCreateFlagBitsKHR); +DECLARE_REFLECTION_ENUM(VkExternalMemoryHandleTypeFlagBitsNV); +DECLARE_REFLECTION_ENUM(VkExternalMemoryHandleTypeFlagBits); +DECLARE_REFLECTION_ENUM(VkExternalSemaphoreHandleTypeFlagBits); +DECLARE_REFLECTION_ENUM(VkExternalFenceHandleTypeFlagBits); +DECLARE_REFLECTION_ENUM(VkSurfaceCounterFlagBitsEXT); +DECLARE_REFLECTION_ENUM(VkQueueGlobalPriorityEXT); +DECLARE_REFLECTION_ENUM(VkDeviceGroupPresentModeFlagBitsKHR); +DECLARE_REFLECTION_ENUM(VkMemoryAllocateFlagBits); \ No newline at end of file diff --git a/renderdoc/driver/vulkan/vk_serialise.cpp b/renderdoc/driver/vulkan/vk_serialise.cpp index 2041a5ef2..20d311e3d 100644 --- a/renderdoc/driver/vulkan/vk_serialise.cpp +++ b/renderdoc/driver/vulkan/vk_serialise.cpp @@ -119,99 +119,139 @@ void DoSerialiseViaResourceId(SerialiserType &ser, type &el) SERIALISE_VK_HANDLES(); +#if ENABLED(RDOC_WIN32) + +#define HANDLE_PNEXT_OS() \ + /* VK_NV_external_memory_win32 */ \ + PNEXT_STRUCT(VK_STRUCTURE_TYPE_IMPORT_MEMORY_WIN32_HANDLE_INFO_NV, VkImportMemoryWin32HandleInfoNV) \ + PNEXT_STRUCT(VK_STRUCTURE_TYPE_EXPORT_MEMORY_WIN32_HANDLE_INFO_NV, VkExportMemoryWin32HandleInfoNV) \ + \ + /* VK_NV_win32_keyed_mutex */ \ + PNEXT_STRUCT(VK_STRUCTURE_TYPE_WIN32_KEYED_MUTEX_ACQUIRE_RELEASE_INFO_NV, \ + VkWin32KeyedMutexAcquireReleaseInfoNV) \ + \ + /* VK_KHR_win32_keyed_mutex */ \ + PNEXT_STRUCT(VK_STRUCTURE_TYPE_WIN32_KEYED_MUTEX_ACQUIRE_RELEASE_INFO_KHR, \ + VkWin32KeyedMutexAcquireReleaseInfoKHR) \ + \ + /* VK_KHR_external_memory_win32 */ \ + PNEXT_STRUCT(VK_STRUCTURE_TYPE_IMPORT_MEMORY_WIN32_HANDLE_INFO_KHR, \ + VkImportMemoryWin32HandleInfoKHR) \ + PNEXT_STRUCT(VK_STRUCTURE_TYPE_EXPORT_MEMORY_WIN32_HANDLE_INFO_KHR, \ + VkImportMemoryWin32HandleInfoKHR) \ + \ + /* VK_KHR_external_semaphore_win32 */ \ + PNEXT_STRUCT(VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_WIN32_HANDLE_INFO_KHR, \ + VkExportSemaphoreWin32HandleInfoKHR) \ + \ + /* VK_KHR_external_fence_win32 */ \ + PNEXT_STRUCT(VK_STRUCTURE_TYPE_EXPORT_FENCE_WIN32_HANDLE_INFO_KHR, VkExportFenceWin32HandleInfoKHR) + +#else + +#define HANDLE_PNEXT_OS() + +#endif + // 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) \ - PNEXT_IGNORE(VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO) \ - PNEXT_IGNORE(VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_BUFFER_CREATE_INFO) \ - 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) \ - PNEXT_IGNORE(VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_WIN32_HANDLE_INFO_KHR) \ - \ - /* VK_KHR_external_fence / .._fd / ..._win32 */ \ - PNEXT_IGNORE(VK_STRUCTURE_TYPE_EXPORT_FENCE_CREATE_INFO) \ - PNEXT_IGNORE(VK_STRUCTURE_TYPE_EXPORT_FENCE_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) \ - \ - /* VK_EXT_global_priority */ \ - PNEXT_IGNORE(VK_STRUCTURE_TYPE_DEVICE_QUEUE_GLOBAL_PRIORITY_CREATE_INFO_EXT) \ - \ - /* for now we don't support ycbcr and force-disable the feature bit, so no-one should try */ \ - /* to pNext any of these structs anyway, but if they do, we ignore them */ \ - /* VK_KHR_sampler_ycbcr_conversion */ \ - PNEXT_IGNORE(VK_STRUCTURE_TYPE_BIND_IMAGE_PLANE_MEMORY_INFO) \ - PNEXT_IGNORE(VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_INFO) \ - \ - /* for now we don't handle true device groups and report all physdevices in separate groups. */ \ - /* So we can safely ignore these structures as redundant/unneeded. */ \ - /* VK_KHR_sampler_ycbcr_conversion */ \ - PNEXT_IGNORE(VK_STRUCTURE_TYPE_DEVICE_GROUP_SWAPCHAIN_CREATE_INFO_KHR) \ - PNEXT_IGNORE(VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_SWAPCHAIN_INFO_KHR) \ - PNEXT_IGNORE(VK_STRUCTURE_TYPE_IMAGE_SWAPCHAIN_CREATE_INFO_KHR) \ - PNEXT_IGNORE(VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_DEVICE_GROUP_INFO) \ - PNEXT_IGNORE(VK_STRUCTURE_TYPE_BIND_BUFFER_MEMORY_DEVICE_GROUP_INFO) \ - PNEXT_IGNORE(VK_STRUCTURE_TYPE_DEVICE_GROUP_BIND_SPARSE_INFO) \ - PNEXT_IGNORE(VK_STRUCTURE_TYPE_DEVICE_GROUP_SUBMIT_INFO) \ - PNEXT_IGNORE(VK_STRUCTURE_TYPE_DEVICE_GROUP_COMMAND_BUFFER_BEGIN_INFO) \ - PNEXT_IGNORE(VK_STRUCTURE_TYPE_DEVICE_GROUP_RENDER_PASS_BEGIN_INFO) \ - PNEXT_IGNORE(VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_FLAGS_INFO) \ - \ - /* Vulkan 1.1 - protected memory */ \ - PNEXT_IGNORE(VK_STRUCTURE_TYPE_PROTECTED_SUBMIT_INFO) \ - \ - /* VK_EXT_conservative_rasterization */ \ - PNEXT_STRUCT(VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_CONSERVATIVE_STATE_CREATE_INFO_EXT, \ - VkPipelineRasterizationConservativeStateCreateInfoEXT) \ - \ - /* VK_KHR_maintenance2 */ \ - PNEXT_STRUCT(VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_DOMAIN_ORIGIN_STATE_CREATE_INFO, \ - VkPipelineTessellationDomainOriginStateCreateInfo) \ - PNEXT_STRUCT(VK_STRUCTURE_TYPE_IMAGE_VIEW_USAGE_CREATE_INFO, VkImageViewUsageCreateInfo) \ - PNEXT_STRUCT(VK_STRUCTURE_TYPE_RENDER_PASS_INPUT_ATTACHMENT_ASPECT_CREATE_INFO, \ - VkRenderPassInputAttachmentAspectCreateInfo) \ - \ - /* VK_EXT_vertex_attribute_divisor */ \ - PNEXT_STRUCT(VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_DIVISOR_STATE_CREATE_INFO_EXT, \ - VkPipelineVertexInputDivisorStateCreateInfoEXT) \ - \ - /* VK_EXT_sampler_filter_minmax */ \ - PNEXT_STRUCT(VK_STRUCTURE_TYPE_SAMPLER_REDUCTION_MODE_CREATE_INFO_EXT, \ - VkSamplerReductionModeCreateInfoEXT) \ - \ - /* VK_KHR_multiview */ \ +#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. */ \ + \ + /* OS-specific extensions */ \ + HANDLE_PNEXT_OS() \ + \ + /* VK_NV_external_memory */ \ + PNEXT_STRUCT(VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO_NV, VkExportMemoryAllocateInfoNV) \ + PNEXT_STRUCT(VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO_NV, \ + VkExternalMemoryImageCreateInfoNV) \ + \ + /* VK_KHR_external_memory / ..._fd */ \ + PNEXT_STRUCT(VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO, VkExportMemoryAllocateInfo) \ + PNEXT_STRUCT(VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO, VkExternalMemoryImageCreateInfo) \ + PNEXT_STRUCT(VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_BUFFER_CREATE_INFO, \ + VkExternalMemoryBufferCreateInfo) \ + PNEXT_STRUCT(VK_STRUCTURE_TYPE_IMPORT_MEMORY_FD_INFO_KHR, VkImportMemoryFdInfoKHR) \ + \ + /* VK_KHR_external_semaphore */ \ + PNEXT_STRUCT(VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_CREATE_INFO, VkExportSemaphoreCreateInfo) \ + \ + /* VK_KHR_external_fence */ \ + PNEXT_STRUCT(VK_STRUCTURE_TYPE_EXPORT_FENCE_CREATE_INFO, VkExportFenceCreateInfo) \ + \ + /* we don't create real swapchains on replay, so we can ignore surface counters */ \ + /* VK_EXT_display_control */ \ + PNEXT_STRUCT(VK_STRUCTURE_TYPE_SWAPCHAIN_COUNTER_CREATE_INFO_EXT, VkSwapchainCounterCreateInfoEXT) \ + \ + /* 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_STRUCT(VK_STRUCTURE_TYPE_DEDICATED_ALLOCATION_MEMORY_ALLOCATE_INFO_NV, \ + VkDedicatedAllocationMemoryAllocateInfoNV) \ + PNEXT_STRUCT(VK_STRUCTURE_TYPE_DEDICATED_ALLOCATION_IMAGE_CREATE_INFO_NV, \ + VkDedicatedAllocationImageCreateInfoNV) \ + PNEXT_STRUCT(VK_STRUCTURE_TYPE_DEDICATED_ALLOCATION_BUFFER_CREATE_INFO_NV, \ + VkDedicatedAllocationBufferCreateInfoNV) \ + \ + /* VK_KHR_dedicated_allocation */ \ + PNEXT_STRUCT(VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO, VkMemoryDedicatedAllocateInfo) \ + \ + /* VK_EXT_global_priority */ \ + PNEXT_STRUCT(VK_STRUCTURE_TYPE_DEVICE_QUEUE_GLOBAL_PRIORITY_CREATE_INFO_EXT, \ + VkDeviceQueueGlobalPriorityCreateInfoEXT) \ + \ + /* for now we don't support ycbcr and force-disable the feature bit, so no-one should try */ \ + /* to pNext any of these structs anyway, but if they do, we ignore them */ \ + /* VK_KHR_sampler_ycbcr_conversion */ \ + PNEXT_STRUCT(VK_STRUCTURE_TYPE_BIND_IMAGE_PLANE_MEMORY_INFO, VkBindImagePlaneMemoryInfo) \ + PNEXT_STRUCT(VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_INFO, VkSamplerYcbcrConversionInfo) \ + \ + /* for now we don't handle true device groups and report all physdevices in separate groups. */ \ + /* So we can safely ignore these structures as redundant/unneeded. */ \ + /* VK_KHR_device_group */ \ + PNEXT_STRUCT(VK_STRUCTURE_TYPE_DEVICE_GROUP_SWAPCHAIN_CREATE_INFO_KHR, \ + VkDeviceGroupSwapchainCreateInfoKHR) \ + PNEXT_STRUCT(VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_SWAPCHAIN_INFO_KHR, \ + VkBindImageMemorySwapchainInfoKHR) \ + PNEXT_STRUCT(VK_STRUCTURE_TYPE_IMAGE_SWAPCHAIN_CREATE_INFO_KHR, VkImageSwapchainCreateInfoKHR) \ + PNEXT_STRUCT(VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_DEVICE_GROUP_INFO, \ + VkBindImageMemoryDeviceGroupInfo) \ + PNEXT_STRUCT(VK_STRUCTURE_TYPE_BIND_BUFFER_MEMORY_DEVICE_GROUP_INFO, \ + VkBindBufferMemoryDeviceGroupInfo) \ + PNEXT_STRUCT(VK_STRUCTURE_TYPE_DEVICE_GROUP_BIND_SPARSE_INFO, VkDeviceGroupBindSparseInfo) \ + PNEXT_STRUCT(VK_STRUCTURE_TYPE_DEVICE_GROUP_SUBMIT_INFO, VkDeviceGroupSubmitInfo) \ + PNEXT_STRUCT(VK_STRUCTURE_TYPE_DEVICE_GROUP_COMMAND_BUFFER_BEGIN_INFO, \ + VkDeviceGroupCommandBufferBeginInfo) \ + PNEXT_STRUCT(VK_STRUCTURE_TYPE_DEVICE_GROUP_RENDER_PASS_BEGIN_INFO, \ + VkDeviceGroupRenderPassBeginInfo) \ + PNEXT_STRUCT(VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_FLAGS_INFO, VkMemoryAllocateFlagsInfo) \ + \ + /* Vulkan 1.1 - protected memory */ \ + PNEXT_STRUCT(VK_STRUCTURE_TYPE_PROTECTED_SUBMIT_INFO, VkProtectedSubmitInfo) \ + \ + /* VK_EXT_conservative_rasterization */ \ + PNEXT_STRUCT(VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_CONSERVATIVE_STATE_CREATE_INFO_EXT, \ + VkPipelineRasterizationConservativeStateCreateInfoEXT) \ + \ + /* VK_KHR_maintenance2 */ \ + PNEXT_STRUCT(VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_DOMAIN_ORIGIN_STATE_CREATE_INFO, \ + VkPipelineTessellationDomainOriginStateCreateInfo) \ + PNEXT_STRUCT(VK_STRUCTURE_TYPE_IMAGE_VIEW_USAGE_CREATE_INFO, VkImageViewUsageCreateInfo) \ + PNEXT_STRUCT(VK_STRUCTURE_TYPE_RENDER_PASS_INPUT_ATTACHMENT_ASPECT_CREATE_INFO, \ + VkRenderPassInputAttachmentAspectCreateInfo) \ + \ + /* VK_EXT_vertex_attribute_divisor */ \ + PNEXT_STRUCT(VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_DIVISOR_STATE_CREATE_INFO_EXT, \ + VkPipelineVertexInputDivisorStateCreateInfoEXT) \ + \ + /* VK_EXT_sampler_filter_minmax */ \ + PNEXT_STRUCT(VK_STRUCTURE_TYPE_SAMPLER_REDUCTION_MODE_CREATE_INFO_EXT, \ + VkSamplerReductionModeCreateInfoEXT) \ + \ + /* VK_KHR_multiview */ \ PNEXT_STRUCT(VK_STRUCTURE_TYPE_RENDER_PASS_MULTIVIEW_CREATE_INFO, VkRenderPassMultiviewCreateInfo) template @@ -243,10 +283,6 @@ static void SerialiseNext(SerialiserType &ser, VkStructureType &sType, const voi // 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: \ @@ -278,11 +314,6 @@ static void SerialiseNext(SerialiserType &ser, VkStructureType &sType, const voi } 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, @@ -2453,6 +2484,443 @@ void Deserialise(const VkDeviceQueueInfo2 &el) DeserialiseNext(el.pNext); } +template +void DoSerialise(SerialiserType &ser, VkExportMemoryAllocateInfoNV &el) +{ + RDCASSERT(ser.IsReading() || el.sType == VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO_NV); + SerialiseNext(ser, el.sType, el.pNext); + + SERIALISE_MEMBER_TYPED(VkExternalMemoryHandleTypeFlagBitsNV, handleTypes); +} + +template <> +void Deserialise(const VkExportMemoryAllocateInfoNV &el) +{ + DeserialiseNext(el.pNext); +} + +template +void DoSerialise(SerialiserType &ser, VkExternalMemoryImageCreateInfoNV &el) +{ + RDCASSERT(ser.IsReading() || el.sType == VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO_NV); + SerialiseNext(ser, el.sType, el.pNext); + + SERIALISE_MEMBER_TYPED(VkExternalMemoryHandleTypeFlagBitsNV, handleTypes); +} + +template <> +void Deserialise(const VkExternalMemoryImageCreateInfoNV &el) +{ + DeserialiseNext(el.pNext); +} + +template +void DoSerialise(SerialiserType &ser, VkExternalMemoryImageCreateInfo &el) +{ + RDCASSERT(ser.IsReading() || el.sType == VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO); + SerialiseNext(ser, el.sType, el.pNext); + + SERIALISE_MEMBER_TYPED(VkExternalMemoryHandleTypeFlagBits, handleTypes); +} + +template <> +void Deserialise(const VkExternalMemoryImageCreateInfo &el) +{ + DeserialiseNext(el.pNext); +} + +template +void DoSerialise(SerialiserType &ser, VkExportMemoryAllocateInfo &el) +{ + RDCASSERT(ser.IsReading() || el.sType == VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO); + SerialiseNext(ser, el.sType, el.pNext); + + SERIALISE_MEMBER_TYPED(VkExternalMemoryHandleTypeFlagBits, handleTypes); +} + +template <> +void Deserialise(const VkExportMemoryAllocateInfo &el) +{ + DeserialiseNext(el.pNext); +} + +template +void DoSerialise(SerialiserType &ser, VkExternalMemoryBufferCreateInfo &el) +{ + RDCASSERT(ser.IsReading() || el.sType == VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_BUFFER_CREATE_INFO); + SerialiseNext(ser, el.sType, el.pNext); + + SERIALISE_MEMBER_TYPED(VkExternalMemoryHandleTypeFlagBits, handleTypes); +} + +template <> +void Deserialise(const VkExternalMemoryBufferCreateInfo &el) +{ + DeserialiseNext(el.pNext); +} + +template +void DoSerialise(SerialiserType &ser, VkImportMemoryFdInfoKHR &el) +{ + RDCASSERT(ser.IsReading() || el.sType == VK_STRUCTURE_TYPE_IMPORT_MEMORY_FD_INFO_KHR); + SerialiseNext(ser, el.sType, el.pNext); + + SERIALISE_MEMBER(handleType); + SERIALISE_MEMBER(fd); +} + +template <> +void Deserialise(const VkImportMemoryFdInfoKHR &el) +{ + DeserialiseNext(el.pNext); +} + +template +void DoSerialise(SerialiserType &ser, VkExportSemaphoreCreateInfo &el) +{ + RDCASSERT(ser.IsReading() || el.sType == VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_CREATE_INFO); + SerialiseNext(ser, el.sType, el.pNext); + + SERIALISE_MEMBER_TYPED(VkExternalSemaphoreHandleTypeFlagBits, handleTypes); +} + +template <> +void Deserialise(const VkExportSemaphoreCreateInfo &el) +{ + DeserialiseNext(el.pNext); +} + +template +void DoSerialise(SerialiserType &ser, VkExportFenceCreateInfo &el) +{ + RDCASSERT(ser.IsReading() || el.sType == VK_STRUCTURE_TYPE_EXPORT_FENCE_CREATE_INFO); + SerialiseNext(ser, el.sType, el.pNext); + + SERIALISE_MEMBER_TYPED(VkExternalFenceHandleTypeFlagBits, handleTypes); +} + +template <> +void Deserialise(const VkExportFenceCreateInfo &el) +{ + DeserialiseNext(el.pNext); +} + +template +void DoSerialise(SerialiserType &ser, VkSwapchainCounterCreateInfoEXT &el) +{ + RDCASSERT(ser.IsReading() || el.sType == VK_STRUCTURE_TYPE_SWAPCHAIN_COUNTER_CREATE_INFO_EXT); + SerialiseNext(ser, el.sType, el.pNext); + + SERIALISE_MEMBER_TYPED(VkSurfaceCounterFlagBitsEXT, surfaceCounters); +} + +template <> +void Deserialise(const VkSwapchainCounterCreateInfoEXT &el) +{ + DeserialiseNext(el.pNext); +} + +template +void DoSerialise(SerialiserType &ser, VkDedicatedAllocationMemoryAllocateInfoNV &el) +{ + RDCASSERT(ser.IsReading() || + el.sType == VK_STRUCTURE_TYPE_DEDICATED_ALLOCATION_MEMORY_ALLOCATE_INFO_NV); + SerialiseNext(ser, el.sType, el.pNext); + + SERIALISE_MEMBER(image); + SERIALISE_MEMBER(buffer); +} + +template <> +void Deserialise(const VkDedicatedAllocationMemoryAllocateInfoNV &el) +{ + DeserialiseNext(el.pNext); +} + +template +void DoSerialise(SerialiserType &ser, VkDedicatedAllocationImageCreateInfoNV &el) +{ + RDCASSERT(ser.IsReading() || + el.sType == VK_STRUCTURE_TYPE_DEDICATED_ALLOCATION_IMAGE_CREATE_INFO_NV); + SerialiseNext(ser, el.sType, el.pNext); + + SERIALISE_MEMBER(dedicatedAllocation); +} + +template <> +void Deserialise(const VkDedicatedAllocationImageCreateInfoNV &el) +{ + DeserialiseNext(el.pNext); +} + +template +void DoSerialise(SerialiserType &ser, VkDedicatedAllocationBufferCreateInfoNV &el) +{ + RDCASSERT(ser.IsReading() || + el.sType == VK_STRUCTURE_TYPE_DEDICATED_ALLOCATION_BUFFER_CREATE_INFO_NV); + SerialiseNext(ser, el.sType, el.pNext); + + SERIALISE_MEMBER(dedicatedAllocation); +} + +template <> +void Deserialise(const VkDedicatedAllocationBufferCreateInfoNV &el) +{ + DeserialiseNext(el.pNext); +} + +template +void DoSerialise(SerialiserType &ser, VkMemoryDedicatedAllocateInfo &el) +{ + RDCASSERT(ser.IsReading() || el.sType == VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO); + SerialiseNext(ser, el.sType, el.pNext); + + SERIALISE_MEMBER(image); + SERIALISE_MEMBER(buffer); +} + +template <> +void Deserialise(const VkMemoryDedicatedAllocateInfo &el) +{ + DeserialiseNext(el.pNext); +} + +template +void DoSerialise(SerialiserType &ser, VkDeviceQueueGlobalPriorityCreateInfoEXT &el) +{ + RDCASSERT(ser.IsReading() || + el.sType == VK_STRUCTURE_TYPE_DEVICE_QUEUE_GLOBAL_PRIORITY_CREATE_INFO_EXT); + SerialiseNext(ser, el.sType, el.pNext); + + SERIALISE_MEMBER(globalPriority); +} + +template <> +void Deserialise(const VkDeviceQueueGlobalPriorityCreateInfoEXT &el) +{ + DeserialiseNext(el.pNext); +} + +template +void DoSerialise(SerialiserType &ser, VkBindImagePlaneMemoryInfo &el) +{ + RDCASSERT(ser.IsReading() || el.sType == VK_STRUCTURE_TYPE_BIND_IMAGE_PLANE_MEMORY_INFO); + SerialiseNext(ser, el.sType, el.pNext); + + SERIALISE_MEMBER(planeAspect); +} + +template <> +void Deserialise(const VkBindImagePlaneMemoryInfo &el) +{ + DeserialiseNext(el.pNext); +} + +template +void DoSerialise(SerialiserType &ser, VkSamplerYcbcrConversionInfo &el) +{ + RDCASSERT(ser.IsReading() || el.sType == VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_INFO); + SerialiseNext(ser, el.sType, el.pNext); + + SERIALISE_MEMBER(conversion); +} + +template <> +void Deserialise(const VkSamplerYcbcrConversionInfo &el) +{ + DeserialiseNext(el.pNext); +} + +template +void DoSerialise(SerialiserType &ser, VkDeviceGroupSwapchainCreateInfoKHR &el) +{ + RDCASSERT(ser.IsReading() || el.sType == VK_STRUCTURE_TYPE_DEVICE_GROUP_SWAPCHAIN_CREATE_INFO_KHR); + SerialiseNext(ser, el.sType, el.pNext); + + SERIALISE_MEMBER_TYPED(VkDeviceGroupPresentModeFlagBitsKHR, modes); +} + +template <> +void Deserialise(const VkDeviceGroupSwapchainCreateInfoKHR &el) +{ + DeserialiseNext(el.pNext); +} + +template +void DoSerialise(SerialiserType &ser, VkBindImageMemorySwapchainInfoKHR &el) +{ + RDCASSERT(ser.IsReading() || el.sType == VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_SWAPCHAIN_INFO_KHR); + SerialiseNext(ser, el.sType, el.pNext); + + SERIALISE_MEMBER(swapchain); + SERIALISE_MEMBER(imageIndex); +} + +template <> +void Deserialise(const VkBindImageMemorySwapchainInfoKHR &el) +{ + DeserialiseNext(el.pNext); +} + +template +void DoSerialise(SerialiserType &ser, VkImageSwapchainCreateInfoKHR &el) +{ + RDCASSERT(ser.IsReading() || el.sType == VK_STRUCTURE_TYPE_IMAGE_SWAPCHAIN_CREATE_INFO_KHR); + SerialiseNext(ser, el.sType, el.pNext); + + SERIALISE_MEMBER(swapchain); +} + +template <> +void Deserialise(const VkImageSwapchainCreateInfoKHR &el) +{ + DeserialiseNext(el.pNext); +} + +template +void DoSerialise(SerialiserType &ser, VkBindImageMemoryDeviceGroupInfo &el) +{ + RDCASSERT(ser.IsReading() || el.sType == VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_DEVICE_GROUP_INFO); + SerialiseNext(ser, el.sType, el.pNext); + + SERIALISE_MEMBER(deviceIndexCount); + SERIALISE_MEMBER_ARRAY(pDeviceIndices, deviceIndexCount); + SERIALISE_MEMBER(splitInstanceBindRegionCount); + SERIALISE_MEMBER_ARRAY(pSplitInstanceBindRegions, splitInstanceBindRegionCount); +} + +template <> +void Deserialise(const VkBindImageMemoryDeviceGroupInfo &el) +{ + DeserialiseNext(el.pNext); + + delete[] el.pDeviceIndices; + delete[] el.pSplitInstanceBindRegions; +} + +template +void DoSerialise(SerialiserType &ser, VkBindBufferMemoryDeviceGroupInfo &el) +{ + RDCASSERT(ser.IsReading() || el.sType == VK_STRUCTURE_TYPE_BIND_BUFFER_MEMORY_DEVICE_GROUP_INFO); + SerialiseNext(ser, el.sType, el.pNext); + + SERIALISE_MEMBER(deviceIndexCount); + SERIALISE_MEMBER_ARRAY(pDeviceIndices, deviceIndexCount); +} + +template <> +void Deserialise(const VkBindBufferMemoryDeviceGroupInfo &el) +{ + DeserialiseNext(el.pNext); + + delete[] el.pDeviceIndices; +} + +template +void DoSerialise(SerialiserType &ser, VkDeviceGroupBindSparseInfo &el) +{ + RDCASSERT(ser.IsReading() || el.sType == VK_STRUCTURE_TYPE_DEVICE_GROUP_BIND_SPARSE_INFO); + SerialiseNext(ser, el.sType, el.pNext); + + SERIALISE_MEMBER(resourceDeviceIndex); + SERIALISE_MEMBER(memoryDeviceIndex); +} + +template <> +void Deserialise(const VkDeviceGroupBindSparseInfo &el) +{ + DeserialiseNext(el.pNext); +} + +template +void DoSerialise(SerialiserType &ser, VkDeviceGroupSubmitInfo &el) +{ + RDCASSERT(ser.IsReading() || el.sType == VK_STRUCTURE_TYPE_DEVICE_GROUP_SUBMIT_INFO); + SerialiseNext(ser, el.sType, el.pNext); + + SERIALISE_MEMBER(waitSemaphoreCount); + SERIALISE_MEMBER_ARRAY(pWaitSemaphoreDeviceIndices, waitSemaphoreCount); + SERIALISE_MEMBER(commandBufferCount); + SERIALISE_MEMBER_ARRAY(pCommandBufferDeviceMasks, commandBufferCount); + SERIALISE_MEMBER(signalSemaphoreCount); + SERIALISE_MEMBER_ARRAY(pSignalSemaphoreDeviceIndices, signalSemaphoreCount); +} + +template <> +void Deserialise(const VkDeviceGroupSubmitInfo &el) +{ + DeserialiseNext(el.pNext); + + delete[] el.pWaitSemaphoreDeviceIndices; + delete[] el.pCommandBufferDeviceMasks; + delete[] el.pSignalSemaphoreDeviceIndices; +} + +template +void DoSerialise(SerialiserType &ser, VkDeviceGroupCommandBufferBeginInfo &el) +{ + RDCASSERT(ser.IsReading() || el.sType == VK_STRUCTURE_TYPE_DEVICE_GROUP_COMMAND_BUFFER_BEGIN_INFO); + SerialiseNext(ser, el.sType, el.pNext); + + SERIALISE_MEMBER(deviceMask); +} + +template <> +void Deserialise(const VkDeviceGroupCommandBufferBeginInfo &el) +{ + DeserialiseNext(el.pNext); +} + +template +void DoSerialise(SerialiserType &ser, VkDeviceGroupRenderPassBeginInfo &el) +{ + RDCASSERT(ser.IsReading() || el.sType == VK_STRUCTURE_TYPE_DEVICE_GROUP_RENDER_PASS_BEGIN_INFO); + SerialiseNext(ser, el.sType, el.pNext); + + SERIALISE_MEMBER(deviceMask); + SERIALISE_MEMBER(deviceRenderAreaCount); + SERIALISE_MEMBER_ARRAY(pDeviceRenderAreas, deviceRenderAreaCount); +} + +template <> +void Deserialise(const VkDeviceGroupRenderPassBeginInfo &el) +{ + DeserialiseNext(el.pNext); + + delete[] el.pDeviceRenderAreas; +} + +template +void DoSerialise(SerialiserType &ser, VkMemoryAllocateFlagsInfo &el) +{ + RDCASSERT(ser.IsReading() || el.sType == VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_FLAGS_INFO); + SerialiseNext(ser, el.sType, el.pNext); + + SERIALISE_MEMBER_TYPED(VkMemoryAllocateFlagBits, flags); + SERIALISE_MEMBER(deviceMask); +} + +template <> +void Deserialise(const VkMemoryAllocateFlagsInfo &el) +{ + DeserialiseNext(el.pNext); +} + +template +void DoSerialise(SerialiserType &ser, VkProtectedSubmitInfo &el) +{ + RDCASSERT(ser.IsReading() || el.sType == VK_STRUCTURE_TYPE_PROTECTED_SUBMIT_INFO); + SerialiseNext(ser, el.sType, el.pNext); + + SERIALISE_MEMBER(protectedSubmit); +} + +template <> +void Deserialise(const VkProtectedSubmitInfo &el) +{ + DeserialiseNext(el.pNext); +} + INSTANTIATE_SERIALISE_TYPE(VkOffset2D); INSTANTIATE_SERIALISE_TYPE(VkExtent2D); INSTANTIATE_SERIALISE_TYPE(VkMemoryType); @@ -2560,7 +3028,261 @@ INSTANTIATE_SERIALISE_TYPE(VkDebugUtilsLabelEXT); INSTANTIATE_SERIALISE_TYPE(VkSamplerYcbcrConversionCreateInfo); INSTANTIATE_SERIALISE_TYPE(VkRenderPassMultiviewCreateInfo); INSTANTIATE_SERIALISE_TYPE(VkDeviceQueueInfo2); +INSTANTIATE_SERIALISE_TYPE(VkExportMemoryAllocateInfoNV); +INSTANTIATE_SERIALISE_TYPE(VkExternalMemoryImageCreateInfoNV); +INSTANTIATE_SERIALISE_TYPE(VkExportMemoryAllocateInfo); +INSTANTIATE_SERIALISE_TYPE(VkExternalMemoryBufferCreateInfo); +INSTANTIATE_SERIALISE_TYPE(VkImportMemoryFdInfoKHR); +INSTANTIATE_SERIALISE_TYPE(VkExportSemaphoreCreateInfo); +INSTANTIATE_SERIALISE_TYPE(VkExportFenceCreateInfo); +INSTANTIATE_SERIALISE_TYPE(VkSwapchainCounterCreateInfoEXT); +INSTANTIATE_SERIALISE_TYPE(VkDedicatedAllocationMemoryAllocateInfoNV); +INSTANTIATE_SERIALISE_TYPE(VkDedicatedAllocationImageCreateInfoNV); +INSTANTIATE_SERIALISE_TYPE(VkDedicatedAllocationBufferCreateInfoNV); +INSTANTIATE_SERIALISE_TYPE(VkMemoryDedicatedAllocateInfo); +INSTANTIATE_SERIALISE_TYPE(VkDeviceQueueGlobalPriorityCreateInfoEXT); +INSTANTIATE_SERIALISE_TYPE(VkBindImagePlaneMemoryInfo); +INSTANTIATE_SERIALISE_TYPE(VkSamplerYcbcrConversionInfo); +INSTANTIATE_SERIALISE_TYPE(VkDeviceGroupSwapchainCreateInfoKHR); +INSTANTIATE_SERIALISE_TYPE(VkBindImageMemorySwapchainInfoKHR); +INSTANTIATE_SERIALISE_TYPE(VkImageSwapchainCreateInfoKHR); +INSTANTIATE_SERIALISE_TYPE(VkBindImageMemoryDeviceGroupInfo); +INSTANTIATE_SERIALISE_TYPE(VkBindBufferMemoryDeviceGroupInfo); +INSTANTIATE_SERIALISE_TYPE(VkDeviceGroupBindSparseInfo); +INSTANTIATE_SERIALISE_TYPE(VkDeviceGroupSubmitInfo); +INSTANTIATE_SERIALISE_TYPE(VkDeviceGroupCommandBufferBeginInfo); +INSTANTIATE_SERIALISE_TYPE(VkDeviceGroupRenderPassBeginInfo); +INSTANTIATE_SERIALISE_TYPE(VkMemoryAllocateFlagsInfo); +INSTANTIATE_SERIALISE_TYPE(VkProtectedSubmitInfo); INSTANTIATE_SERIALISE_TYPE(DescriptorSetSlot); INSTANTIATE_SERIALISE_TYPE(ImageRegionState); -INSTANTIATE_SERIALISE_TYPE(ImageLayouts); \ No newline at end of file +INSTANTIATE_SERIALISE_TYPE(ImageLayouts); + +#if defined(VK_KHR_external_memory_win32) || defined(VK_NV_external_memory_win32) +template +void DoSerialise(SerialiserType &ser, VkImportMemoryWin32HandleInfoNV &el) +{ + RDCASSERT(ser.IsReading() || el.sType == VK_STRUCTURE_TYPE_IMPORT_MEMORY_WIN32_HANDLE_INFO_NV); + SerialiseNext(ser, el.sType, el.pNext); + + SERIALISE_MEMBER_TYPED(VkExternalMemoryHandleTypeFlagBitsNV, handleType); + + { + uint64_t handle = (uint64_t)el.handle; + ser.Serialise("handle", handle); + + // won't be valid on read, though we won't try to replay this anyway + if(ser.IsReading()) + el.handle = NULL; + } +} + +template <> +void Deserialise(const VkImportMemoryWin32HandleInfoNV &el) +{ + DeserialiseNext(el.pNext); +} + +template +void DoSerialise(SerialiserType &ser, VkExportMemoryWin32HandleInfoNV &el) +{ + RDCASSERT(ser.IsReading() || el.sType == VK_STRUCTURE_TYPE_EXPORT_MEMORY_WIN32_HANDLE_INFO_NV); + SerialiseNext(ser, el.sType, el.pNext); + + { + // serialise pointer as plain integer, rather than recursing and serialising struct + uint64_t pAttributes = (uint64_t)el.pAttributes; + ser.Serialise("pAttributes", pAttributes).TypedAs("SECURITY_ATTRIBUTES*"); + + // won't be valid on read, though we won't try to replay this anyway + if(ser.IsReading()) + el.pAttributes = NULL; + } + + SERIALISE_MEMBER_TYPED(uint32_t, dwAccess); +} + +template <> +void Deserialise(const VkExportMemoryWin32HandleInfoNV &el) +{ + DeserialiseNext(el.pNext); +} + +template +void DoSerialise(SerialiserType &ser, VkImportMemoryWin32HandleInfoKHR &el) +{ + RDCASSERT(ser.IsReading() || el.sType == VK_STRUCTURE_TYPE_EXPORT_MEMORY_WIN32_HANDLE_INFO_KHR); + SerialiseNext(ser, el.sType, el.pNext); + + SERIALISE_MEMBER(handleType); + + { + uint64_t handle = (uint64_t)el.handle; + ser.Serialise("handle", handle); + + // won't be valid on read, though we won't try to replay this anyway + if(ser.IsReading()) + el.handle = NULL; + } + + { + std::string name = StringFormat::Wide2UTF8(std::wstring(el.name)); + + ser.Serialise("name", name); + + // we don't expose UTF82Wide on all platforms, but as above this struct won't be valid anyway + if(ser.IsReading()) + el.name = L"???"; + } +} + +template <> +void Deserialise(const VkImportMemoryWin32HandleInfoKHR &el) +{ + DeserialiseNext(el.pNext); +} + +INSTANTIATE_SERIALISE_TYPE(VkImportMemoryWin32HandleInfoNV); +INSTANTIATE_SERIALISE_TYPE(VkExportMemoryWin32HandleInfoNV); +INSTANTIATE_SERIALISE_TYPE(VkImportMemoryWin32HandleInfoKHR); +#endif // #if defined(VK_KHR_external_memory_win32) || defined(VK_NV_external_memory_win32) + +#ifdef VK_KHR_external_fence_win32 +template +void DoSerialise(SerialiserType &ser, VkExportFenceWin32HandleInfoKHR &el) +{ + RDCASSERT(ser.IsReading() || el.sType == VK_STRUCTURE_TYPE_EXPORT_FENCE_WIN32_HANDLE_INFO_KHR); + SerialiseNext(ser, el.sType, el.pNext); + + { + // serialise pointer as plain integer, rather than recursing and serialising struct + uint64_t pAttributes = (uint64_t)el.pAttributes; + ser.Serialise("pAttributes", pAttributes).TypedAs("SECURITY_ATTRIBUTES*"); + + // won't be valid on read, though we won't try to replay this anyway + if(ser.IsReading()) + el.pAttributes = NULL; + } + + SERIALISE_MEMBER_TYPED(uint32_t, dwAccess); + + { + std::string name = StringFormat::Wide2UTF8(std::wstring(el.name)); + + ser.Serialise("name", name); + + // we don't expose UTF82Wide on all platforms, but as above this struct won't be valid anyway + if(ser.IsReading()) + el.name = L"???"; + } +} + +template <> +void Deserialise(const VkExportFenceWin32HandleInfoKHR &el) +{ + DeserialiseNext(el.pNext); +} + +INSTANTIATE_SERIALISE_TYPE(VkExportFenceWin32HandleInfoKHR); +#endif // #ifdef VK_KHR_external_fence_win32 + +#ifdef VK_KHR_external_semaphore_win32 +template +void DoSerialise(SerialiserType &ser, VkExportSemaphoreWin32HandleInfoKHR &el) +{ + RDCASSERT(ser.IsReading() || el.sType == VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_WIN32_HANDLE_INFO_KHR); + SerialiseNext(ser, el.sType, el.pNext); + + { + // serialise pointer as plain integer, rather than recursing and serialising struct + uint64_t pAttributes = (uint64_t)el.pAttributes; + ser.Serialise("pAttributes", pAttributes).TypedAs("SECURITY_ATTRIBUTES*"); + + // won't be valid on read, though we won't try to replay this anyway + if(ser.IsReading()) + el.pAttributes = NULL; + } + + SERIALISE_MEMBER_TYPED(uint32_t, dwAccess); + + { + std::string name = StringFormat::Wide2UTF8(std::wstring(el.name)); + + ser.Serialise("name", name); + + // we don't expose UTF82Wide on all platforms, but as above this struct won't be valid anyway + if(ser.IsReading()) + el.name = L"???"; + } +} + +template <> +void Deserialise(const VkExportSemaphoreWin32HandleInfoKHR &el) +{ + DeserialiseNext(el.pNext); +} + +INSTANTIATE_SERIALISE_TYPE(VkExportSemaphoreWin32HandleInfoKHR); +#endif // #ifdef VK_KHR_external_semaphore_win32 + +#if defined(VK_KHR_win32_keyed_mutex) || defined(VK_NV_win32_keyed_mutex) +template +void DoSerialise(SerialiserType &ser, VkWin32KeyedMutexAcquireReleaseInfoNV &el) +{ + RDCASSERT(ser.IsReading() || + el.sType == VK_STRUCTURE_TYPE_WIN32_KEYED_MUTEX_ACQUIRE_RELEASE_INFO_NV); + SerialiseNext(ser, el.sType, el.pNext); + + SERIALISE_MEMBER(acquireCount); + SERIALISE_MEMBER_ARRAY(pAcquireSyncs, acquireCount); + SERIALISE_MEMBER_ARRAY(pAcquireKeys, acquireCount); + SERIALISE_MEMBER_ARRAY(pAcquireTimeoutMilliseconds, acquireCount); + SERIALISE_MEMBER(releaseCount); + SERIALISE_MEMBER_ARRAY(pReleaseSyncs, releaseCount); + SERIALISE_MEMBER_ARRAY(pReleaseKeys, releaseCount); +} + +template <> +void Deserialise(const VkWin32KeyedMutexAcquireReleaseInfoNV &el) +{ + DeserialiseNext(el.pNext); + + delete[] el.pAcquireSyncs; + delete[] el.pAcquireKeys; + delete[] el.pAcquireTimeoutMilliseconds; + delete[] el.pReleaseSyncs; + delete[] el.pReleaseKeys; +} + +template +void DoSerialise(SerialiserType &ser, VkWin32KeyedMutexAcquireReleaseInfoKHR &el) +{ + RDCASSERT(ser.IsReading() || + el.sType == VK_STRUCTURE_TYPE_WIN32_KEYED_MUTEX_ACQUIRE_RELEASE_INFO_KHR); + SerialiseNext(ser, el.sType, el.pNext); + + SERIALISE_MEMBER(acquireCount); + SERIALISE_MEMBER_ARRAY(pAcquireSyncs, acquireCount); + SERIALISE_MEMBER_ARRAY(pAcquireKeys, acquireCount); + SERIALISE_MEMBER_ARRAY(pAcquireTimeouts, acquireCount); + SERIALISE_MEMBER(releaseCount); + SERIALISE_MEMBER_ARRAY(pReleaseSyncs, releaseCount); + SERIALISE_MEMBER_ARRAY(pReleaseKeys, releaseCount); +} + +template <> +void Deserialise(const VkWin32KeyedMutexAcquireReleaseInfoKHR &el) +{ + DeserialiseNext(el.pNext); + + delete[] el.pAcquireSyncs; + delete[] el.pAcquireKeys; + delete[] el.pAcquireTimeouts; + delete[] el.pReleaseSyncs; + delete[] el.pReleaseKeys; +} + +INSTANTIATE_SERIALISE_TYPE(VkWin32KeyedMutexAcquireReleaseInfoNV); +INSTANTIATE_SERIALISE_TYPE(VkWin32KeyedMutexAcquireReleaseInfoKHR); +#endif // #if defined(VK_KHR_win32_keyed_mutex) || defined(VK_NV_win32_keyed_mutex) \ No newline at end of file diff --git a/renderdoc/driver/vulkan/vk_stringise.cpp b/renderdoc/driver/vulkan/vk_stringise.cpp index 4f613d957..c7286f636 100644 --- a/renderdoc/driver/vulkan/vk_stringise.cpp +++ b/renderdoc/driver/vulkan/vk_stringise.cpp @@ -580,6 +580,100 @@ std::string DoStringise(const VkAccessFlagBits &el) END_BITFIELD_STRINGISE(); } +template <> +std::string DoStringise(const VkExternalMemoryHandleTypeFlagBitsNV &el) +{ + BEGIN_BITFIELD_STRINGISE(VkExternalMemoryHandleTypeFlagBitsNV); + { + STRINGISE_BITFIELD_BIT(VK_MEMORY_HEAP_DEVICE_LOCAL_BIT); + STRINGISE_BITFIELD_BIT(VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT_NV); + STRINGISE_BITFIELD_BIT(VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_IMAGE_BIT_NV); + STRINGISE_BITFIELD_BIT(VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_IMAGE_KMT_BIT_NV); + STRINGISE_BITFIELD_BIT(VK_EXTERNAL_MEMORY_HANDLE_TYPE_FLAG_BITS_MAX_ENUM_NV); + } + END_BITFIELD_STRINGISE(); +} + +template <> +std::string DoStringise(const VkExternalMemoryHandleTypeFlagBits &el) +{ + BEGIN_BITFIELD_STRINGISE(VkExternalMemoryHandleTypeFlagBits); + { + STRINGISE_BITFIELD_BIT(VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT); + STRINGISE_BITFIELD_BIT(VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT); + STRINGISE_BITFIELD_BIT(VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT); + STRINGISE_BITFIELD_BIT(VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_BIT); + STRINGISE_BITFIELD_BIT(VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_KMT_BIT); + STRINGISE_BITFIELD_BIT(VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_HEAP_BIT); + STRINGISE_BITFIELD_BIT(VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_RESOURCE_BIT); + STRINGISE_BITFIELD_BIT(VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT); + STRINGISE_BITFIELD_BIT(VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID); + STRINGISE_BITFIELD_BIT(VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT); + STRINGISE_BITFIELD_BIT(VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_MAPPED_FOREIGN_MEMORY_BIT_EXT); + } + END_BITFIELD_STRINGISE(); +} + +template <> +std::string DoStringise(const VkExternalSemaphoreHandleTypeFlagBits &el) +{ + BEGIN_BITFIELD_STRINGISE(VkExternalSemaphoreHandleTypeFlagBits); + { + STRINGISE_BITFIELD_BIT(VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT); + STRINGISE_BITFIELD_BIT(VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT); + STRINGISE_BITFIELD_BIT(VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT); + STRINGISE_BITFIELD_BIT(VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_D3D12_FENCE_BIT); + STRINGISE_BITFIELD_BIT(VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT); + } + END_BITFIELD_STRINGISE(); +} + +template <> +std::string DoStringise(const VkExternalFenceHandleTypeFlagBits &el) +{ + BEGIN_BITFIELD_STRINGISE(VkExternalFenceHandleTypeFlagBits); + { + STRINGISE_BITFIELD_BIT(VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_FD_BIT); + STRINGISE_BITFIELD_BIT(VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_BIT); + STRINGISE_BITFIELD_BIT(VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT); + STRINGISE_BITFIELD_BIT(VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT); + } + END_BITFIELD_STRINGISE(); +} + +template <> +std::string DoStringise(const VkSurfaceCounterFlagBitsEXT &el) +{ + BEGIN_BITFIELD_STRINGISE(VkSurfaceCounterFlagBitsEXT); + { + STRINGISE_BITFIELD_BIT(VK_SURFACE_COUNTER_VBLANK_EXT); + } + END_BITFIELD_STRINGISE(); +} + +template <> +std::string DoStringise(const VkDeviceGroupPresentModeFlagBitsKHR &el) +{ + BEGIN_BITFIELD_STRINGISE(VkDeviceGroupPresentModeFlagBitsKHR); + { + STRINGISE_BITFIELD_BIT(VK_DEVICE_GROUP_PRESENT_MODE_LOCAL_BIT_KHR); + STRINGISE_BITFIELD_BIT(VK_DEVICE_GROUP_PRESENT_MODE_REMOTE_BIT_KHR); + STRINGISE_BITFIELD_BIT(VK_DEVICE_GROUP_PRESENT_MODE_SUM_BIT_KHR); + STRINGISE_BITFIELD_BIT(VK_DEVICE_GROUP_PRESENT_MODE_LOCAL_MULTI_DEVICE_BIT_KHR); + } + END_BITFIELD_STRINGISE(); +} + +template <> +std::string DoStringise(const VkMemoryAllocateFlagBits &el) +{ + BEGIN_BITFIELD_STRINGISE(VkMemoryAllocateFlagBits); + { + STRINGISE_BITFIELD_BIT(VK_MEMORY_ALLOCATE_DEVICE_MASK_BIT); + } + END_BITFIELD_STRINGISE(); +} + template <> std::string DoStringise(const VkStencilFaceFlagBits &el) { @@ -1814,6 +1908,19 @@ std::string DoStringise(const VkSwapchainCreateFlagBitsKHR &el) END_ENUM_STRINGISE(); } +template <> +std::string DoStringise(const VkQueueGlobalPriorityEXT &el) +{ + BEGIN_ENUM_STRINGISE(VkQueueGlobalPriorityEXT); + { + STRINGISE_ENUM(VK_QUEUE_GLOBAL_PRIORITY_LOW_EXT) + STRINGISE_ENUM(VK_QUEUE_GLOBAL_PRIORITY_MEDIUM_EXT) + STRINGISE_ENUM(VK_QUEUE_GLOBAL_PRIORITY_HIGH_EXT) + STRINGISE_ENUM(VK_QUEUE_GLOBAL_PRIORITY_REALTIME_EXT) + } + END_ENUM_STRINGISE(); +} + template <> std::string DoStringise(const VkExtent3D &el) { diff --git a/renderdoc/driver/vulkan/wrappers/vk_cmd_funcs.cpp b/renderdoc/driver/vulkan/wrappers/vk_cmd_funcs.cpp index 53db7e85a..6acadeac9 100644 --- a/renderdoc/driver/vulkan/wrappers/vk_cmd_funcs.cpp +++ b/renderdoc/driver/vulkan/wrappers/vk_cmd_funcs.cpp @@ -626,6 +626,11 @@ bool WrappedVulkan::Serialise_vkBeginCommandBuffer(SerialiserType &ser, VkComman unwrappedBeginInfo.pInheritanceInfo = &unwrappedInheritInfo; } + byte *tempMem = GetTempMemory(GetNextPatchSize(unwrappedBeginInfo.pNext)); + + UnwrapNextChain(m_State, "VkCommandBufferBeginInfo", tempMem, + (VkGenericStruct *)&unwrappedBeginInfo); + if(IsActiveReplaying(m_State)) { const uint32_t length = m_BakedCmdBufferInfo[BakedCommandBuffer].eventCount; @@ -816,6 +821,10 @@ VkResult WrappedVulkan::vkBeginCommandBuffer(VkCommandBuffer commandBuffer, beginInfo.pInheritanceInfo = &unwrappedInfo; } + byte *tempMem = GetTempMemory(GetNextPatchSize(beginInfo.pNext)); + + UnwrapNextChain(m_State, "VkCommandBufferBeginInfo", tempMem, (VkGenericStruct *)&beginInfo); + VkResult ret; SERIALISE_TIME_CALL( ret = ObjDisp(commandBuffer)->BeginCommandBuffer(Unwrap(commandBuffer), &beginInfo)); @@ -1039,6 +1048,10 @@ bool WrappedVulkan::Serialise_vkCmdBeginRenderPass(SerialiserType &ser, VkComman unwrappedInfo.renderPass = Unwrap(unwrappedInfo.renderPass); unwrappedInfo.framebuffer = Unwrap(unwrappedInfo.framebuffer); + byte *tempMem = GetTempMemory(GetNextPatchSize(unwrappedInfo.pNext)); + + UnwrapNextChain(m_State, "VkRenderPassBeginInfo", tempMem, (VkGenericStruct *)&unwrappedInfo); + m_LastCmdBufferID = GetResourceManager()->GetOriginalID(GetResID(commandBuffer)); if(IsActiveReplaying(m_State)) @@ -1113,6 +1126,11 @@ void WrappedVulkan::vkCmdBeginRenderPass(VkCommandBuffer commandBuffer, VkRenderPassBeginInfo unwrappedInfo = *pRenderPassBegin; unwrappedInfo.renderPass = Unwrap(unwrappedInfo.renderPass); unwrappedInfo.framebuffer = Unwrap(unwrappedInfo.framebuffer); + + byte *tempMem = GetTempMemory(GetNextPatchSize(unwrappedInfo.pNext)); + + UnwrapNextChain(m_State, "VkRenderPassBeginInfo", tempMem, (VkGenericStruct *)&unwrappedInfo); + SERIALISE_TIME_CALL( ObjDisp(commandBuffer)->CmdBeginRenderPass(Unwrap(commandBuffer), &unwrappedInfo, contents)); diff --git a/renderdoc/driver/vulkan/wrappers/vk_misc_funcs.cpp b/renderdoc/driver/vulkan/wrappers/vk_misc_funcs.cpp index 25144c14d..19d5e09b4 100644 --- a/renderdoc/driver/vulkan/wrappers/vk_misc_funcs.cpp +++ b/renderdoc/driver/vulkan/wrappers/vk_misc_funcs.cpp @@ -421,7 +421,13 @@ bool WrappedVulkan::Serialise_vkCreateSampler(SerialiserType &ser, VkDevice devi { VkSampler samp = VK_NULL_HANDLE; - VkResult ret = ObjDisp(device)->CreateSampler(Unwrap(device), &CreateInfo, NULL, &samp); + VkSamplerCreateInfo patched = CreateInfo; + + byte *tempMem = GetTempMemory(GetNextPatchSize(patched.pNext)); + + UnwrapNextChain(m_State, "VkSamplerCreateInfo", tempMem, (VkGenericStruct *)&patched); + + VkResult ret = ObjDisp(device)->CreateSampler(Unwrap(device), &patched, NULL, &samp); if(ret != VK_SUCCESS) { @@ -466,7 +472,7 @@ VkResult WrappedVulkan::vkCreateSampler(VkDevice device, const VkSamplerCreateIn byte *tempMem = GetTempMemory(GetNextPatchSize(info.pNext)); - PatchNextChain("VkSamplerCreateInfo", tempMem, (VkGenericStruct *)&info); + UnwrapNextChain(m_State, "VkSamplerCreateInfo", tempMem, (VkGenericStruct *)&info); VkResult ret; SERIALISE_TIME_CALL( diff --git a/renderdoc/driver/vulkan/wrappers/vk_queue_funcs.cpp b/renderdoc/driver/vulkan/wrappers/vk_queue_funcs.cpp index 5f95650e0..67ffbea99 100644 --- a/renderdoc/driver/vulkan/wrappers/vk_queue_funcs.cpp +++ b/renderdoc/driver/vulkan/wrappers/vk_queue_funcs.cpp @@ -174,8 +174,21 @@ bool WrappedVulkan::Serialise_vkQueueSubmit(SerialiserType &ser, VkQueue queue, // don't submit the fence, since we have nothing to wait on it being signalled, and we might // not have it correctly in the unsignalled state. VkSubmitInfo unwrapped = submitInfo; - unwrapped.pCommandBuffers = - UnwrapArray(unwrapped.pCommandBuffers, unwrapped.commandBufferCount); + + size_t tempMemSize = unwrapped.commandBufferCount * sizeof(VkCommandBuffer) + + GetNextPatchSize(unwrapped.pNext); + + byte *tempMem = GetTempMemory(tempMemSize); + + VkCommandBuffer *unwrappedCmds = (VkCommandBuffer *)tempMem; + unwrapped.pCommandBuffers = unwrappedCmds; + for(uint32_t i = 0; i < unwrapped.commandBufferCount; i++) + unwrappedCmds[i] = Unwrap(submitInfo.pCommandBuffers[i]); + + tempMem += unwrapped.commandBufferCount * sizeof(VkCommandBuffer); + + UnwrapNextChain(m_State, "VkSubmitInfo", tempMem, (VkGenericStruct *)&unwrapped); + ObjDisp(queue)->QueueSubmit(Unwrap(queue), 1, &unwrapped, VK_NULL_HANDLE); AddEvent(); @@ -448,56 +461,7 @@ VkResult WrappedVulkan::vkQueueSubmit(VkQueue queue, uint32_t submitCount, tempmemSize += pSubmits[i].signalSemaphoreCount * sizeof(VkSemaphore); tempmemSize += pSubmits[i].waitSemaphoreCount * sizeof(VkSemaphore); - VkGenericStruct *next = (VkGenericStruct *)pSubmits[i].pNext; - while(next) - { - if(next->sType == VK_STRUCTURE_TYPE_MAX_ENUM) - { - RDCERR("Invalid extension structure"); - } - else if(next->sType == VK_STRUCTURE_TYPE_WIN32_KEYED_MUTEX_ACQUIRE_RELEASE_INFO_NV || - next->sType == VK_STRUCTURE_TYPE_WIN32_KEYED_MUTEX_ACQUIRE_RELEASE_INFO_KHR) - { -#ifdef VK_USE_PLATFORM_WIN32_KHR - // make sure the structures are still identical - RDCCOMPILE_ASSERT(sizeof(VkWin32KeyedMutexAcquireReleaseInfoNV) == - sizeof(VkWin32KeyedMutexAcquireReleaseInfoKHR), - "Structs are different!"); - -#define NV_DUMMY ((VkWin32KeyedMutexAcquireReleaseInfoNV *)NULL) -#define KHR_DUMMY ((VkWin32KeyedMutexAcquireReleaseInfoKHR *)NULL) - RDCCOMPILE_ASSERT(&NV_DUMMY->acquireCount == &KHR_DUMMY->acquireCount, - "Structs are different!"); - RDCCOMPILE_ASSERT(&NV_DUMMY->releaseCount == &KHR_DUMMY->releaseCount, - "Structs are different!"); - RDCCOMPILE_ASSERT(&NV_DUMMY->pAcquireSyncs == &KHR_DUMMY->pAcquireSyncs, - "Structs are different!"); - RDCCOMPILE_ASSERT(&NV_DUMMY->pReleaseSyncs == &KHR_DUMMY->pReleaseSyncs, - "Structs are different!"); -#undef NV_DUMMY -#undef KHR_DUMMY - - tempmemSize += sizeof(VkWin32KeyedMutexAcquireReleaseInfoKHR); - - VkWin32KeyedMutexAcquireReleaseInfoKHR *info = (VkWin32KeyedMutexAcquireReleaseInfoKHR *)next; - tempmemSize += info->acquireCount * sizeof(VkDeviceMemory); - tempmemSize += info->releaseCount * sizeof(VkDeviceMemory); -#else - RDCERR("Unexpected use of Win32 Keyed Mutex extension without support compiled in"); -#endif - } - else if(next->sType == VK_STRUCTURE_TYPE_D3D12_FENCE_SUBMIT_INFO_KHR) - { - // nothing to do - this is plain old data with nothing to unwrap so we can keep it in the - // pNext chain as-is - } - else - { - RDCERR("Unexpected extension structure %d", next->sType); - } - - next = (VkGenericStruct *)next->pNext; - } + tempmemSize += GetNextPatchSize(pSubmits[i].pNext); } byte *memory = GetTempMemory(tempmemSize); @@ -535,49 +499,7 @@ VkResult WrappedVulkan::vkQueueSubmit(VkQueue queue, uint32_t submitCount, for(uint32_t o = 0; o < unwrappedSubmits[i].signalSemaphoreCount; o++) unwrappedSignalSems[o] = Unwrap(pSubmits[i].pSignalSemaphores[o]); - VkGenericStruct **nextptr = (VkGenericStruct **)&unwrappedSubmits[i].pNext; - while(*nextptr) - { - VkGenericStruct *next = *nextptr; - - if(next->sType == VK_STRUCTURE_TYPE_WIN32_KEYED_MUTEX_ACQUIRE_RELEASE_INFO_NV || - next->sType == VK_STRUCTURE_TYPE_WIN32_KEYED_MUTEX_ACQUIRE_RELEASE_INFO_KHR) - { -#ifdef VK_USE_PLATFORM_WIN32_KHR - // allocate local unwrapped struct - VkWin32KeyedMutexAcquireReleaseInfoKHR *unwrappedMutexInfoKHR = - (VkWin32KeyedMutexAcquireReleaseInfoKHR *)memory; - memory += sizeof(VkWin32KeyedMutexAcquireReleaseInfoKHR); - - // copy over info from original struct - VkWin32KeyedMutexAcquireReleaseInfoKHR *wrappedMutexInfoKHR = - (VkWin32KeyedMutexAcquireReleaseInfoKHR *)next; - *unwrappedMutexInfoKHR = *wrappedMutexInfoKHR; - - // allocate unwrapped arrays - VkDeviceMemory *unwrappedAcquires = (VkDeviceMemory *)memory; - memory += sizeof(VkDeviceMemory) * unwrappedMutexInfoKHR->acquireCount; - VkDeviceMemory *unwrappedReleases = (VkDeviceMemory *)memory; - memory += sizeof(VkDeviceMemory) * unwrappedMutexInfoKHR->releaseCount; - - // unwrap the arrays - for(uint32_t mem = 0; mem < unwrappedMutexInfoKHR->acquireCount; mem++) - unwrappedAcquires[mem] = Unwrap(wrappedMutexInfoKHR->pAcquireSyncs[mem]); - for(uint32_t mem = 0; mem < unwrappedMutexInfoKHR->releaseCount; mem++) - unwrappedReleases[mem] = Unwrap(wrappedMutexInfoKHR->pReleaseSyncs[mem]); - - unwrappedMutexInfoKHR->pAcquireSyncs = unwrappedAcquires; - unwrappedMutexInfoKHR->pReleaseSyncs = unwrappedReleases; - - // insert this struct into the chain. - // nextptr is pointing to the address of the pNext, so we can overwrite it to point to our - // locally-allocated unwrapped struct - *nextptr = (VkGenericStruct *)unwrappedMutexInfoKHR; -#endif - } - - nextptr = (VkGenericStruct **)&next->pNext; - } + UnwrapNextChain(m_State, "VkSubmitInfo", memory, (VkGenericStruct *)&unwrappedSubmits[i]); } VkResult ret; @@ -911,6 +833,8 @@ VkResult WrappedVulkan::vkQueueBindSparse(VkQueue queue, uint32_t bindInfoCount, for(uint32_t i = 0; i < bindInfoCount; i++) { + tempmemSize += GetNextPatchSize(pBindInfo[i].pNext); + // within each batch, need to allocate space for each resource bind tempmemSize += pBindInfo[i].bufferBindCount * sizeof(VkSparseBufferMemoryBindInfo); tempmemSize += pBindInfo[i].imageOpaqueBindCount * sizeof(VkSparseImageOpaqueMemoryBindInfo); @@ -939,6 +863,8 @@ VkResult WrappedVulkan::vkQueueBindSparse(VkQueue queue, uint32_t bindInfoCount, RDCASSERT(pBindInfo[i].sType == VK_STRUCTURE_TYPE_BIND_SPARSE_INFO && pBindInfo[i].pNext == NULL); unwrapped[i] = pBindInfo[i]; + UnwrapNextChain(m_State, "VkBindSparseInfo", next, (VkGenericStruct *)&unwrapped[i]); + // unwrap the signal semaphores into a new array VkSemaphore *signal = (VkSemaphore *)next; next += sizeof(VkSemaphore) * unwrapped[i].signalSemaphoreCount; diff --git a/renderdoc/driver/vulkan/wrappers/vk_resource_funcs.cpp b/renderdoc/driver/vulkan/wrappers/vk_resource_funcs.cpp index fdab5743c..f1847c1f0 100644 --- a/renderdoc/driver/vulkan/wrappers/vk_resource_funcs.cpp +++ b/renderdoc/driver/vulkan/wrappers/vk_resource_funcs.cpp @@ -174,7 +174,7 @@ VkBindImageMemoryInfo *WrappedVulkan::UnwrapInfos(const VkBindImageMemoryInfo *i for(uint32_t i = 0; i < count; i++) { - PatchNextChain("VkBindImageMemoryInfo", tempMem, (VkGenericStruct *)&ret[i]); + UnwrapNextChain(m_State, "VkBindImageMemoryInfo", tempMem, (VkGenericStruct *)&ret[i]); ret[i].image = Unwrap(ret[i].image); ret[i].memory = Unwrap(ret[i].memory); } @@ -258,7 +258,13 @@ bool WrappedVulkan::Serialise_vkAllocateMemory(SerialiserType &ser, VkDevice dev // appropriate index on replay AllocateInfo.memoryTypeIndex = m_PhysicalDeviceData.memIdxMap[AllocateInfo.memoryTypeIndex]; - VkResult ret = ObjDisp(device)->AllocateMemory(Unwrap(device), &AllocateInfo, NULL, &mem); + VkMemoryAllocateInfo patched = AllocateInfo; + + byte *tempMem = GetTempMemory(GetNextPatchSize(patched.pNext)); + + UnwrapNextChain(m_State, "VkMemoryAllocateInfo", tempMem, (VkGenericStruct *)&patched); + + VkResult ret = ObjDisp(device)->AllocateMemory(Unwrap(device), &patched, NULL, &mem); if(ret != VK_SUCCESS) { @@ -375,13 +381,15 @@ VkResult WrappedVulkan::vkAllocateMemory(VkDevice device, const VkMemoryAllocate ObjDisp(device)->DestroyBuffer(Unwrap(device), buf, NULL); } - byte *tempMem = GetTempMemory(GetNextPatchSize(info.pNext)); + VkMemoryAllocateInfo unwrapped = info; - PatchNextChain("VkMemoryAllocateInfo", tempMem, (VkGenericStruct *)&info); + byte *tempMem = GetTempMemory(GetNextPatchSize(unwrapped.pNext)); + + UnwrapNextChain(m_State, "VkMemoryAllocateInfo", tempMem, (VkGenericStruct *)&unwrapped); VkResult ret; SERIALISE_TIME_CALL( - ret = ObjDisp(device)->AllocateMemory(Unwrap(device), &info, pAllocator, pMemory)); + ret = ObjDisp(device)->AllocateMemory(Unwrap(device), &unwrapped, pAllocator, pMemory)); // restore the memoryTypeIndex to the original, as that's what we want to serialise, // but maintain any potential modifications we made to info.allocationSize @@ -1001,7 +1009,13 @@ bool WrappedVulkan::Serialise_vkCreateBuffer(SerialiserType &ser, VkDevice devic // ensure we can always readback from buffers CreateInfo.usage |= VK_BUFFER_USAGE_TRANSFER_SRC_BIT; - VkResult ret = ObjDisp(device)->CreateBuffer(Unwrap(device), &CreateInfo, NULL, &buf); + VkBufferCreateInfo patched = CreateInfo; + + byte *tempMem = GetTempMemory(GetNextPatchSize(patched.pNext)); + + UnwrapNextChain(m_State, "VkBufferCreateInfo", tempMem, (VkGenericStruct *)&patched); + + VkResult ret = ObjDisp(device)->CreateBuffer(Unwrap(device), &patched, NULL, &buf); if(CreateInfo.flags & (VK_BUFFER_CREATE_SPARSE_BINDING_BIT | VK_BUFFER_CREATE_SPARSE_RESIDENCY_BIT)) @@ -1040,6 +1054,10 @@ VkResult WrappedVulkan::vkCreateBuffer(VkDevice device, const VkBufferCreateInfo // on replay, so that the memory requirements are the same adjusted_info.usage |= VK_BUFFER_USAGE_TRANSFER_SRC_BIT; + byte *tempMem = GetTempMemory(GetNextPatchSize(adjusted_info.pNext)); + + UnwrapNextChain(m_State, "VkBufferCreateInfo", tempMem, (VkGenericStruct *)&adjusted_info); + VkResult ret; SERIALISE_TIME_CALL( ret = ObjDisp(device)->CreateBuffer(Unwrap(device), &adjusted_info, pAllocator, pBuffer)); @@ -1266,7 +1284,13 @@ bool WrappedVulkan::Serialise_vkCreateImage(SerialiserType &ser, VkDevice device APIProps.SparseResources = true; } - VkResult ret = ObjDisp(device)->CreateImage(Unwrap(device), &CreateInfo, NULL, &img); + VkImageCreateInfo patched = CreateInfo; + + byte *tempMem = GetTempMemory(GetNextPatchSize(patched.pNext)); + + UnwrapNextChain(m_State, "VkImageCreateInfo", tempMem, (VkGenericStruct *)&patched); + + VkResult ret = ObjDisp(device)->CreateImage(Unwrap(device), &patched, NULL, &img); CreateInfo.usage = origusage; @@ -1382,7 +1406,7 @@ VkResult WrappedVulkan::vkCreateImage(VkDevice device, const VkImageCreateInfo * byte *tempMem = GetTempMemory(GetNextPatchSize(createInfo_adjusted.pNext)); - PatchNextChain("VkImageCreateInfo", tempMem, (VkGenericStruct *)&createInfo_adjusted); + UnwrapNextChain(m_State, "VkImageCreateInfo", tempMem, (VkGenericStruct *)&createInfo_adjusted); VkResult ret; SERIALISE_TIME_CALL( diff --git a/renderdoc/driver/vulkan/wrappers/vk_sync_funcs.cpp b/renderdoc/driver/vulkan/wrappers/vk_sync_funcs.cpp index 17859e7b1..1ea218b59 100644 --- a/renderdoc/driver/vulkan/wrappers/vk_sync_funcs.cpp +++ b/renderdoc/driver/vulkan/wrappers/vk_sync_funcs.cpp @@ -87,7 +87,13 @@ bool WrappedVulkan::Serialise_vkCreateFence(SerialiserType &ser, VkDevice device { VkFence fence = VK_NULL_HANDLE; - VkResult ret = ObjDisp(device)->CreateFence(Unwrap(device), &CreateInfo, NULL, &fence); + VkFenceCreateInfo patched = CreateInfo; + + byte *tempMem = GetTempMemory(GetNextPatchSize(patched.pNext)); + + UnwrapNextChain(m_State, "VkFenceCreateInfo", tempMem, (VkGenericStruct *)&patched); + + VkResult ret = ObjDisp(device)->CreateFence(Unwrap(device), &patched, NULL, &fence); if(ret != VK_SUCCESS) { @@ -110,9 +116,14 @@ bool WrappedVulkan::Serialise_vkCreateFence(SerialiserType &ser, VkDevice device VkResult WrappedVulkan::vkCreateFence(VkDevice device, const VkFenceCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator, VkFence *pFence) { + VkFenceCreateInfo info = *pCreateInfo; + + byte *tempMem = GetTempMemory(GetNextPatchSize(info.pNext)); + + UnwrapNextChain(m_State, "VkFenceCreateInfo", tempMem, (VkGenericStruct *)&info); + VkResult ret; - SERIALISE_TIME_CALL( - ret = ObjDisp(device)->CreateFence(Unwrap(device), pCreateInfo, pAllocator, pFence)); + SERIALISE_TIME_CALL(ret = ObjDisp(device)->CreateFence(Unwrap(device), &info, pAllocator, pFence)); if(ret == VK_SUCCESS) { @@ -484,7 +495,13 @@ bool WrappedVulkan::Serialise_vkCreateSemaphore(SerialiserType &ser, VkDevice de { VkSemaphore sem = VK_NULL_HANDLE; - VkResult ret = ObjDisp(device)->CreateSemaphore(Unwrap(device), &CreateInfo, NULL, &sem); + VkSemaphoreCreateInfo patched = CreateInfo; + + byte *tempMem = GetTempMemory(GetNextPatchSize(patched.pNext)); + + UnwrapNextChain(m_State, "VkSemaphoreCreateInfo", tempMem, (VkGenericStruct *)&patched); + + VkResult ret = ObjDisp(device)->CreateSemaphore(Unwrap(device), &patched, NULL, &sem); if(ret != VK_SUCCESS) { @@ -528,9 +545,15 @@ VkResult WrappedVulkan::vkCreateSemaphore(VkDevice device, const VkSemaphoreCrea const VkAllocationCallbacks *pAllocator, VkSemaphore *pSemaphore) { + VkSemaphoreCreateInfo info = *pCreateInfo; + + byte *tempMem = GetTempMemory(GetNextPatchSize(info.pNext)); + + UnwrapNextChain(m_State, "VkSemaphoreCreateInfo", tempMem, (VkGenericStruct *)&info); + VkResult ret; SERIALISE_TIME_CALL( - ret = ObjDisp(device)->CreateSemaphore(Unwrap(device), pCreateInfo, pAllocator, pSemaphore)); + ret = ObjDisp(device)->CreateSemaphore(Unwrap(device), &info, pAllocator, pSemaphore)); if(ret == VK_SUCCESS) {