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) {