diff --git a/renderdoc/driver/vulkan/CMakeLists.txt b/renderdoc/driver/vulkan/CMakeLists.txt
index 1932850ef..30d26840c 100644
--- a/renderdoc/driver/vulkan/CMakeLists.txt
+++ b/renderdoc/driver/vulkan/CMakeLists.txt
@@ -21,6 +21,7 @@ set(sources
vk_resources.h
vk_state.cpp
vk_state.h
+ vk_serialise.cpp
vk_stringise.cpp
vk_layer.cpp
official/vk_layer.h
@@ -79,12 +80,6 @@ elseif(UNIX)
install (FILES ${json_out} DESTINATION ${VULKAN_LAYER_FOLDER})
endif()
-# GCC 6.1 may or may not complain about enum reference casts
-if(CMAKE_COMPILER_IS_GNUCXX)
- set_source_files_properties(vk_common.cpp
- PROPERTIES COMPILE_FLAGS "-Wno-strict-aliasing")
-endif()
-
add_library(rdoc_vulkan OBJECT ${sources})
target_compile_definitions(rdoc_vulkan ${definitions})
target_include_directories(rdoc_vulkan ${RDOC_INCLUDES})
diff --git a/renderdoc/driver/vulkan/renderdoc_vulkan.vcxproj b/renderdoc/driver/vulkan/renderdoc_vulkan.vcxproj
index ba2b98c3e..532b4c7b7 100644
--- a/renderdoc/driver/vulkan/renderdoc_vulkan.vcxproj
+++ b/renderdoc/driver/vulkan/renderdoc_vulkan.vcxproj
@@ -104,6 +104,7 @@
true
+
diff --git a/renderdoc/driver/vulkan/renderdoc_vulkan.vcxproj.filters b/renderdoc/driver/vulkan/renderdoc_vulkan.vcxproj.filters
index 88c622fdc..0f3138815 100644
--- a/renderdoc/driver/vulkan/renderdoc_vulkan.vcxproj.filters
+++ b/renderdoc/driver/vulkan/renderdoc_vulkan.vcxproj.filters
@@ -100,6 +100,9 @@
Util
+
+ Util
+
diff --git a/renderdoc/driver/vulkan/vk_common.cpp b/renderdoc/driver/vulkan/vk_common.cpp
index 51b667760..f35dab37e 100644
--- a/renderdoc/driver/vulkan/vk_common.cpp
+++ b/renderdoc/driver/vulkan/vk_common.cpp
@@ -1439,1958 +1439,3 @@ StencilOp MakeStencilOp(VkStencilOp op)
return StencilOp::Keep;
}
-
-// we know the object will be a non-dispatchable object type
-#define SerialiseObjectInternal(type, name, obj, opt) \
- { \
- VulkanResourceManager *rm = (VulkanResourceManager *)GetUserData(); \
- ResourceId id; \
- if(m_Mode >= WRITING) \
- id = GetResID(obj); \
- Serialise(name, id); \
- if(m_Mode < WRITING) \
- { \
- obj = VK_NULL_HANDLE; \
- if(id != ResourceId()) \
- { \
- if(rm->HasLiveResource(id)) \
- obj = Unwrap(rm->GetLiveHandle(id)); \
- else if(!opt) \
- /* It can be OK for a resource to have no live equivalent if the */ \
- /* capture decided its not needed, which some APIs do fairly often. */ \
- RDCWARN("Capture may be missing reference to " #type " resource."); \
- } \
- } \
- }
-
-#define SerialiseObject(type, name, obj) SerialiseObjectInternal(type, name, obj, false)
-#define SerialiseObjectOptional(type, name, obj) SerialiseObjectInternal(type, name, obj, true)
-
-static void SerialiseNext(Serialiser *ser, VkStructureType &sType, const void *&pNext)
-{
- ser->Serialise("sType", sType);
-
- if(ser->IsReading())
- {
- pNext = NULL;
- }
- else
- {
- if(pNext == NULL)
- return;
-
- VkGenericStruct *next = (VkGenericStruct *)pNext;
-
- while(next)
- {
- // we can ignore this entirely, we don't need to serialise or replay it as we won't
- // actually use external memory. Unwrapping, if necessary, happens elsewhere
- if(next->sType == VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO_NV ||
- next->sType == VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO_NV ||
- next->sType == VK_STRUCTURE_TYPE_IMPORT_MEMORY_WIN32_HANDLE_INFO_NV ||
- next->sType == VK_STRUCTURE_TYPE_EXPORT_MEMORY_WIN32_HANDLE_INFO_NV ||
- next->sType == VK_STRUCTURE_TYPE_WIN32_KEYED_MUTEX_ACQUIRE_RELEASE_INFO_NV ||
-
- next->sType == VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO_KHR ||
- next->sType == VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO_KHR ||
- next->sType == VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_BUFFER_CREATE_INFO_KHR ||
- next->sType == VK_STRUCTURE_TYPE_IMPORT_MEMORY_WIN32_HANDLE_INFO_KHR ||
- next->sType == VK_STRUCTURE_TYPE_EXPORT_MEMORY_WIN32_HANDLE_INFO_KHR ||
- next->sType == VK_STRUCTURE_TYPE_IMPORT_MEMORY_FD_INFO_KHR ||
- next->sType == VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_CREATE_INFO_KHR ||
- next->sType == VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_WIN32_HANDLE_INFO_KHR)
- {
- // do nothing
- }
- // likewise we don't create real swapchains, so we can ignore surface counters
- else if(next->sType == VK_STRUCTURE_TYPE_SWAPCHAIN_COUNTER_CREATE_INFO_EXT)
- {
- // do nothing
- }
- // for now we don't serialise dedicated memory on replay as it's only a performance hint,
- // and is only required in conjunction with shared memory (which we don't replay). In future
- // it might be helpful to serialise this for informational purposes.
- else if(next->sType == VK_STRUCTURE_TYPE_DEDICATED_ALLOCATION_MEMORY_ALLOCATE_INFO_NV ||
- next->sType == VK_STRUCTURE_TYPE_DEDICATED_ALLOCATION_IMAGE_CREATE_INFO_NV ||
- next->sType == VK_STRUCTURE_TYPE_DEDICATED_ALLOCATION_BUFFER_CREATE_INFO_NV ||
- next->sType == VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO_KHR)
- {
- // do nothing
- }
- else
- {
- RDCERR("Unrecognised extension structure type %d", next->sType);
- }
-
- next = (VkGenericStruct *)next->pNext;
- }
- }
-}
-
-template
-void SerialiseOptionalObject(Serialiser *ser, const char *name, T *&el)
-{
- bool present;
-
- present = el != NULL;
- ser->Serialise((string(name) + "Present").c_str(), present);
- if(present)
- {
- if(ser->IsReading())
- el = new T;
- ser->Serialise(name, *el);
- }
- else if(ser->IsReading())
- {
- el = NULL;
- }
-}
-
-template <>
-void Serialiser::Serialise(const char *name, VkDeviceQueueCreateInfo &el)
-{
- ScopedContext scope(this, name, "VkDeviceQueueCreateInfo", 0, true);
-
- // RDCASSERT(m_Mode < WRITING || el.sType == VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO);
- if(m_Mode >= WRITING && el.sType != VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO)
- RDCWARN("sType not set properly: %u", el.sType);
- SerialiseNext(this, el.sType, el.pNext);
-
- Serialise("flags", (VkFlagWithNoBits &)el.flags);
- Serialise("queueFamilyIndex", el.queueFamilyIndex);
- Serialise("queueCount", el.queueCount);
- if(m_Mode == READING)
- el.pQueuePriorities = NULL;
- SerialisePODArray("pQueuePriorities", (float *&)el.pQueuePriorities, el.queueCount);
-}
-
-// technically this doesn't need a serialise function as it's POD,
-// but we give it one just for ease of printing etc.
-template <>
-void Serialiser::Serialise(const char *name, VkPhysicalDeviceFeatures &el)
-{
- ScopedContext scope(this, name, "VkPhysicalDeviceFeatures", 0, true);
-
- Serialise("robustBufferAccess", el.robustBufferAccess);
- Serialise("fullDrawIndexUint32", el.fullDrawIndexUint32);
- Serialise("imageCubeArray", el.imageCubeArray);
- Serialise("independentBlend", el.independentBlend);
- Serialise("geometryShader", el.geometryShader);
- Serialise("tessellationShader", el.tessellationShader);
- Serialise("sampleRateShading", el.sampleRateShading);
- Serialise("dualSrcBlend", el.dualSrcBlend);
- Serialise("logicOp", el.logicOp);
- Serialise("multiDrawIndirect", el.multiDrawIndirect);
- Serialise("drawIndirectFirstInstance", el.drawIndirectFirstInstance);
- Serialise("depthClamp", el.depthClamp);
- Serialise("depthBiasClamp", el.depthBiasClamp);
- Serialise("fillModeNonSolid", el.fillModeNonSolid);
- Serialise("depthBounds", el.depthBounds);
- Serialise("wideLines", el.wideLines);
- Serialise("largePoints", el.largePoints);
- Serialise("alphaToOne", el.alphaToOne);
- Serialise("multiViewport", el.multiViewport);
- Serialise("samplerAnisotropy", el.samplerAnisotropy);
- Serialise("textureCompressionETC2", el.textureCompressionETC2);
- Serialise("textureCompressionASTC_LDR", el.textureCompressionASTC_LDR);
- Serialise("textureCompressionBC", el.textureCompressionBC);
- Serialise("occlusionQueryPrecise", el.occlusionQueryPrecise);
- Serialise("pipelineStatisticsQuery", el.pipelineStatisticsQuery);
- Serialise("vertexPipelineStoresAndAtomics", el.vertexPipelineStoresAndAtomics);
- Serialise("fragmentStoresAndAtomics", el.fragmentStoresAndAtomics);
- Serialise("shaderTessellationAndGeometryPointSize", el.shaderTessellationAndGeometryPointSize);
- Serialise("shaderImageGatherExtended", el.shaderImageGatherExtended);
- Serialise("shaderStorageImageExtendedFormats", el.shaderStorageImageExtendedFormats);
- Serialise("shaderStorageImageMultisample", el.shaderStorageImageMultisample);
- Serialise("shaderStorageImageReadWithoutFormat", el.shaderStorageImageReadWithoutFormat);
- Serialise("shaderStorageImageWriteWithoutFormat", el.shaderStorageImageWriteWithoutFormat);
- Serialise("shaderUniformBufferArrayDynamicIndexing", el.shaderUniformBufferArrayDynamicIndexing);
- Serialise("shaderSampledImageArrayDynamicIndexing", el.shaderSampledImageArrayDynamicIndexing);
- Serialise("shaderStorageBufferArrayDynamicIndexing", el.shaderStorageBufferArrayDynamicIndexing);
- Serialise("shaderStorageImageArrayDynamicIndexing", el.shaderStorageImageArrayDynamicIndexing);
- Serialise("shaderClipDistance", el.shaderClipDistance);
- Serialise("shaderCullDistance", el.shaderCullDistance);
- Serialise("shaderFloat64", el.shaderFloat64);
- Serialise("shaderInt64", el.shaderInt64);
- Serialise("shaderInt16", el.shaderInt16);
- Serialise("shaderResourceResidency", el.shaderResourceResidency);
- Serialise("shaderResourceMinLod", el.shaderResourceMinLod);
- Serialise("sparseBinding", el.sparseBinding);
- Serialise("sparseResidencyBuffer", el.sparseResidencyBuffer);
- Serialise("sparseResidencyImage2D", el.sparseResidencyImage2D);
- Serialise("sparseResidencyImage3D", el.sparseResidencyImage3D);
- Serialise("sparseResidency2Samples", el.sparseResidency2Samples);
- Serialise("sparseResidency4Samples", el.sparseResidency4Samples);
- Serialise("sparseResidency8Samples", el.sparseResidency8Samples);
- Serialise("sparseResidency16Samples", el.sparseResidency16Samples);
- Serialise("sparseResidencyAliased", el.sparseResidencyAliased);
- Serialise("variableMultisampleRate", el.variableMultisampleRate);
- Serialise("inheritedQueries", el.inheritedQueries);
-}
-
-template <>
-void Serialiser::Serialise(const char *name, VkPhysicalDeviceMemoryProperties &el)
-{
- ScopedContext scope(this, name, "VkPhysicalDeviceMemoryProperties", 0, true);
-
- VkMemoryType *types = el.memoryTypes;
- VkMemoryHeap *heaps = el.memoryHeaps;
-
- SerialisePODArray("memoryTypes", types, el.memoryTypeCount);
- SerialisePODArray("memoryHeaps", heaps, el.memoryHeapCount);
-}
-
-template <>
-void Serialiser::Serialise(const char *name, VkPhysicalDeviceLimits &el)
-{
- ScopedContext scope(this, name, "VkPhysicalDeviceLimits", 0, true);
-
- Serialise("maxImageDimension1D", el.maxImageDimension1D);
- Serialise("maxImageDimension2D", el.maxImageDimension2D);
- Serialise("maxImageDimension3D", el.maxImageDimension3D);
- Serialise("maxImageDimensionCube", el.maxImageDimensionCube);
- Serialise("maxImageArrayLayers", el.maxImageArrayLayers);
- Serialise("maxTexelBufferElements", el.maxTexelBufferElements);
- Serialise("maxUniformBufferRange", el.maxUniformBufferRange);
- Serialise("maxStorageBufferRange", el.maxStorageBufferRange);
- Serialise("maxPushConstantsSize", el.maxPushConstantsSize);
- Serialise("maxMemoryAllocationCount", el.maxMemoryAllocationCount);
- Serialise("maxSamplerAllocationCount", el.maxSamplerAllocationCount);
- Serialise("bufferImageGranularity", el.bufferImageGranularity);
- Serialise("sparseAddressSpaceSize", el.sparseAddressSpaceSize);
- Serialise("maxBoundDescriptorSets", el.maxBoundDescriptorSets);
- Serialise("maxPerStageDescriptorSamplers", el.maxPerStageDescriptorSamplers);
- Serialise("maxPerStageDescriptorUniformBuffers", el.maxPerStageDescriptorUniformBuffers);
- Serialise("maxPerStageDescriptorStorageBuffers", el.maxPerStageDescriptorStorageBuffers);
- Serialise("maxPerStageDescriptorSampledImages", el.maxPerStageDescriptorSampledImages);
- Serialise("maxPerStageDescriptorStorageImages", el.maxPerStageDescriptorStorageImages);
- Serialise("maxPerStageDescriptorInputAttachments", el.maxPerStageDescriptorInputAttachments);
- Serialise("maxPerStageResources", el.maxPerStageResources);
- Serialise("maxDescriptorSetSamplers", el.maxDescriptorSetSamplers);
- Serialise("maxDescriptorSetUniformBuffers", el.maxDescriptorSetUniformBuffers);
- Serialise("maxDescriptorSetUniformBuffersDynamic", el.maxDescriptorSetUniformBuffersDynamic);
- Serialise("maxDescriptorSetStorageBuffers", el.maxDescriptorSetStorageBuffers);
- Serialise("maxDescriptorSetStorageBuffersDynamic", el.maxDescriptorSetStorageBuffersDynamic);
- Serialise("maxDescriptorSetSampledImages", el.maxDescriptorSetSampledImages);
- Serialise("maxDescriptorSetStorageImages", el.maxDescriptorSetStorageImages);
- Serialise("maxDescriptorSetInputAttachments", el.maxDescriptorSetInputAttachments);
- Serialise("maxVertexInputAttributes", el.maxVertexInputAttributes);
- Serialise("maxVertexInputBindings", el.maxVertexInputBindings);
- Serialise("maxVertexInputAttributeOffset", el.maxVertexInputAttributeOffset);
- Serialise("maxVertexInputBindingStride", el.maxVertexInputBindingStride);
- Serialise("maxVertexOutputComponents", el.maxVertexOutputComponents);
- Serialise("maxTessellationGenerationLevel", el.maxTessellationGenerationLevel);
- Serialise("maxTessellationPatchSize", el.maxTessellationPatchSize);
- Serialise("maxTessellationControlPerVertexInputComponents",
- el.maxTessellationControlPerVertexInputComponents);
- Serialise("maxTessellationControlPerVertexOutputComponents",
- el.maxTessellationControlPerVertexOutputComponents);
- Serialise("maxTessellationControlPerPatchOutputComponents",
- el.maxTessellationControlPerPatchOutputComponents);
- Serialise("maxTessellationControlTotalOutputComponents",
- el.maxTessellationControlTotalOutputComponents);
- Serialise("maxTessellationEvaluationInputComponents", el.maxTessellationEvaluationInputComponents);
- Serialise("maxTessellationEvaluationOutputComponents",
- el.maxTessellationEvaluationOutputComponents);
- Serialise("maxGeometryShaderInvocations", el.maxGeometryShaderInvocations);
- Serialise("maxGeometryInputComponents", el.maxGeometryInputComponents);
- Serialise("maxGeometryOutputComponents", el.maxGeometryOutputComponents);
- Serialise("maxGeometryOutputVertices", el.maxGeometryOutputVertices);
- Serialise("maxGeometryTotalOutputComponents", el.maxGeometryTotalOutputComponents);
- Serialise("maxFragmentInputComponents", el.maxFragmentInputComponents);
- Serialise("maxFragmentOutputAttachments", el.maxFragmentOutputAttachments);
- Serialise("maxFragmentDualSrcAttachments", el.maxFragmentDualSrcAttachments);
- Serialise("maxFragmentCombinedOutputResources", el.maxFragmentCombinedOutputResources);
- Serialise("maxComputeSharedMemorySize", el.maxComputeSharedMemorySize);
- SerialisePODArray<3>("maxComputeWorkGroupCount", el.maxComputeWorkGroupCount);
- Serialise("maxComputeWorkGroupInvocations", el.maxComputeWorkGroupInvocations);
- SerialisePODArray<3>("maxComputeWorkGroupSize", el.maxComputeWorkGroupSize);
- Serialise("subPixelPrecisionBits", el.subPixelPrecisionBits);
- Serialise("subTexelPrecisionBits", el.subTexelPrecisionBits);
- Serialise("mipmapPrecisionBits", el.mipmapPrecisionBits);
- Serialise("maxDrawIndexedIndexValue", el.maxDrawIndexedIndexValue);
- Serialise("maxDrawIndirectCount", el.maxDrawIndirectCount);
- Serialise("maxSamplerLodBias", el.maxSamplerLodBias);
- Serialise("maxSamplerAnisotropy", el.maxSamplerAnisotropy);
- Serialise("maxViewports", el.maxViewports);
- SerialisePODArray<2>("maxViewportDimensions", el.maxViewportDimensions);
- SerialisePODArray<2>("viewportBoundsRange", el.viewportBoundsRange);
- Serialise("viewportSubPixelBits", el.viewportSubPixelBits);
- uint64_t minMemoryMapAlignment = (uint64_t)el.minMemoryMapAlignment;
- Serialise("minMemoryMapAlignment", minMemoryMapAlignment);
- el.minMemoryMapAlignment = (size_t)minMemoryMapAlignment;
- Serialise("minTexelBufferOffsetAlignment", el.minTexelBufferOffsetAlignment);
- Serialise("minUniformBufferOffsetAlignment", el.minUniformBufferOffsetAlignment);
- Serialise("minStorageBufferOffsetAlignment", el.minStorageBufferOffsetAlignment);
- Serialise("minTexelOffset", el.minTexelOffset);
- Serialise("maxTexelOffset", el.maxTexelOffset);
- Serialise("minTexelGatherOffset", el.minTexelGatherOffset);
- Serialise("maxTexelGatherOffset", el.maxTexelGatherOffset);
- Serialise("minInterpolationOffset", el.minInterpolationOffset);
- Serialise("maxInterpolationOffset", el.maxInterpolationOffset);
- Serialise("subPixelInterpolationOffsetBits", el.subPixelInterpolationOffsetBits);
- Serialise("maxFramebufferWidth", el.maxFramebufferWidth);
- Serialise("maxFramebufferHeight", el.maxFramebufferHeight);
- Serialise("maxFramebufferLayers", el.maxFramebufferLayers);
- Serialise("framebufferColorSampleCounts", el.framebufferColorSampleCounts);
- Serialise("framebufferDepthSampleCounts", el.framebufferDepthSampleCounts);
- Serialise("framebufferStencilSampleCounts", el.framebufferStencilSampleCounts);
- Serialise("framebufferNoAttachmentsSampleCounts", el.framebufferNoAttachmentsSampleCounts);
- Serialise("maxColorAttachments", el.maxColorAttachments);
- Serialise("sampledImageColorSampleCounts", el.sampledImageColorSampleCounts);
- Serialise("sampledImageIntegerSampleCounts", el.sampledImageIntegerSampleCounts);
- Serialise("sampledImageDepthSampleCounts", el.sampledImageDepthSampleCounts);
- Serialise("sampledImageStencilSampleCounts", el.sampledImageStencilSampleCounts);
- Serialise("storageImageSampleCounts", el.storageImageSampleCounts);
- Serialise("maxSampleMaskWords", el.maxSampleMaskWords);
- Serialise("timestampComputeAndGraphics", el.timestampComputeAndGraphics);
- Serialise("timestampPeriod", el.timestampPeriod);
- Serialise("maxClipDistances", el.maxClipDistances);
- Serialise("maxCullDistances", el.maxCullDistances);
- Serialise("maxCombinedClipAndCullDistances", el.maxCombinedClipAndCullDistances);
- Serialise("discreteQueuePriorities", el.discreteQueuePriorities);
- SerialisePODArray<2>("pointSizeRange", el.pointSizeRange);
- SerialisePODArray<2>("lineWidthRange", el.lineWidthRange);
- Serialise("pointSizeGranularity", el.pointSizeGranularity);
- Serialise("lineWidthGranularity", el.lineWidthGranularity);
- Serialise("strictLines", el.strictLines);
- Serialise("standardSampleLocations", el.standardSampleLocations);
- Serialise("optimalBufferCopyOffsetAlignment", el.optimalBufferCopyOffsetAlignment);
- Serialise("optimalBufferCopyRowPitchAlignment", el.optimalBufferCopyRowPitchAlignment);
- Serialise("nonCoherentAtomSize", el.nonCoherentAtomSize);
-}
-
-template <>
-void Serialiser::Serialise(const char *name, VkPhysicalDeviceSparseProperties &el)
-{
- ScopedContext scope(this, name, "VkPhysicalDeviceSparseProperties", 0, true);
-
- Serialise("residencyStandard2DBlockShape", el.residencyStandard2DBlockShape);
- Serialise("residencyStandard2DMultisampleBlockShape", el.residencyStandard2DMultisampleBlockShape);
- Serialise("residencyStandard3DBlockShape", el.residencyStandard3DBlockShape);
- Serialise("residencyAlignedMipSize", el.residencyAlignedMipSize);
- Serialise("residencyNonResidentStrict", el.residencyNonResidentStrict);
-}
-
-template <>
-void Serialiser::Serialise(const char *name, VkPhysicalDeviceProperties &el)
-{
- ScopedContext scope(this, name, "VkPhysicalDeviceProperties", 0, true);
-
- Serialise("apiVersion", el.apiVersion);
- Serialise("driverVersion", el.driverVersion);
- Serialise("vendorID", el.vendorID);
- Serialise("deviceID", el.deviceID);
- Serialise("deviceType", el.deviceType);
-
- string deviceName;
- if(m_Mode == WRITING)
- deviceName = el.deviceName;
- Serialise("deviceName", deviceName);
- if(m_Mode == READING)
- {
- RDCEraseEl(el.deviceName);
- memcpy(el.deviceName, deviceName.c_str(),
- RDCMIN(deviceName.size(), (size_t)VK_MAX_PHYSICAL_DEVICE_NAME_SIZE));
- }
-
- SerialisePODArray("pipelineCacheUUID", el.pipelineCacheUUID);
- Serialise("limits", el.limits);
- Serialise("sparseProperties", el.sparseProperties);
-}
-
-template <>
-void Serialiser::Serialise(const char *name, VkDeviceCreateInfo &el)
-{
- ScopedContext scope(this, name, "VkDeviceCreateInfo", 0, true);
-
- RDCASSERT(m_Mode < WRITING || el.sType == VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO);
- SerialiseNext(this, el.sType, el.pNext);
-
- Serialise("flags", (VkFlagWithNoBits &)el.flags);
- SerialiseComplexArray("pQueueCreateInfos", (VkDeviceQueueCreateInfo *&)el.pQueueCreateInfos,
- el.queueCreateInfoCount);
-
- // need to do this by hand to use string DB
- Serialise("extensionCount", el.enabledExtensionCount);
-
- if(m_Mode == READING)
- el.ppEnabledExtensionNames =
- el.enabledExtensionCount ? new char *[el.enabledExtensionCount] : NULL;
-
- // cast away const on array so we can assign to it on reading
- const char **exts = (const char **)el.ppEnabledExtensionNames;
- for(uint32_t i = 0; i < el.enabledExtensionCount; i++)
- {
- string s = "";
- if(m_Mode == WRITING && exts[i] != NULL)
- s = exts[i];
-
- Serialise("ppEnabledExtensionNames", s);
-
- if(m_Mode == READING)
- {
- m_StringDB.insert(s);
- exts[i] = m_StringDB.find(s)->c_str();
- }
- }
-
- // need to do this by hand to use string DB
- Serialise("layerCount", el.enabledLayerCount);
-
- if(m_Mode == READING)
- el.ppEnabledLayerNames = el.enabledLayerCount ? new char *[el.enabledLayerCount] : NULL;
-
- // cast away const on array so we can assign to it on reading
- const char **layers = (const char **)el.ppEnabledLayerNames;
- for(uint32_t i = 0; i < el.enabledLayerCount; i++)
- {
- string s = "";
- if(m_Mode == WRITING && layers[i] != NULL)
- s = layers[i];
-
- Serialise("ppEnabledLayerNames", s);
-
- if(m_Mode == READING)
- {
- m_StringDB.insert(s);
- layers[i] = m_StringDB.find(s)->c_str();
- }
- }
-
- SerialiseOptionalObject(this, "pEnabledFeatures", (VkPhysicalDeviceFeatures *&)el.pEnabledFeatures);
-}
-
-template <>
-void Serialiser::Deserialise(const VkDeviceCreateInfo *const el) const
-{
- if(m_Mode == READING)
- {
- RDCASSERT(el->pNext == NULL); // otherwise delete
- for(uint32_t i = 0; i < el->queueCreateInfoCount; i++)
- delete[] el->pQueueCreateInfos[i].pQueuePriorities;
- delete[] el->pQueueCreateInfos;
- delete[] el->ppEnabledExtensionNames;
- delete[] el->ppEnabledLayerNames;
- delete el->pEnabledFeatures;
- }
-}
-
-template <>
-void Serialiser::Serialise(const char *name, VkBufferCreateInfo &el)
-{
- ScopedContext scope(this, name, "VkBufferCreateInfo", 0, true);
-
- RDCASSERT(m_Mode < WRITING || el.sType == VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO);
- SerialiseNext(this, el.sType, el.pNext);
-
- Serialise("flags", (VkBufferCreateFlagBits &)el.flags);
- Serialise("size", el.size);
- Serialise("usage", (VkBufferUsageFlagBits &)el.usage);
- Serialise("sharingMode", el.sharingMode);
- if(m_Mode == READING)
- {
- el.pQueueFamilyIndices = NULL;
- el.queueFamilyIndexCount = 0;
- }
- if(el.sharingMode == VK_SHARING_MODE_CONCURRENT)
- {
- SerialisePODArray("pQueueFamilyIndices", (uint32_t *&)el.pQueueFamilyIndices,
- el.queueFamilyIndexCount);
- }
- else
- {
- // for backwards compatibility with captures, ignore the family count and serialise empty array
- uint32_t zero = 0;
- uint32_t *empty = NULL;
- SerialisePODArray("pQueueFamilyIndices", empty, zero);
- delete[] empty;
- }
-}
-
-template <>
-void Serialiser::Deserialise(const VkBufferCreateInfo *const el) const
-{
- if(m_Mode == READING)
- {
- RDCASSERT(el->pNext == NULL); // otherwise delete
- delete[] el->pQueueFamilyIndices;
- }
-}
-
-template <>
-void Serialiser::Serialise(const char *name, VkBufferViewCreateInfo &el)
-{
- ScopedContext scope(this, name, "VkBufferViewCreateInfo", 0, true);
-
- RDCASSERT(m_Mode < WRITING || el.sType == VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO);
- SerialiseNext(this, el.sType, el.pNext);
-
- Serialise("flags", (VkFlagWithNoBits &)el.flags);
- SerialiseObject(VkBuffer, "buffer", el.buffer);
- Serialise("format", el.format);
- Serialise("offset", el.offset);
- Serialise("range", el.range);
-}
-
-template <>
-void Serialiser::Serialise(const char *name, VkImageCreateInfo &el)
-{
- ScopedContext scope(this, name, "VkImageCreateInfo", 0, true);
-
- RDCASSERT(m_Mode < WRITING || el.sType == VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO);
- SerialiseNext(this, el.sType, el.pNext);
-
- Serialise("flags", (VkImageCreateFlagBits &)el.flags);
- Serialise("imageType", el.imageType);
- Serialise("format", el.format);
- Serialise("extent", el.extent);
- Serialise("mipLevels", el.mipLevels);
- Serialise("arraySize", el.arrayLayers);
- Serialise("samples", el.samples);
- Serialise("tiling", el.tiling);
- Serialise("usage", (VkImageUsageFlagBits &)el.usage);
- Serialise("sharingMode", el.sharingMode);
- if(m_Mode == READING)
- {
- el.pQueueFamilyIndices = NULL;
- el.queueFamilyIndexCount = 0;
- }
- if(el.sharingMode == VK_SHARING_MODE_CONCURRENT)
- {
- SerialisePODArray("pQueueFamilyIndices", (uint32_t *&)el.pQueueFamilyIndices,
- el.queueFamilyIndexCount);
- }
- else
- {
- // for backwards compatibility with captures, ignore the family count and serialise empty array
- uint32_t zero = 0;
- uint32_t empty[1] = {0};
- SerialisePODArray("pQueueFamilyIndices", (uint32_t *&)empty, zero);
- }
- Serialise("initialLayout", el.initialLayout);
-}
-
-template <>
-void Serialiser::Deserialise(const VkImageCreateInfo *const el) const
-{
- if(m_Mode == READING)
- {
- RDCASSERT(el->pNext == NULL); // otherwise delete
- delete[] el->pQueueFamilyIndices;
- }
-}
-
-template <>
-void Serialiser::Serialise(const char *name, VkImageViewCreateInfo &el)
-{
- ScopedContext scope(this, name, "VkImageViewCreateInfo", 0, true);
-
- RDCASSERT(m_Mode < WRITING || el.sType == VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO);
- SerialiseNext(this, el.sType, el.pNext);
-
- Serialise("flags", (VkFlagWithNoBits &)el.flags);
- SerialiseObject(VkImage, "image", el.image);
- Serialise("viewType", el.viewType);
- Serialise("format", el.format);
- Serialise("components", el.components);
- Serialise("subresourceRange", el.subresourceRange);
-}
-
-template <>
-void Serialiser::Serialise(const char *name, VkSparseMemoryBind &el)
-{
- ScopedContext scope(this, name, "VkSparseMemoryBind", 0, true);
-
- Serialise("resourceOffset", el.resourceOffset);
- Serialise("size", el.size);
- SerialiseObject(VkDeviceMemory, "memory", el.memory);
- Serialise("memoryOffset", el.memoryOffset);
- Serialise("flags", (VkSparseMemoryBindFlagBits &)el.flags);
-}
-
-template <>
-void Serialiser::Serialise(const char *name, VkSparseBufferMemoryBindInfo &el)
-{
- ScopedContext scope(this, name, "VkSparseBufferMemoryBindInfo", 0, true);
-
- SerialiseObject(VkBuffer, "buffer", el.buffer);
- SerialiseComplexArray("pBinds", (VkSparseMemoryBind *&)el.pBinds, el.bindCount);
-}
-
-template <>
-void Serialiser::Serialise(const char *name, VkSparseImageOpaqueMemoryBindInfo &el)
-{
- ScopedContext scope(this, name, "VkSparseImageOpaqueMemoryBindInfo", 0, true);
-
- SerialiseObject(VkImage, "image", el.image);
- SerialiseComplexArray("pBinds", (VkSparseMemoryBind *&)el.pBinds, el.bindCount);
-}
-
-template <>
-void Serialiser::Serialise(const char *name, VkSparseImageMemoryBind &el)
-{
- ScopedContext scope(this, name, "VkSparseImageMemoryBind", 0, true);
-
- Serialise("subresource", el.subresource);
- Serialise("offset", el.offset);
- Serialise("extent", el.extent);
- SerialiseObject(VkDeviceMemory, "memory", el.memory);
- Serialise("memoryOffset", el.memoryOffset);
- Serialise("flags", (VkSparseMemoryBindFlagBits &)el.flags);
-}
-
-template <>
-void Serialiser::Serialise(const char *name, VkSparseImageMemoryBindInfo &el)
-{
- ScopedContext scope(this, name, "VkSparseImageMemoryBindInfo", 0, true);
-
- SerialiseObject(VkImage, "image", el.image);
- SerialiseComplexArray("pBinds", (VkSparseImageMemoryBind *&)el.pBinds, el.bindCount);
-}
-
-template <>
-void Serialiser::Serialise(const char *name, VkBindSparseInfo &el)
-{
- ScopedContext scope(this, name, "VkBindSparseInfo", 0, true);
-
- RDCASSERT(m_Mode < WRITING || el.sType == VK_STRUCTURE_TYPE_BIND_SPARSE_INFO);
- SerialiseNext(this, el.sType, el.pNext);
-
- // do this one by hand because it's an array of objects that aren't Serialise
- // overloaded
- Serialise("waitSemaphoreCount", el.waitSemaphoreCount);
-
- if(m_Mode == READING)
- el.pWaitSemaphores = el.waitSemaphoreCount ? new VkSemaphore[el.waitSemaphoreCount] : NULL;
-
- VkSemaphore *waitsems = (VkSemaphore *)el.pWaitSemaphores;
- for(uint32_t i = 0; i < el.waitSemaphoreCount; i++)
- SerialiseObject(VkSemaphore, "pWaitSemaphores", waitsems[i]);
-
- SerialiseComplexArray("pBufferBinds", (VkSparseBufferMemoryBindInfo *&)el.pBufferBinds,
- el.bufferBindCount);
- SerialiseComplexArray("pImageOpaqueBinds",
- (VkSparseImageOpaqueMemoryBindInfo *&)el.pImageOpaqueBinds,
- el.imageOpaqueBindCount);
- SerialiseComplexArray("pImageBinds", (VkSparseImageMemoryBindInfo *&)el.pImageBinds,
- el.imageBindCount);
-
- // do this one by hand because it's an array of objects that aren't Serialise
- // overloaded
- Serialise("signalSemaphoreCount", el.signalSemaphoreCount);
-
- if(m_Mode == READING)
- el.pSignalSemaphores = el.signalSemaphoreCount ? new VkSemaphore[el.signalSemaphoreCount] : NULL;
-
- VkSemaphore *sigsems = (VkSemaphore *)el.pSignalSemaphores;
- for(uint32_t i = 0; i < el.signalSemaphoreCount; i++)
- SerialiseObject(VkSemaphore, "pSignalSemaphores", sigsems[i]);
-}
-
-template <>
-void Serialiser::Deserialise(const VkBindSparseInfo *const el) const
-{
- if(m_Mode == READING)
- {
- RDCASSERT(el->pNext == NULL); // otherwise delete
- delete[] el->pWaitSemaphores;
- for(uint32_t i = 0; i < el->bufferBindCount; i++)
- delete[] el->pBufferBinds[i].pBinds;
- delete[] el->pBufferBinds;
- for(uint32_t i = 0; i < el->imageOpaqueBindCount; i++)
- delete[] el->pImageOpaqueBinds[i].pBinds;
- delete[] el->pImageOpaqueBinds;
- delete[] el->pImageBinds;
- delete[] el->pSignalSemaphores;
- }
-}
-
-template <>
-void Serialiser::Serialise(const char *name, VkFramebufferCreateInfo &el)
-{
- ScopedContext scope(this, name, "VkFramebufferCreateInfo", 0, true);
-
- RDCASSERT(m_Mode < WRITING || el.sType == VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO);
- SerialiseNext(this, el.sType, el.pNext);
-
- Serialise("flags", (VkFlagWithNoBits &)el.flags);
- SerialiseObject(VkRenderPass, "renderPass", el.renderPass);
- Serialise("width", el.width);
- Serialise("height", el.height);
- Serialise("layers", el.layers);
-
- // do this one by hand because it's an array of objects that aren't Serialise
- // overloaded
- Serialise("attachmentCount", el.attachmentCount);
-
- if(m_Mode == READING)
- el.pAttachments = el.attachmentCount ? new VkImageView[el.attachmentCount] : NULL;
-
- VkImageView *attaches = (VkImageView *)el.pAttachments;
- for(uint32_t i = 0; i < el.attachmentCount; i++)
- SerialiseObject(VkImageView, "pAttachments", attaches[i]);
-}
-
-template <>
-void Serialiser::Deserialise(const VkFramebufferCreateInfo *const el) const
-{
- if(m_Mode == READING)
- {
- RDCASSERT(el->pNext == NULL); // otherwise delete
- delete[] el->pAttachments;
- }
-}
-
-template <>
-void Serialiser::Serialise(const char *name, VkAttachmentDescription &el)
-{
- ScopedContext scope(this, name, "VkAttachmentDescription", 0, true);
-
- Serialise("flags", (VkAttachmentDescriptionFlagBits &)el.flags);
- Serialise("format", el.format);
- Serialise("samples", el.samples);
- Serialise("loadOp", el.loadOp);
- Serialise("storeOp", el.storeOp);
- Serialise("stencilLoadOp", el.stencilLoadOp);
- Serialise("stencilStoreOp", el.stencilStoreOp);
- Serialise("initialLayout", el.initialLayout);
- Serialise("finalLayout", el.finalLayout);
-}
-
-template <>
-void Serialiser::Serialise(const char *name, VkSubpassDescription &el)
-{
- ScopedContext scope(this, name, "VkSubpassDescription", 0, true);
-
- Serialise("flags", (VkFlagWithNoBits &)el.flags);
- Serialise("pipelineBindPoint", el.pipelineBindPoint);
- SerialiseOptionalObject(this, "pDepthStencilAttachment",
- (VkAttachmentReference *&)el.pDepthStencilAttachment);
-
- if(m_Mode == READING)
- {
- el.pInputAttachments = NULL;
- el.pColorAttachments = NULL;
- el.pResolveAttachments = NULL;
- el.pPreserveAttachments = NULL;
- }
-
- SerialisePODArray("inputAttachments", (VkAttachmentReference *&)el.pInputAttachments,
- el.inputAttachmentCount);
- SerialisePODArray("colorAttachments", (VkAttachmentReference *&)el.pColorAttachments,
- el.colorAttachmentCount);
-
- bool hasResolves = (el.pResolveAttachments != NULL);
- Serialise("hasResolves", hasResolves);
-
- if(hasResolves)
- SerialisePODArray("resolveAttachments", (VkAttachmentReference *&)el.pResolveAttachments,
- el.colorAttachmentCount);
-
- SerialisePODArray("preserveAttachments", (VkAttachmentReference *&)el.pPreserveAttachments,
- el.preserveAttachmentCount);
-}
-
-template <>
-void Serialiser::Serialise(const char *name, VkSubpassDependency &el)
-{
- ScopedContext scope(this, name, "VkSubpassDependency", 0, true);
-
- Serialise("srcSubpass", el.srcSubpass);
- Serialise("destSubpass", el.dstSubpass);
- Serialise("srcStageMask", (VkPipelineStageFlagBits &)el.srcStageMask);
- Serialise("destStageMask", (VkPipelineStageFlagBits &)el.dstStageMask);
- Serialise("srcAccessMask", (VkAccessFlagBits &)el.srcAccessMask);
- Serialise("dstAccessMask", (VkAccessFlagBits &)el.dstAccessMask);
- Serialise("dependencyFlags", (VkDependencyFlagBits &)el.dependencyFlags);
-}
-
-template <>
-void Serialiser::Serialise(const char *name, VkRenderPassCreateInfo &el)
-{
- ScopedContext scope(this, name, "VkRenderPassCreateInfo", 0, true);
-
- RDCASSERT(m_Mode < WRITING || el.sType == VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO);
- SerialiseNext(this, el.sType, el.pNext);
-
- Serialise("flags", (VkFlagWithNoBits &)el.flags);
- SerialiseComplexArray("pAttachments", (VkAttachmentDescription *&)el.pAttachments,
- el.attachmentCount);
- SerialiseComplexArray("pSubpasses", (VkSubpassDescription *&)el.pSubpasses, el.subpassCount);
- SerialiseComplexArray("pDependencies", (VkSubpassDependency *&)el.pDependencies,
- el.dependencyCount);
-}
-
-template <>
-void Serialiser::Deserialise(const VkRenderPassCreateInfo *const el) const
-{
- if(m_Mode == READING)
- {
- RDCASSERT(el->pNext == NULL); // otherwise delete
- delete[] el->pAttachments;
- for(uint32_t i = 0; i < el->subpassCount; i++)
- {
- delete el->pSubpasses[i].pDepthStencilAttachment;
- delete[] el->pSubpasses[i].pInputAttachments;
- delete[] el->pSubpasses[i].pColorAttachments;
- delete[] el->pSubpasses[i].pResolveAttachments;
- if(el->pSubpasses[i].pPreserveAttachments)
- delete[] el->pSubpasses[i].pPreserveAttachments;
- }
- delete[] el->pSubpasses;
- delete[] el->pDependencies;
- }
-}
-
-template <>
-void Serialiser::Serialise(const char *name, VkRenderPassBeginInfo &el)
-{
- ScopedContext scope(this, name, "VkRenderPassBeginInfo", 0, true);
-
- RDCASSERT(m_Mode < WRITING || el.sType == VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO);
- SerialiseNext(this, el.sType, el.pNext);
-
- SerialiseObject(VkRenderPass, "renderPass", el.renderPass);
- SerialiseObject(VkFramebuffer, "framebuffer", el.framebuffer);
- Serialise("renderArea", el.renderArea);
-
- if(m_Mode == READING)
- el.pClearValues = NULL;
- SerialisePODArray("pClearValues", (VkClearValue *&)el.pClearValues, el.clearValueCount);
-}
-
-template <>
-void Serialiser::Deserialise(const VkRenderPassBeginInfo *const el) const
-{
- if(m_Mode == READING)
- {
- RDCASSERT(el->pNext == NULL); // otherwise delete
- delete[] el->pClearValues;
- }
-}
-
-template <>
-void Serialiser::Serialise(const char *name, VkVertexInputBindingDescription &el)
-{
- ScopedContext scope(this, name, "VkVertexInputBindingDescription", 0, true);
-
- Serialise("binding", el.binding);
- Serialise("strideInBytes", el.stride);
- Serialise("inputRate", el.inputRate);
-}
-
-template <>
-void Serialiser::Serialise(const char *name, VkVertexInputAttributeDescription &el)
-{
- ScopedContext scope(this, name, "VkVertexInputAttributeDescription", 0, true);
-
- Serialise("location", el.location);
- Serialise("binding", el.binding);
- Serialise("format", el.format);
- Serialise("offset", el.offset);
-}
-
-template <>
-void Serialiser::Serialise(const char *name, VkPipelineVertexInputStateCreateInfo &el)
-{
- ScopedContext scope(this, name, "VkPipelineVertexInputStateCreateInfo", 0, true);
-
- RDCASSERT(m_Mode < WRITING ||
- el.sType == VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO);
- SerialiseNext(this, el.sType, el.pNext);
-
- Serialise("flags", (VkFlagWithNoBits &)el.flags);
- SerialiseComplexArray("pVertexBindingDescriptions",
- (VkVertexInputBindingDescription *&)el.pVertexBindingDescriptions,
- el.vertexBindingDescriptionCount);
- SerialiseComplexArray("pVertexAttributeDescriptions",
- (VkVertexInputAttributeDescription *&)el.pVertexAttributeDescriptions,
- el.vertexAttributeDescriptionCount);
-}
-
-template <>
-void Serialiser::Serialise(const char *name, VkPipelineInputAssemblyStateCreateInfo &el)
-{
- ScopedContext scope(this, name, "VkPipelineInputAssemblyStateCreateInfo", 0, true);
-
- RDCASSERT(m_Mode < WRITING ||
- el.sType == VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO);
- SerialiseNext(this, el.sType, el.pNext);
-
- Serialise("flags", (VkFlagWithNoBits &)el.flags);
- Serialise("topology", el.topology);
- Serialise("primitiveRestartEnable", el.primitiveRestartEnable);
-}
-
-template <>
-void Serialiser::Serialise(const char *name, VkPipelineTessellationStateCreateInfo &el)
-{
- ScopedContext scope(this, name, "VkPipelineTessStateCreateInfo", 0, true);
-
- RDCASSERT(m_Mode < WRITING ||
- el.sType == VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO);
- SerialiseNext(this, el.sType, el.pNext);
-
- Serialise("flags", (VkFlagWithNoBits &)el.flags);
- Serialise("patchControlPoints", el.patchControlPoints);
-}
-
-template <>
-void Serialiser::Serialise(const char *name, VkPipelineViewportStateCreateInfo &el)
-{
- ScopedContext scope(this, name, "VkPipelineViewportStateCreateInfo", 0, true);
-
- RDCASSERT(m_Mode < WRITING || el.sType == VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO);
- SerialiseNext(this, el.sType, el.pNext);
-
- Serialise("flags", (VkFlagWithNoBits &)el.flags);
-
- if(m_Mode == READING)
- {
- el.pViewports = NULL;
- el.pScissors = NULL;
- }
-
- // need to handle these arrays potentially being NULL if they're dynamic
- bool hasViews = (el.pViewports != NULL);
- bool hasScissors = (el.pScissors != NULL);
-
- Serialise("hasViews", hasViews);
- Serialise("hasScissors", hasScissors);
-
- if(hasViews)
- SerialisePODArray("viewports", (VkViewport *&)el.pViewports, el.viewportCount);
- else
- Serialise("viewportCount", el.viewportCount);
-
- if(hasScissors)
- SerialisePODArray("scissors", (VkRect2D *&)el.pScissors, el.scissorCount);
- else
- Serialise("scissorCount", el.scissorCount);
-}
-
-template <>
-void Serialiser::Serialise(const char *name, VkPipelineRasterizationStateCreateInfo &el)
-{
- ScopedContext scope(this, name, "VkPipelineRasterStateCreateInfo", 0, true);
-
- RDCASSERT(m_Mode < WRITING ||
- el.sType == VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO);
- SerialiseNext(this, el.sType, el.pNext);
-
- Serialise("flags", (VkFlagWithNoBits &)el.flags);
- Serialise("depthClampEnable", el.depthClampEnable);
- Serialise("rasterizerDiscardEnable", el.rasterizerDiscardEnable);
- Serialise("polygonMode", el.polygonMode);
- Serialise("cullMode", el.cullMode);
- Serialise("frontFace", el.frontFace);
- Serialise("depthBiasEnable", el.depthBiasEnable);
- Serialise("depthBiasConstantFactor", el.depthBiasConstantFactor);
- Serialise("depthBiasClamp", el.depthBiasClamp);
- Serialise("depthBiasSlopeFactor", el.depthBiasSlopeFactor);
- Serialise("lineWidth", el.lineWidth);
-}
-
-template <>
-void Serialiser::Serialise(const char *name, VkPipelineMultisampleStateCreateInfo &el)
-{
- ScopedContext scope(this, name, "VkPipelineMultisampleStateCreateInfo", 0, true);
-
- RDCASSERT(m_Mode < WRITING || el.sType == VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO);
- SerialiseNext(this, el.sType, el.pNext);
-
- Serialise("flags", (VkFlagWithNoBits &)el.flags);
- Serialise("rasterizationSamples", el.rasterizationSamples);
- RDCASSERT(el.rasterizationSamples <= VK_SAMPLE_COUNT_32_BIT);
- Serialise("sampleShadingEnable", el.sampleShadingEnable);
- Serialise("minSampleShading", el.minSampleShading);
- SerialiseOptionalObject(this, "sampleMask", (VkSampleMask *&)el.pSampleMask);
- Serialise("alphaToCoverageEnable", el.alphaToCoverageEnable);
- Serialise("alphaToOneEnable", el.alphaToOneEnable);
-}
-
-template <>
-void Serialiser::Serialise(const char *name, VkPipelineColorBlendAttachmentState &el)
-{
- ScopedContext scope(this, name, "VkPipelineColorBlendAttachmentState", 0, true);
-
- Serialise("blendEnable", el.blendEnable);
- Serialise("srcColorBlendFactor", el.srcColorBlendFactor);
- Serialise("dstColorBlendFactor", el.dstColorBlendFactor);
- Serialise("colorBlendOp", el.colorBlendOp);
- Serialise("srcAlphaBlendFactor", el.srcAlphaBlendFactor);
- Serialise("dstAlphaBlendFactor", el.dstAlphaBlendFactor);
- Serialise("alphaBlendOp", el.alphaBlendOp);
- Serialise("channelWriteMask", el.colorWriteMask);
-}
-
-template <>
-void Serialiser::Serialise(const char *name, VkPipelineColorBlendStateCreateInfo &el)
-{
- ScopedContext scope(this, name, "VkPipelineColorBlendStateCreateInfo", 0, true);
-
- RDCASSERT(m_Mode < WRITING || el.sType == VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO);
- SerialiseNext(this, el.sType, el.pNext);
-
- Serialise("flags", (VkFlagWithNoBits &)el.flags);
- Serialise("logicOpEnable", el.logicOpEnable);
- Serialise("logicOp", el.logicOp);
-
- Serialise("attachmentCount", el.attachmentCount);
-
- SerialiseComplexArray("pAttachments", (VkPipelineColorBlendAttachmentState *&)el.pAttachments,
- el.attachmentCount);
-
- SerialisePODArray<4>("blendConstants", el.blendConstants);
-}
-
-template <>
-void Serialiser::Serialise(const char *name, VkPipelineDepthStencilStateCreateInfo &el)
-{
- ScopedContext scope(this, name, "VkPipelineDepthStencilStateCreateInfo", 0, true);
-
- RDCASSERT(m_Mode < WRITING ||
- el.sType == VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO);
- SerialiseNext(this, el.sType, el.pNext);
-
- Serialise("flags", (VkFlagWithNoBits &)el.flags);
- Serialise("depthTestEnable", el.depthTestEnable);
- Serialise("depthWriteEnable", el.depthWriteEnable);
- Serialise("depthCompareOp", el.depthCompareOp);
- Serialise("depthBoundsTestEnable", el.depthBoundsTestEnable);
- Serialise("stencilEnable", el.stencilTestEnable);
- Serialise("front", el.front);
- Serialise("back", el.back);
- Serialise("minDepthBounds", el.minDepthBounds);
- Serialise("maxDepthBounds", el.maxDepthBounds);
-}
-
-template <>
-void Serialiser::Serialise(const char *name, VkPipelineDynamicStateCreateInfo &el)
-{
- ScopedContext scope(this, name, "VkPipelineDynamicStateCreateInfo", 0, true);
-
- RDCASSERT(m_Mode < WRITING || el.sType == VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO);
- SerialiseNext(this, el.sType, el.pNext);
-
- Serialise("flags", (VkFlagWithNoBits &)el.flags);
- if(m_Mode == READING)
- el.pDynamicStates = NULL;
- SerialisePODArray("dynamicStates", (VkDynamicState *&)el.pDynamicStates, el.dynamicStateCount);
-}
-
-template <>
-void Serialiser::Serialise(const char *name, VkCommandPoolCreateInfo &el)
-{
- ScopedContext scope(this, name, "VkCommandPoolCreateInfo", 0, true);
-
- RDCASSERT(m_Mode < WRITING || el.sType == VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO);
- SerialiseNext(this, el.sType, el.pNext);
-
- Serialise("flags", (VkCommandPoolCreateFlagBits &)el.flags);
- Serialise("queueFamilyIndex", el.queueFamilyIndex);
-}
-
-template <>
-void Serialiser::Serialise(const char *name, VkCommandBufferAllocateInfo &el)
-{
- ScopedContext scope(this, name, "VkCommandBufferAllocateInfo", 0, true);
-
- RDCASSERT(m_Mode < WRITING || el.sType == VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO);
- SerialiseNext(this, el.sType, el.pNext);
-
- SerialiseObject(VkCommandPool, "commandPool", el.commandPool);
- Serialise("level", el.level);
- Serialise("bufferCount", el.commandBufferCount);
-}
-
-template <>
-void Serialiser::Serialise(const char *name, VkCommandBufferInheritanceInfo &el)
-{
- ScopedContext scope(this, name, "VkCommandBufferInheritanceInfo", 0, true);
-
- RDCASSERT(m_Mode < WRITING || el.sType == VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO);
- SerialiseNext(this, el.sType, el.pNext);
-
- SerialiseObject(VkRenderPass, "renderPass", el.renderPass);
- Serialise("subpass", el.subpass);
- SerialiseObject(VkFramebuffer, "framebuffer", el.framebuffer);
- Serialise("occlusionQueryEnable", el.occlusionQueryEnable);
- Serialise("queryFlags", (VkQueryControlFlagBits &)el.queryFlags);
- Serialise("pipelineStatistics", (VkQueryPipelineStatisticFlagBits &)el.pipelineStatistics);
-}
-
-template <>
-void Serialiser::Serialise(const char *name, VkCommandBufferBeginInfo &el)
-{
- ScopedContext scope(this, name, "VkCommandBufferBeginInfo", 0, true);
-
- RDCASSERT(m_Mode < WRITING || el.sType == VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO);
- SerialiseNext(this, el.sType, el.pNext);
-
- Serialise("flags", (VkCommandBufferUsageFlagBits &)el.flags);
- SerialiseOptionalObject(this, "el.pInheritanceInfo",
- (VkCommandBufferInheritanceInfo *&)el.pInheritanceInfo);
-}
-
-template <>
-void Serialiser::Deserialise(const VkCommandBufferBeginInfo *const el) const
-{
- if(m_Mode == READING)
- {
- RDCASSERT(el->pNext == NULL); // otherwise delete
- delete el->pInheritanceInfo;
- }
-}
-
-template <>
-void Serialiser::Serialise(const char *name, VkStencilOpState &el)
-{
- ScopedContext scope(this, name, "VkStencilOpState", 0, true);
-
- Serialise("failOp", el.failOp);
- Serialise("passOp", el.passOp);
- Serialise("depthFailOp", el.depthFailOp);
- Serialise("compareOp", el.compareOp);
- Serialise("compareMask", el.compareMask);
- Serialise("writeMask", el.writeMask);
- Serialise("reference", el.reference);
-}
-
-template <>
-void Serialiser::Serialise(const char *name, VkQueryPoolCreateInfo &el)
-{
- ScopedContext scope(this, name, "VkQueryPoolCreateInfo", 0, true);
-
- RDCASSERT(m_Mode < WRITING || el.sType == VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO);
- SerialiseNext(this, el.sType, el.pNext);
-
- Serialise("flags", (VkFlagWithNoBits &)el.flags);
- Serialise("queryType", el.queryType);
- Serialise("queryCount", el.queryCount);
- Serialise("pipelineStatistics", (VkQueryPipelineStatisticFlagBits &)el.pipelineStatistics);
-}
-
-template <>
-void Serialiser::Serialise(const char *name, VkSemaphoreCreateInfo &el)
-{
- ScopedContext scope(this, name, "VkSemaphoreCreateInfo", 0, true);
-
- RDCASSERT(m_Mode < WRITING || el.sType == VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO);
- SerialiseNext(this, el.sType, el.pNext);
-
- Serialise("flags", (VkFlagWithNoBits &)el.flags);
-}
-
-template <>
-void Serialiser::Serialise(const char *name, VkEventCreateInfo &el)
-{
- ScopedContext scope(this, name, "VkEventCreateInfo", 0, true);
-
- RDCASSERT(m_Mode < WRITING || el.sType == VK_STRUCTURE_TYPE_EVENT_CREATE_INFO);
- SerialiseNext(this, el.sType, el.pNext);
-
- Serialise("flags", (VkFlagWithNoBits &)el.flags);
-}
-
-template <>
-void Serialiser::Serialise(const char *name, VkFenceCreateInfo &el)
-{
- ScopedContext scope(this, name, "VkFenceCreateInfo", 0, true);
-
- RDCASSERT(m_Mode < WRITING || el.sType == VK_STRUCTURE_TYPE_FENCE_CREATE_INFO);
- SerialiseNext(this, el.sType, el.pNext);
-
- Serialise("flags", (VkFenceCreateFlagBits &)el.flags);
-}
-
-template <>
-void Serialiser::Serialise(const char *name, VkSamplerCreateInfo &el)
-{
- ScopedContext scope(this, name, "VkSamplerCreateInfo", 0, true);
-
- RDCASSERT(m_Mode < WRITING || el.sType == VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO);
- SerialiseNext(this, el.sType, el.pNext);
-
- Serialise("flags", (VkFlagWithNoBits &)el.flags);
- Serialise("minFilter", el.minFilter);
- Serialise("magFilter", el.magFilter);
- Serialise("mipmapMode", el.mipmapMode);
- Serialise("addressModeU", el.addressModeU);
- Serialise("addressModeV", el.addressModeV);
- Serialise("addressModeW", el.addressModeW);
- Serialise("mipLodBias", el.mipLodBias);
- Serialise("anisotropyEnable", el.anisotropyEnable);
- Serialise("maxAnisotropy", el.maxAnisotropy);
- Serialise("compareEnable", el.compareEnable);
- Serialise("compareOp", el.compareOp);
- Serialise("minLod", el.minLod);
- Serialise("maxLod", el.maxLod);
- Serialise("borderColor", el.borderColor);
- Serialise("unnormalizedCoordinates", el.unnormalizedCoordinates);
-}
-
-template <>
-void Serialiser::Serialise(const char *name, VkPipelineShaderStageCreateInfo &el)
-{
- ScopedContext scope(this, name, "VkPipelineShaderStageCreateInfo", 0, true);
-
- RDCASSERT(m_Mode < WRITING || el.sType == VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO);
- SerialiseNext(this, el.sType, el.pNext);
-
- Serialise("flags", (VkFlagWithNoBits &)el.flags);
- Serialise("stage", el.stage);
- SerialiseObject(VkShaderModule, "module", el.module);
-
- string s = "";
- if(m_Mode >= WRITING && el.pName != NULL)
- s = el.pName;
-
- Serialise("pName", s);
-
- if(m_Mode == READING)
- {
- if(s == "")
- {
- el.pName = "";
- }
- else
- {
- string str;
- str.assign((char *)m_BufferHead - s.length(), s.length());
- m_StringDB.insert(str);
- el.pName = m_StringDB.find(str)->c_str();
- }
- }
-
- SerialiseOptionalObject(this, "el.pSpecializationInfo",
- (VkSpecializationInfo *&)el.pSpecializationInfo);
-}
-
-template <>
-void Serialiser::Serialise(const char *name, VkSpecializationMapEntry &el)
-{
- ScopedContext scope(this, name, "VkSpecializationMapEntry", 0, true);
-
- Serialise("constantId", el.constantID);
- Serialise("offset", el.offset);
- uint64_t size = el.size;
- Serialise("size", size);
- if(m_Mode == READING)
- el.size = (size_t)size;
-}
-
-template <>
-void Serialiser::Serialise(const char *name, VkSpecializationInfo &el)
-{
- ScopedContext scope(this, name, "VkSpecializationInfo", 0, true);
-
- uint64_t dataSize = el.dataSize;
- Serialise("dataSize", dataSize);
- size_t sz = (size_t)dataSize;
- if(m_Mode == READING)
- {
- el.pData = NULL;
- el.dataSize = sz;
- }
- SerialiseBuffer("pData", (byte *&)el.pData, sz);
-
- SerialiseComplexArray("pMapEntries", (VkSpecializationMapEntry *&)el.pMapEntries, el.mapEntryCount);
-}
-
-template <>
-void Serialiser::Serialise(const char *name, VkPipelineCacheCreateInfo &el)
-{
- ScopedContext scope(this, name, "VkPipelineCacheCreateInfo", 0, true);
-
- RDCASSERT(m_Mode < WRITING || el.sType == VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO);
- SerialiseNext(this, el.sType, el.pNext);
-
- Serialise("flags", (VkFlagWithNoBits &)el.flags);
-
- uint64_t initialDataSize = el.initialDataSize;
- Serialise("codeSize", initialDataSize);
- el.initialDataSize = (size_t)initialDataSize;
-
- if(m_Mode == READING)
- el.pInitialData = NULL;
- SerialiseBuffer("initialData", (byte *&)el.pInitialData, el.initialDataSize);
-}
-
-template <>
-void Serialiser::Deserialise(const VkPipelineCacheCreateInfo *const el) const
-{
- if(m_Mode == READING)
- {
- RDCASSERT(el->pNext == NULL); // otherwise delete
- delete[](byte *)(el->pInitialData);
- }
-}
-
-template <>
-void Serialiser::Serialise(const char *name, VkPipelineLayoutCreateInfo &el)
-{
- ScopedContext scope(this, name, "VkPipelineLayoutCreateInfo", 0, true);
-
- RDCASSERT(m_Mode < WRITING || el.sType == VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO);
- SerialiseNext(this, el.sType, el.pNext);
-
- Serialise("flags", (VkFlagWithNoBits &)el.flags);
-
- // need to do this one by hand since it's just an array of objects that don't themselves have
- // a Serialise overload
- Serialise("descriptorSetCount", el.setLayoutCount);
-
- if(m_Mode == READING)
- el.pSetLayouts = el.setLayoutCount ? new VkDescriptorSetLayout[el.setLayoutCount] : NULL;
-
- // cast away const on array so we can assign to it on reading
- VkDescriptorSetLayout *layouts = (VkDescriptorSetLayout *)el.pSetLayouts;
- for(uint32_t i = 0; i < el.setLayoutCount; i++)
- SerialiseObject(VkDescriptorSetLayout, "layout", layouts[i]);
-
- SerialiseComplexArray("pPushConstantRanges", (VkPushConstantRange *&)el.pPushConstantRanges,
- el.pushConstantRangeCount);
-}
-
-template <>
-void Serialiser::Deserialise(const VkPipelineLayoutCreateInfo *const el) const
-{
- if(m_Mode == READING)
- {
- RDCASSERT(el->pNext == NULL); // otherwise delete
- delete[] el->pSetLayouts;
- delete[] el->pPushConstantRanges;
- }
-}
-
-template <>
-void Serialiser::Serialise(const char *name, VkShaderModuleCreateInfo &el)
-{
- ScopedContext scope(this, name, "VkShaderModuleCreateInfo", 0, true);
-
- RDCASSERT(m_Mode < WRITING || el.sType == VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO);
- SerialiseNext(this, el.sType, el.pNext);
-
- Serialise("flags", (VkFlagWithNoBits &)el.flags);
-
- uint64_t codeSize = el.codeSize;
- Serialise("codeSize", codeSize);
- el.codeSize = (size_t)codeSize;
-
- size_t sz = (size_t)codeSize;
- if(m_Mode == READING)
- el.pCode = NULL;
- SerialiseBuffer("pCode", (byte *&)el.pCode, sz);
-}
-
-template <>
-void Serialiser::Deserialise(const VkShaderModuleCreateInfo *const el) const
-{
- if(m_Mode == READING)
- {
- RDCASSERT(el->pNext == NULL); // otherwise delete
- delete[](byte *)(el->pCode);
- }
-}
-
-template <>
-void Serialiser::Serialise(const char *name, VkImageSubresourceRange &el)
-{
- ScopedContext scope(this, name, "VkImageSubresourceRange", 0, true);
-
- Serialise("aspectMask", (VkImageAspectFlagBits &)el.aspectMask);
- Serialise("baseMipLevel", el.baseMipLevel);
- Serialise("levelCount", el.levelCount);
- Serialise("baseArrayLayer", el.baseArrayLayer);
- Serialise("layerCount", el.layerCount);
-}
-
-template <>
-void Serialiser::Serialise(const char *name, VkImageSubresourceLayers &el)
-{
- ScopedContext scope(this, name, "VkImageSubresourceLayers", 0, true);
-
- Serialise("aspectMask", (VkImageAspectFlagBits &)el.aspectMask);
- Serialise("mipLevel", el.mipLevel);
- Serialise("baseArrayLayer", el.baseArrayLayer);
- Serialise("layerCount", el.layerCount);
-}
-
-template <>
-void Serialiser::Serialise(const char *name, VkImageSubresource &el)
-{
- ScopedContext scope(this, name, "VkImageSubresource", 0, true);
-
- Serialise("aspectMask", (VkImageAspectFlagBits &)el.aspectMask);
- Serialise("mipLevel", el.mipLevel);
- Serialise("arrayLayer", el.arrayLayer);
-}
-
-template <>
-void Serialiser::Serialise(const char *name, VkMemoryAllocateInfo &el)
-{
- ScopedContext scope(this, name, "VkMemoryAllocateInfo", 0, true);
-
- RDCASSERT(m_Mode < WRITING || el.sType == VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO);
- SerialiseNext(this, el.sType, el.pNext);
-
- Serialise("allocationSize", el.allocationSize);
- Serialise("memoryTypeIndex", el.memoryTypeIndex);
-}
-
-template <>
-void Serialiser::Serialise(const char *name, VkMemoryBarrier &el)
-{
- ScopedContext scope(this, name, "VkMemoryBarrier", 0, true);
-
- RDCASSERT(m_Mode < WRITING || el.sType == VK_STRUCTURE_TYPE_MEMORY_BARRIER);
- SerialiseNext(this, el.sType, el.pNext);
-
- Serialise("srcAccessMask", (VkAccessFlagBits &)el.srcAccessMask);
- Serialise("dstAccessMask", (VkAccessFlagBits &)el.dstAccessMask);
-}
-
-template <>
-void Serialiser::Serialise(const char *name, VkBufferMemoryBarrier &el)
-{
- ScopedContext scope(this, name, "VkBufferMemoryBarrier", 0, true);
-
- RDCASSERT(m_Mode < WRITING || el.sType == VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER);
- SerialiseNext(this, el.sType, el.pNext);
-
- Serialise("srcAccessMask", (VkAccessFlagBits &)el.srcAccessMask);
- Serialise("dstAccessMask", (VkAccessFlagBits &)el.dstAccessMask);
- // serialise as signed because then QUEUE_FAMILY_IGNORED is -1 and queue
- // family index won't be legitimately larger than 2 billion
- Serialise("srcQueueFamilyIndex", (int32_t &)el.srcQueueFamilyIndex);
- Serialise("dstQueueFamilyIndex", (int32_t &)el.dstQueueFamilyIndex);
- SerialiseObject(VkBuffer, "buffer", el.buffer);
- Serialise("offset", el.offset);
- Serialise("size", el.size);
-}
-
-template <>
-void Serialiser::Serialise(const char *name, VkImageMemoryBarrier &el)
-{
- ScopedContext scope(this, name, "VkImageMemoryBarrier", 0, true);
-
- RDCASSERT(m_Mode < WRITING || el.sType == VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER);
- SerialiseNext(this, el.sType, el.pNext);
-
- Serialise("srcAccessMask", (VkAccessFlagBits &)el.srcAccessMask);
- Serialise("dstAccessMask", (VkAccessFlagBits &)el.dstAccessMask);
- Serialise("oldLayout", el.oldLayout);
- Serialise("newLayout", el.newLayout);
- // serialise as signed because then QUEUE_FAMILY_IGNORED is -1 and queue
- // family index won't be legitimately larger than 2 billion
- Serialise("srcQueueFamilyIndex", (int32_t &)el.srcQueueFamilyIndex);
- Serialise("dstQueueFamilyIndex", (int32_t &)el.dstQueueFamilyIndex);
- SerialiseObject(VkImage, "image", el.image);
- Serialise("subresourceRange", el.subresourceRange);
-}
-
-template <>
-void Serialiser::Serialise(const char *name, VkGraphicsPipelineCreateInfo &el)
-{
- ScopedContext scope(this, name, "VkGraphicsPipelineCreateInfo", 0, true);
-
- RDCASSERT(m_Mode < WRITING || el.sType == VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO);
- SerialiseNext(this, el.sType, el.pNext);
-
- Serialise("flags", (VkPipelineCreateFlagBits &)el.flags);
- SerialiseObject(VkPipelineLayout, "layout", el.layout);
- SerialiseObject(VkRenderPass, "renderPass", el.renderPass);
- Serialise("subpass", el.subpass);
- SerialiseObject(VkPipeline, "basePipelineHandle", el.basePipelineHandle);
- Serialise("basePipelineIndex", el.basePipelineIndex);
-
- SerialiseOptionalObject(this, "pVertexInputState",
- (VkPipelineVertexInputStateCreateInfo *&)el.pVertexInputState);
- SerialiseOptionalObject(this, "pInputAssemblyState",
- (VkPipelineInputAssemblyStateCreateInfo *&)el.pInputAssemblyState);
- SerialiseOptionalObject(this, "pTessellationState",
- (VkPipelineTessellationStateCreateInfo *&)el.pTessellationState);
- SerialiseOptionalObject(this, "pViewportState",
- (VkPipelineViewportStateCreateInfo *&)el.pViewportState);
- SerialiseOptionalObject(this, "pRasterState",
- (VkPipelineRasterizationStateCreateInfo *&)el.pRasterizationState);
- SerialiseOptionalObject(this, "pMultisampleState",
- (VkPipelineMultisampleStateCreateInfo *&)el.pMultisampleState);
- SerialiseOptionalObject(this, "pDepthStencilState",
- (VkPipelineDepthStencilStateCreateInfo *&)el.pDepthStencilState);
- SerialiseOptionalObject(this, "pColorBlendState",
- (VkPipelineColorBlendStateCreateInfo *&)el.pColorBlendState);
- SerialiseOptionalObject(this, "pDynamicState",
- (VkPipelineDynamicStateCreateInfo *&)el.pDynamicState);
-
- SerialiseComplexArray("pStages", (VkPipelineShaderStageCreateInfo *&)el.pStages, el.stageCount);
-}
-
-template <>
-void Serialiser::Deserialise(const VkGraphicsPipelineCreateInfo *const el) const
-{
- if(m_Mode == READING)
- {
- RDCASSERT(el->pNext == NULL); // otherwise delete
- if(el->pVertexInputState)
- {
- RDCASSERT(el->pVertexInputState->pNext == NULL); // otherwise delete
- delete[] el->pVertexInputState->pVertexBindingDescriptions;
- delete[] el->pVertexInputState->pVertexAttributeDescriptions;
- delete el->pVertexInputState;
- }
- if(el->pInputAssemblyState)
- {
- RDCASSERT(el->pInputAssemblyState->pNext == NULL); // otherwise delete
- delete el->pInputAssemblyState;
- }
- if(el->pTessellationState)
- {
- RDCASSERT(el->pTessellationState->pNext == NULL); // otherwise delete
- delete el->pTessellationState;
- }
- if(el->pViewportState)
- {
- RDCASSERT(el->pViewportState->pNext == NULL); // otherwise delete
- if(el->pViewportState->pViewports)
- delete[] el->pViewportState->pViewports;
- if(el->pViewportState->pScissors)
- delete[] el->pViewportState->pScissors;
- delete el->pViewportState;
- }
- if(el->pRasterizationState)
- {
- RDCASSERT(el->pRasterizationState->pNext == NULL); // otherwise delete
- delete el->pRasterizationState;
- }
- if(el->pMultisampleState)
- {
- RDCASSERT(el->pMultisampleState->pNext == NULL); // otherwise delete
- delete el->pMultisampleState->pSampleMask;
- delete el->pMultisampleState;
- }
- if(el->pDepthStencilState)
- {
- RDCASSERT(el->pDepthStencilState->pNext == NULL); // otherwise delete
- delete el->pDepthStencilState;
- }
- if(el->pColorBlendState)
- {
- RDCASSERT(el->pColorBlendState->pNext == NULL); // otherwise delete
- delete[] el->pColorBlendState->pAttachments;
- delete el->pColorBlendState;
- }
- if(el->pDynamicState)
- {
- RDCASSERT(el->pDynamicState->pNext == NULL); // otherwise delete
- if(el->pDynamicState->pDynamicStates)
- delete[] el->pDynamicState->pDynamicStates;
- delete el->pDynamicState;
- }
- for(uint32_t i = 0; i < el->stageCount; i++)
- {
- RDCASSERT(el->pStages[i].pNext == NULL); // otherwise delete
- if(el->pStages[i].pSpecializationInfo)
- {
- delete[](byte *)(el->pStages[i].pSpecializationInfo->pData);
- delete[] el->pStages[i].pSpecializationInfo->pMapEntries;
- delete el->pStages[i].pSpecializationInfo;
- }
- }
- delete[] el->pStages;
- }
-}
-
-template <>
-void Serialiser::Serialise(const char *name, VkComputePipelineCreateInfo &el)
-{
- ScopedContext scope(this, name, "VkComputePipelineCreateInfo", 0, true);
-
- RDCASSERT(m_Mode < WRITING || el.sType == VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO);
- SerialiseNext(this, el.sType, el.pNext);
-
- Serialise("stage", el.stage);
- Serialise("flags", (VkPipelineCreateFlagBits &)el.flags);
- SerialiseObject(VkPipelineLayout, "layout", el.layout);
- SerialiseObject(VkPipeline, "basePipelineHandle", el.basePipelineHandle);
- Serialise("basePipelineIndex", el.basePipelineIndex);
-}
-
-template <>
-void Serialiser::Deserialise(const VkComputePipelineCreateInfo *const el) const
-{
- if(m_Mode == READING)
- {
- RDCASSERT(el->pNext == NULL); // otherwise delete
- RDCASSERT(el->stage.pNext == NULL); // otherwise delete
- if(el->stage.pSpecializationInfo)
- {
- delete[](byte *)(el->stage.pSpecializationInfo->pData);
- delete[] el->stage.pSpecializationInfo->pMapEntries;
- delete el->stage.pSpecializationInfo;
- }
- }
-}
-
-template <>
-void Serialiser::Serialise(const char *name, VkDescriptorPoolSize &el)
-{
- ScopedContext scope(this, name, "VkDescriptorPoolSize", 0, true);
-
- Serialise("type", el.type);
- Serialise("descriptorCount", el.descriptorCount);
-}
-
-template <>
-void Serialiser::Serialise(const char *name, VkDescriptorPoolCreateInfo &el)
-{
- ScopedContext scope(this, name, "VkDescriptorPoolCreateInfo", 0, true);
-
- RDCASSERT(m_Mode < WRITING || el.sType == VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO);
- SerialiseNext(this, el.sType, el.pNext);
-
- Serialise("flags", (VkDescriptorPoolCreateFlagBits &)el.flags);
- Serialise("maxSets", el.maxSets);
- SerialiseComplexArray("pTypeCount", (VkDescriptorPoolSize *&)el.pPoolSizes, el.poolSizeCount);
-}
-
-template <>
-void Serialiser::Deserialise(const VkDescriptorPoolCreateInfo *const el) const
-{
- if(m_Mode == READING)
- {
- RDCASSERT(el->pNext == NULL); // otherwise delete
- delete[] el->pPoolSizes;
- }
-}
-
-template <>
-void Serialiser::Serialise(const char *name, VkDescriptorSetAllocateInfo &el)
-{
- ScopedContext scope(this, name, "VkDescriptorSetAllocateInfo", 0, true);
-
- RDCASSERT(m_Mode < WRITING || el.sType == VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO);
- SerialiseNext(this, el.sType, el.pNext);
-
- SerialiseObject(VkDescriptorPool, "descriptorPool", el.descriptorPool);
-
- // need to do this one by hand since it's just an array of objects that don't themselves have
- // a Serialise overload
- Serialise("descriptorSetCount", el.descriptorSetCount);
-
- if(m_Mode == READING)
- el.pSetLayouts = el.descriptorSetCount ? new VkDescriptorSetLayout[el.descriptorSetCount] : NULL;
-
- // cast away const on array so we can assign to it on reading
- VkDescriptorSetLayout *layouts = (VkDescriptorSetLayout *)el.pSetLayouts;
- for(uint32_t i = 0; i < el.descriptorSetCount; i++)
- SerialiseObject(VkDescriptorSetLayout, "pSetLayouts", layouts[i]);
-}
-
-template <>
-void Serialiser::Deserialise(const VkDescriptorSetAllocateInfo *const el) const
-{
- if(m_Mode == READING)
- {
- RDCASSERT(el->pNext == NULL); // otherwise delete
- delete[] el->pSetLayouts;
- }
-}
-
-template <>
-void Serialiser::Serialise(const char *name, VkDescriptorImageInfo &el)
-{
- ScopedContext scope(this, name, "VkDescriptorImageInfo", 0, true);
-
- SerialiseObjectOptional(VkSampler, "sampler", el.sampler);
- SerialiseObjectOptional(VkImageView, "imageView", el.imageView);
- Serialise("imageLayout", el.imageLayout);
-}
-
-template <>
-void Serialiser::Serialise(const char *name, VkDescriptorBufferInfo &el)
-{
- ScopedContext scope(this, name, "VkDescriptorBufferInfo", 0, true);
-
- SerialiseObjectOptional(VkBuffer, "buffer", el.buffer);
- Serialise("offset", el.offset);
- Serialise("range", el.range);
-}
-
-template <>
-void Serialiser::Serialise(const char *name, VkWriteDescriptorSet &el)
-{
- ScopedContext scope(this, name, "VkWriteDescriptorSet", 0, true);
-
- RDCASSERT(m_Mode < WRITING || el.sType == VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET);
- SerialiseNext(this, el.sType, el.pNext);
-
- SerialiseObjectOptional(VkDescriptorSet, "dstSet", el.dstSet);
- Serialise("dstBinding", el.dstBinding);
- Serialise("dstArrayElement", el.dstArrayElement);
- Serialise("descriptorType", el.descriptorType);
-
- if(m_Mode == READING)
- {
- el.pImageInfo = NULL;
- el.pBufferInfo = NULL;
- el.pTexelBufferView = NULL;
- }
-
- // only serialise the array type used, the others are ignored
- if(el.descriptorType == VK_DESCRIPTOR_TYPE_SAMPLER ||
- el.descriptorType == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER ||
- el.descriptorType == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE ||
- el.descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_IMAGE ||
- el.descriptorType == VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT)
- {
- SerialiseComplexArray("pImageInfo", (VkDescriptorImageInfo *&)el.pImageInfo, el.descriptorCount);
- }
- else if(el.descriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER ||
- el.descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER ||
- el.descriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC ||
- el.descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC)
- {
- SerialiseComplexArray("pBufferInfo", (VkDescriptorBufferInfo *&)el.pBufferInfo,
- el.descriptorCount);
- }
- else if(el.descriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER ||
- el.descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER)
- {
- // need to do this one by hand since it's just an array of objects that don't themselves have
- // a Serialise overload
- Serialise("descriptorCount", el.descriptorCount);
-
- if(m_Mode == READING)
- el.pTexelBufferView = el.descriptorCount ? new VkBufferView[el.descriptorCount] : NULL;
-
- // cast away const on array so we can assign to it on reading
- VkBufferView *views = (VkBufferView *)el.pTexelBufferView;
- for(uint32_t i = 0; i < el.descriptorCount; i++)
- SerialiseObjectOptional(VkBufferView, "pTexelBufferView", views[i]);
- }
-}
-
-template <>
-void Serialiser::Deserialise(const VkWriteDescriptorSet *const el) const
-{
- if(m_Mode == READING)
- {
- RDCASSERT(el->pNext == NULL); // otherwise delete
- if(el->pImageInfo)
- delete[] el->pImageInfo;
- if(el->pBufferInfo)
- delete[] el->pBufferInfo;
- if(el->pTexelBufferView)
- delete[] el->pTexelBufferView;
- }
-}
-
-template <>
-void Serialiser::Serialise(const char *name, VkCopyDescriptorSet &el)
-{
- ScopedContext scope(this, name, "VkCopyDescriptorSet", 0, true);
-
- RDCASSERT(m_Mode < WRITING || el.sType == VK_STRUCTURE_TYPE_COPY_DESCRIPTOR_SET);
- SerialiseNext(this, el.sType, el.pNext);
-
- SerialiseObjectOptional(VkDescriptorSet, "srcSet", el.srcSet);
- Serialise("srcBinding", el.srcBinding);
- Serialise("srcArrayElement", el.srcArrayElement);
- SerialiseObjectOptional(VkDescriptorSet, "destSet", el.dstSet);
- Serialise("destBinding", el.dstBinding);
- Serialise("destArrayElement", el.dstArrayElement);
-
- Serialise("descriptorCount", el.descriptorCount);
-}
-
-template <>
-void Serialiser::Serialise(const char *name, VkPushConstantRange &el)
-{
- ScopedContext scope(this, name, "VkPushConstantRange", 0, true);
-
- Serialise("stageFlags", (VkShaderStageFlagBits &)el.stageFlags);
- Serialise("offset", el.offset);
- Serialise("size", el.size);
-}
-
-template <>
-void Serialiser::Serialise(const char *name, VkDescriptorSetLayoutBinding &el)
-{
- ScopedContext scope(this, name, "VkDescriptorSetLayoutBinding", 0, true);
-
- Serialise("binding", el.binding);
- Serialise("descriptorType", el.descriptorType);
- Serialise("descriptorCount", el.descriptorCount);
- Serialise("stageFlags", (VkShaderStageFlagBits &)el.stageFlags);
-
- bool hasSamplers = el.pImmutableSamplers != NULL;
- Serialise("hasSamplers", hasSamplers);
-
- // do this one by hand because it's an array of objects that aren't Serialise
- // overloaded
- if(m_Mode == READING)
- {
- if(hasSamplers)
- el.pImmutableSamplers = el.descriptorCount ? new VkSampler[el.descriptorCount] : NULL;
- else
- el.pImmutableSamplers = NULL;
- }
-
- VkSampler *samplers = (VkSampler *)el.pImmutableSamplers;
-
- for(uint32_t i = 0; hasSamplers && i < el.descriptorCount; i++)
- {
- SerialiseObject(VkSampler, "pImmutableSampler", samplers[i]);
- }
-}
-
-template <>
-void Serialiser::Serialise(const char *name, VkDescriptorSetLayoutCreateInfo &el)
-{
- ScopedContext scope(this, name, "VkDescriptorSetLayoutCreateInfo", 0, true);
-
- RDCASSERT(m_Mode < WRITING || el.sType == VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO);
- SerialiseNext(this, el.sType, el.pNext);
-
- Serialise("flags", (VkFlagWithNoBits &)el.flags);
- SerialiseComplexArray("pBindings", (VkDescriptorSetLayoutBinding *&)el.pBindings, el.bindingCount);
-}
-
-template <>
-void Serialiser::Deserialise(const VkDescriptorSetLayoutCreateInfo *const el) const
-{
- if(m_Mode == READING)
- {
- RDCASSERT(el->pNext == NULL); // otherwise delete
- for(uint32_t i = 0; i < el->bindingCount; i++)
- if(el->pBindings[i].pImmutableSamplers)
- delete[] el->pBindings[i].pImmutableSamplers;
- delete[] el->pBindings;
- }
-}
-
-template <>
-void Serialiser::Serialise(const char *name, VkComponentMapping &el)
-{
- ScopedContext scope(this, name, "VkComponentMapping", 0, true);
-
- Serialise("r", el.r);
- Serialise("g", el.g);
- Serialise("b", el.b);
- Serialise("a", el.a);
-}
-
-template <>
-void Serialiser::Serialise(const char *name, VkBufferImageCopy &el)
-{
- ScopedContext scope(this, name, "VkBufferImageCopy", 0, true);
-
- Serialise("memOffset", el.bufferOffset);
- Serialise("bufferRowLength", el.bufferRowLength);
- Serialise("bufferImageHeight", el.bufferImageHeight);
- Serialise("imageSubresource", el.imageSubresource);
- Serialise("imageOffset", el.imageOffset);
- Serialise("imageExtent", el.imageExtent);
-}
-
-template <>
-void Serialiser::Serialise(const char *name, VkBufferCopy &el)
-{
- ScopedContext scope(this, name, "VkBufferCopy", 0, true);
-
- Serialise("srcOffset", el.srcOffset);
- Serialise("dstOffset", el.dstOffset);
- Serialise("size", el.size);
-}
-
-template <>
-void Serialiser::Serialise(const char *name, VkImageCopy &el)
-{
- ScopedContext scope(this, name, "VkImageCopy", 0, true);
-
- Serialise("srcSubresource", el.srcSubresource);
- Serialise("srcOffset", el.srcOffset);
- Serialise("dstSubresource", el.dstSubresource);
- Serialise("dstOffset", el.dstOffset);
- Serialise("extent", el.extent);
-}
-
-template <>
-void Serialiser::Serialise(const char *name, VkImageBlit &el)
-{
- ScopedContext scope(this, name, "VkImageBlit", 0, true);
-
- Serialise("srcSubresource", el.srcSubresource);
- SerialisePODArray<2>("srcOffsets", el.srcOffsets);
- Serialise("dstSubresource", el.dstSubresource);
- SerialisePODArray<2>("dstOffsets", el.dstOffsets);
-}
-
-template <>
-void Serialiser::Serialise(const char *name, VkImageResolve &el)
-{
- ScopedContext scope(this, name, "VkImageResolve", 0, true);
-
- Serialise("srcSubresource", el.srcSubresource);
- Serialise("srcOffset", el.srcOffset);
- Serialise("dstSubresource", el.dstSubresource);
- Serialise("dstOffset", el.dstOffset);
- Serialise("extent", el.extent);
-}
-
-template <>
-void Serialiser::Serialise(const char *name, VkRect2D &el)
-{
- ScopedContext scope(this, name, "VkRect2D", 0, true);
-
- Serialise("offset", el.offset);
- Serialise("extent", el.extent);
-}
-
-template <>
-void Serialiser::Serialise(const char *name, VkSwapchainCreateInfoKHR &el)
-{
- ScopedContext scope(this, name, "VkSwapchainCreateInfoKHR", 0, true);
-
- RDCASSERT(m_Mode < WRITING || el.sType == VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR);
- SerialiseNext(this, el.sType, el.pNext);
-
- Serialise("flags", (VkFlagWithNoBits &)el.flags);
-
- // don't need the surface
-
- Serialise("minImageCount", el.minImageCount);
- Serialise("imageFormat", el.imageFormat);
- Serialise("imageColorSpace", el.imageColorSpace);
- Serialise("imageExtent", el.imageExtent);
- Serialise("imageArrayLayers", el.imageArrayLayers);
- Serialise("imageUsage", el.imageUsage);
-
- // SHARING: sharingMode, queueFamilyCount, pQueueFamilyIndices
-
- Serialise("preTransform", el.preTransform);
- Serialise("compositeAlpha", el.compositeAlpha);
- Serialise("presentMode", el.presentMode);
- Serialise("clipped", el.clipped);
-
- // don't need the old swap chain
-}
-
-// this isn't a real vulkan type, it's our own "anything that could be in a descriptor"
-// structure that
-template <>
-void Serialiser::Serialise(const char *name, DescriptorSetSlot &el)
-{
- SerialiseObject(VkBuffer, "bufferInfo.buffer", el.bufferInfo.buffer);
- Serialise("bufferInfo.offset", el.bufferInfo.offset);
- Serialise("bufferInfo.range", el.bufferInfo.range);
-
- SerialiseObject(VkSampler, "imageInfo.sampler", el.imageInfo.sampler);
- SerialiseObject(VkImageView, "imageInfo.imageView", el.imageInfo.imageView);
- Serialise("imageInfo.imageLayout", el.imageInfo.imageLayout);
-
- SerialiseObject(VkBufferView, "texelBufferView", el.texelBufferView);
-}
diff --git a/renderdoc/driver/vulkan/vk_common.h b/renderdoc/driver/vulkan/vk_common.h
index cdae6f3e9..6e33088fc 100644
--- a/renderdoc/driver/vulkan/vk_common.h
+++ b/renderdoc/driver/vulkan/vk_common.h
@@ -245,164 +245,12 @@ void AppendModifiedChainedStruct(byte *&tempMem, VkStruct *outputStruct,
ret func(__VA_ARGS__); \
bool CONCAT(Serialise_, func(Serialiser *localSerialiser, __VA_ARGS__));
-template <>
-void Serialiser::Serialise(const char *name, VkRect2D &el);
-template <>
-void Serialiser::Serialise(const char *name, VkDeviceQueueCreateInfo &el);
-template <>
-void Serialiser::Serialise(const char *name, VkPhysicalDeviceFeatures &el);
-template <>
-void Serialiser::Serialise(const char *name, VkPhysicalDeviceMemoryProperties &el);
-template <>
-void Serialiser::Serialise(const char *name, VkPhysicalDeviceProperties &el);
-template <>
-void Serialiser::Serialise(const char *name, VkDeviceCreateInfo &el);
-template <>
-void Serialiser::Serialise(const char *name, VkBufferCreateInfo &el);
-template <>
-void Serialiser::Serialise(const char *name, VkBufferViewCreateInfo &el);
-template <>
-void Serialiser::Serialise(const char *name, VkImageCreateInfo &el);
-template <>
-void Serialiser::Serialise(const char *name, VkImageViewCreateInfo &el);
-template <>
-void Serialiser::Serialise(const char *name, VkSparseMemoryBind &el);
-template <>
-void Serialiser::Serialise(const char *name, VkBindSparseInfo &el);
-template <>
-void Serialiser::Serialise(const char *name, VkFramebufferCreateInfo &el);
-template <>
-void Serialiser::Serialise(const char *name, VkRenderPassCreateInfo &el);
-template <>
-void Serialiser::Serialise(const char *name, VkRenderPassBeginInfo &el);
-template <>
-void Serialiser::Serialise(const char *name, VkPipelineInputAssemblyStateCreateInfo &el);
-template <>
-void Serialiser::Serialise(const char *name, VkPipelineTessellationStateCreateInfo &el);
-template <>
-void Serialiser::Serialise(const char *name, VkPipelineViewportStateCreateInfo &el);
-template <>
-void Serialiser::Serialise(const char *name, VkPipelineRasterizationStateCreateInfo &el);
-template <>
-void Serialiser::Serialise(const char *name, VkPipelineMultisampleStateCreateInfo &el);
-template <>
-void Serialiser::Serialise(const char *name, VkPipelineDepthStencilStateCreateInfo &el);
-template <>
-void Serialiser::Serialise(const char *name, VkPipelineColorBlendStateCreateInfo &el);
-template <>
-void Serialiser::Serialise(const char *name, VkPipelineDynamicStateCreateInfo &el);
-template <>
-void Serialiser::Serialise(const char *name, VkPipelineLayoutCreateInfo &el);
-template <>
-void Serialiser::Serialise(const char *name, VkPushConstantRange &el);
-template <>
-void Serialiser::Serialise(const char *name, VkDescriptorSetLayoutBinding &el);
-template <>
-void Serialiser::Serialise(const char *name, VkDescriptorSetLayoutCreateInfo &el);
-template <>
-void Serialiser::Serialise(const char *name, VkDescriptorPoolCreateInfo &el);
-template <>
-void Serialiser::Serialise(const char *name, VkDescriptorSetAllocateInfo &el);
-template <>
-void Serialiser::Serialise(const char *name, VkWriteDescriptorSet &el);
-template <>
-void Serialiser::Serialise(const char *name, VkCopyDescriptorSet &el);
-template <>
-void Serialiser::Serialise(const char *name, VkCommandPoolCreateInfo &el);
-template <>
-void Serialiser::Serialise(const char *name, VkCommandBufferAllocateInfo &el);
-template <>
-void Serialiser::Serialise(const char *name, VkCommandBufferBeginInfo &el);
-template <>
-void Serialiser::Serialise(const char *name, VkStencilOpState &el);
-template <>
-void Serialiser::Serialise(const char *name, VkQueryPoolCreateInfo &el);
-template <>
-void Serialiser::Serialise(const char *name, VkSemaphoreCreateInfo &el);
-template <>
-void Serialiser::Serialise(const char *name, VkEventCreateInfo &el);
-template <>
-void Serialiser::Serialise(const char *name, VkFenceCreateInfo &el);
-template <>
-void Serialiser::Serialise(const char *name, VkSamplerCreateInfo &el);
-template <>
-void Serialiser::Serialise(const char *name, VkPipelineCacheCreateInfo &el);
-template <>
-void Serialiser::Serialise(const char *name, VkShaderModuleCreateInfo &el);
-template <>
-void Serialiser::Serialise(const char *name, VkImageSubresourceRange &el);
-template <>
-void Serialiser::Serialise(const char *name, VkImageSubresource &el);
-template <>
-void Serialiser::Serialise(const char *name, VkImageSubresourceLayers &el);
-template <>
-void Serialiser::Serialise(const char *name, VkMemoryAllocateInfo &el);
-template <>
-void Serialiser::Serialise(const char *name, VkMemoryBarrier &el);
-template <>
-void Serialiser::Serialise(const char *name, VkBufferMemoryBarrier &el);
-template <>
-void Serialiser::Serialise(const char *name, VkImageMemoryBarrier &el);
-template <>
-void Serialiser::Serialise(const char *name, VkGraphicsPipelineCreateInfo &el);
-template <>
-void Serialiser::Serialise(const char *name, VkComputePipelineCreateInfo &el);
-template <>
-void Serialiser::Serialise(const char *name, VkComponentMapping &el);
-template <>
-void Serialiser::Serialise(const char *name, VkComputePipelineCreateInfo &el);
-template <>
-void Serialiser::Serialise(const char *name, VkBufferImageCopy &el);
-template <>
-void Serialiser::Serialise(const char *name, VkBufferCopy &el);
-template <>
-void Serialiser::Serialise(const char *name, VkImageCopy &el);
-template <>
-void Serialiser::Serialise(const char *name, VkImageBlit &el);
-template <>
-void Serialiser::Serialise(const char *name, VkImageResolve &el);
-
-template <>
-void Serialiser::Serialise(const char *name, VkSwapchainCreateInfoKHR &el);
-
-struct DescriptorSetSlot;
-template <>
-void Serialiser::Serialise(const char *name, DescriptorSetSlot &el);
-
-template <>
-void Serialiser::Deserialise(const VkDeviceCreateInfo *const el) const;
-template <>
-void Serialiser::Deserialise(const VkBufferCreateInfo *const el) const;
-template <>
-void Serialiser::Deserialise(const VkImageCreateInfo *const el) const;
-template <>
-void Serialiser::Deserialise(const VkBindSparseInfo *const el) const;
-template <>
-void Serialiser::Deserialise(const VkDescriptorSetAllocateInfo *const el) const;
-template <>
-void Serialiser::Deserialise(const VkFramebufferCreateInfo *const el) const;
-template <>
-void Serialiser::Deserialise(const VkRenderPassCreateInfo *const el) const;
-template <>
-void Serialiser::Deserialise(const VkRenderPassBeginInfo *const el) const;
-template <>
-void Serialiser::Deserialise(const VkCommandBufferBeginInfo *const el) const;
-template <>
-void Serialiser::Deserialise(const VkPipelineCacheCreateInfo *const el) const;
-template <>
-void Serialiser::Deserialise(const VkPipelineLayoutCreateInfo *const el) const;
-template <>
-void Serialiser::Deserialise(const VkShaderModuleCreateInfo *const el) const;
-template <>
-void Serialiser::Deserialise(const VkGraphicsPipelineCreateInfo *const el) const;
-template <>
-void Serialiser::Deserialise(const VkComputePipelineCreateInfo *const el) const;
-template <>
-void Serialiser::Deserialise(const VkDescriptorPoolCreateInfo *const el) const;
-template <>
-void Serialiser::Deserialise(const VkWriteDescriptorSet *const el) const;
-template <>
-void Serialiser::Deserialise(const VkDescriptorSetLayoutCreateInfo *const el) const;
+// A handy macros to say "is the serialiser reading and we're doing replay-mode stuff?"
+// The reason we check both is that checking the first allows the compiler to eliminate the other
+// path at compile-time, and the second because we might be just struct-serialising in which case we
+// should be doing no work to restore states.
+// Writing is unambiguously during capture mode, so we don't have to check both in that case.
+#define IsReplayingAndReading() (ser.IsReading() && IsReplayMode(m_State))
// the possible contents of a descriptor set slot,
// taken from the VkWriteDescriptorSet
@@ -413,6 +261,8 @@ struct DescriptorSetSlot
VkBufferView texelBufferView;
};
+DECLARE_REFLECTION_STRUCT(DescriptorSetSlot);
+
#define NUM_VK_IMAGE_ASPECTS 4
#define VK_ACCESS_ALL_READ_BITS \
(VK_ACCESS_INDIRECT_COMMAND_READ_BIT | VK_ACCESS_INDEX_READ_BIT | \
@@ -560,3 +410,221 @@ enum VulkanChunkType
};
#pragma endregion Chunks
+
+// this is special - these serialise overloads will fetch the ID during capture, serialise the ID
+// directly as-if it were the original type, then on replay load up the resource if available.
+// Really this is only one type of serialisation, but we declare a couple of overloads to account
+// for resources being accessed through different interfaces in different functions
+#define SERIALISE_VK_HANDLES() \
+ SERIALISE_HANDLE(VkInstance) \
+ SERIALISE_HANDLE(VkPhysicalDevice) \
+ SERIALISE_HANDLE(VkDevice) \
+ SERIALISE_HANDLE(VkQueue) \
+ SERIALISE_HANDLE(VkCommandBuffer) \
+ SERIALISE_HANDLE(VkFence) \
+ SERIALISE_HANDLE(VkDeviceMemory) \
+ SERIALISE_HANDLE(VkBuffer) \
+ SERIALISE_HANDLE(VkImage) \
+ SERIALISE_HANDLE(VkSemaphore) \
+ SERIALISE_HANDLE(VkEvent) \
+ SERIALISE_HANDLE(VkQueryPool) \
+ SERIALISE_HANDLE(VkBufferView) \
+ SERIALISE_HANDLE(VkImageView) \
+ SERIALISE_HANDLE(VkShaderModule) \
+ SERIALISE_HANDLE(VkPipelineCache) \
+ SERIALISE_HANDLE(VkPipelineLayout) \
+ SERIALISE_HANDLE(VkRenderPass) \
+ SERIALISE_HANDLE(VkPipeline) \
+ SERIALISE_HANDLE(VkDescriptorSetLayout) \
+ SERIALISE_HANDLE(VkSampler) \
+ SERIALISE_HANDLE(VkDescriptorPool) \
+ SERIALISE_HANDLE(VkDescriptorSet) \
+ SERIALISE_HANDLE(VkFramebuffer) \
+ SERIALISE_HANDLE(VkCommandPool) \
+ SERIALISE_HANDLE(VkSwapchainKHR) \
+ SERIALISE_HANDLE(VkSurfaceKHR)
+
+#define SERIALISE_HANDLE(type) DECLARE_REFLECTION_STRUCT(type)
+
+SERIALISE_VK_HANDLES();
+
+// declare reflect-able types
+
+DECLARE_REFLECTION_STRUCT(VkOffset2D);
+DECLARE_REFLECTION_STRUCT(VkExtent2D);
+DECLARE_REFLECTION_STRUCT(VkMemoryType);
+DECLARE_REFLECTION_STRUCT(VkMemoryHeap);
+DECLARE_REFLECTION_STRUCT(VkPhysicalDeviceLimits);
+DECLARE_REFLECTION_STRUCT(VkPhysicalDeviceSparseProperties);
+DECLARE_REFLECTION_STRUCT(VkQueueFamilyProperties);
+DECLARE_REFLECTION_STRUCT(VkExtent3D);
+DECLARE_REFLECTION_STRUCT(VkPipelineShaderStageCreateInfo);
+DECLARE_REFLECTION_STRUCT(VkOffset3D);
+DECLARE_REFLECTION_STRUCT(VkCommandBufferInheritanceInfo);
+DECLARE_REFLECTION_STRUCT(VkPipelineVertexInputStateCreateInfo);
+DECLARE_REFLECTION_STRUCT(VkSparseBufferMemoryBindInfo);
+DECLARE_REFLECTION_STRUCT(VkSparseImageOpaqueMemoryBindInfo);
+DECLARE_REFLECTION_STRUCT(VkSparseImageMemoryBindInfo);
+DECLARE_REFLECTION_STRUCT(VkAttachmentDescription);
+DECLARE_REFLECTION_STRUCT(VkSubpassDescription);
+DECLARE_REFLECTION_STRUCT(VkSubpassDependency);
+DECLARE_REFLECTION_STRUCT(VkClearValue);
+DECLARE_REFLECTION_STRUCT(VkClearColorValue);
+DECLARE_REFLECTION_STRUCT(VkClearDepthStencilValue);
+DECLARE_REFLECTION_STRUCT(VkClearAttachment);
+DECLARE_REFLECTION_STRUCT(VkClearRect);
+DECLARE_REFLECTION_STRUCT(VkViewport);
+DECLARE_REFLECTION_STRUCT(VkPipelineColorBlendAttachmentState);
+DECLARE_REFLECTION_STRUCT(VkDescriptorPoolSize);
+DECLARE_REFLECTION_STRUCT(VkDescriptorImageInfo);
+DECLARE_REFLECTION_STRUCT(VkDescriptorBufferInfo);
+DECLARE_REFLECTION_STRUCT(VkSpecializationInfo);
+DECLARE_REFLECTION_STRUCT(VkAttachmentReference);
+DECLARE_REFLECTION_STRUCT(VkSparseImageMemoryBind);
+DECLARE_REFLECTION_STRUCT(VkVertexInputBindingDescription);
+DECLARE_REFLECTION_STRUCT(VkVertexInputAttributeDescription);
+DECLARE_REFLECTION_STRUCT(VkSpecializationMapEntry);
+DECLARE_REFLECTION_STRUCT(VkRect2D);
+DECLARE_REFLECTION_STRUCT(VkDeviceQueueCreateInfo);
+DECLARE_REFLECTION_STRUCT(VkPhysicalDeviceFeatures);
+DECLARE_REFLECTION_STRUCT(VkPhysicalDeviceMemoryProperties);
+DECLARE_REFLECTION_STRUCT(VkPhysicalDeviceProperties);
+DECLARE_REFLECTION_STRUCT(VkDeviceCreateInfo);
+DECLARE_REFLECTION_STRUCT(VkBufferCreateInfo);
+DECLARE_REFLECTION_STRUCT(VkBufferViewCreateInfo);
+DECLARE_REFLECTION_STRUCT(VkImageCreateInfo);
+DECLARE_REFLECTION_STRUCT(VkImageViewCreateInfo);
+DECLARE_REFLECTION_STRUCT(VkSparseMemoryBind);
+DECLARE_REFLECTION_STRUCT(VkBindSparseInfo);
+DECLARE_REFLECTION_STRUCT(VkSubmitInfo);
+DECLARE_REFLECTION_STRUCT(VkFramebufferCreateInfo);
+DECLARE_REFLECTION_STRUCT(VkRenderPassCreateInfo);
+DECLARE_REFLECTION_STRUCT(VkRenderPassBeginInfo);
+DECLARE_REFLECTION_STRUCT(VkPipelineInputAssemblyStateCreateInfo);
+DECLARE_REFLECTION_STRUCT(VkPipelineTessellationStateCreateInfo);
+DECLARE_REFLECTION_STRUCT(VkPipelineViewportStateCreateInfo);
+DECLARE_REFLECTION_STRUCT(VkPipelineRasterizationStateCreateInfo);
+DECLARE_REFLECTION_STRUCT(VkPipelineMultisampleStateCreateInfo);
+DECLARE_REFLECTION_STRUCT(VkPipelineDepthStencilStateCreateInfo);
+DECLARE_REFLECTION_STRUCT(VkPipelineColorBlendStateCreateInfo);
+DECLARE_REFLECTION_STRUCT(VkPipelineDynamicStateCreateInfo);
+DECLARE_REFLECTION_STRUCT(VkPipelineLayoutCreateInfo);
+DECLARE_REFLECTION_STRUCT(VkPushConstantRange);
+DECLARE_REFLECTION_STRUCT(VkDescriptorSetLayoutBinding);
+DECLARE_REFLECTION_STRUCT(VkDescriptorSetLayoutCreateInfo);
+DECLARE_REFLECTION_STRUCT(VkDescriptorPoolCreateInfo);
+DECLARE_REFLECTION_STRUCT(VkDescriptorSetAllocateInfo);
+DECLARE_REFLECTION_STRUCT(VkWriteDescriptorSet);
+DECLARE_REFLECTION_STRUCT(VkCopyDescriptorSet);
+DECLARE_REFLECTION_STRUCT(VkCommandPoolCreateInfo);
+DECLARE_REFLECTION_STRUCT(VkCommandBufferAllocateInfo);
+DECLARE_REFLECTION_STRUCT(VkCommandBufferBeginInfo);
+DECLARE_REFLECTION_STRUCT(VkStencilOpState);
+DECLARE_REFLECTION_STRUCT(VkQueryPoolCreateInfo);
+DECLARE_REFLECTION_STRUCT(VkSemaphoreCreateInfo);
+DECLARE_REFLECTION_STRUCT(VkEventCreateInfo);
+DECLARE_REFLECTION_STRUCT(VkFenceCreateInfo);
+DECLARE_REFLECTION_STRUCT(VkSamplerCreateInfo);
+DECLARE_REFLECTION_STRUCT(VkPipelineCacheCreateInfo);
+DECLARE_REFLECTION_STRUCT(VkShaderModuleCreateInfo);
+DECLARE_REFLECTION_STRUCT(VkImageSubresourceRange);
+DECLARE_REFLECTION_STRUCT(VkImageSubresource);
+DECLARE_REFLECTION_STRUCT(VkImageSubresourceLayers);
+DECLARE_REFLECTION_STRUCT(VkMemoryAllocateInfo);
+DECLARE_REFLECTION_STRUCT(VkMemoryBarrier);
+DECLARE_REFLECTION_STRUCT(VkBufferMemoryBarrier);
+DECLARE_REFLECTION_STRUCT(VkImageMemoryBarrier);
+DECLARE_REFLECTION_STRUCT(VkGraphicsPipelineCreateInfo);
+DECLARE_REFLECTION_STRUCT(VkComputePipelineCreateInfo);
+DECLARE_REFLECTION_STRUCT(VkComponentMapping);
+DECLARE_REFLECTION_STRUCT(VkMappedMemoryRange);
+DECLARE_REFLECTION_STRUCT(VkBufferImageCopy);
+DECLARE_REFLECTION_STRUCT(VkBufferCopy);
+DECLARE_REFLECTION_STRUCT(VkImageCopy);
+DECLARE_REFLECTION_STRUCT(VkImageBlit);
+DECLARE_REFLECTION_STRUCT(VkImageResolve);
+DECLARE_REFLECTION_STRUCT(VkSwapchainCreateInfoKHR);
+DECLARE_REFLECTION_STRUCT(VkDebugMarkerMarkerInfoEXT);
+
+DECLARE_DESERIALISE_TYPE(VkDeviceCreateInfo);
+DECLARE_DESERIALISE_TYPE(VkBufferCreateInfo);
+DECLARE_DESERIALISE_TYPE(VkImageCreateInfo);
+DECLARE_DESERIALISE_TYPE(VkBindSparseInfo);
+DECLARE_DESERIALISE_TYPE(VkSubmitInfo);
+DECLARE_DESERIALISE_TYPE(VkDescriptorSetAllocateInfo);
+DECLARE_DESERIALISE_TYPE(VkFramebufferCreateInfo);
+DECLARE_DESERIALISE_TYPE(VkRenderPassCreateInfo);
+DECLARE_DESERIALISE_TYPE(VkRenderPassBeginInfo);
+DECLARE_DESERIALISE_TYPE(VkCommandBufferBeginInfo);
+DECLARE_DESERIALISE_TYPE(VkPipelineCacheCreateInfo);
+DECLARE_DESERIALISE_TYPE(VkPipelineLayoutCreateInfo);
+DECLARE_DESERIALISE_TYPE(VkShaderModuleCreateInfo);
+DECLARE_DESERIALISE_TYPE(VkGraphicsPipelineCreateInfo);
+DECLARE_DESERIALISE_TYPE(VkComputePipelineCreateInfo);
+DECLARE_DESERIALISE_TYPE(VkDescriptorPoolCreateInfo);
+DECLARE_DESERIALISE_TYPE(VkWriteDescriptorSet);
+DECLARE_DESERIALISE_TYPE(VkDescriptorSetLayoutCreateInfo);
+
+DECLARE_REFLECTION_ENUM(VkFlagWithNoBits);
+DECLARE_REFLECTION_ENUM(VkQueueFlagBits);
+DECLARE_REFLECTION_ENUM(VkPipelineCreateFlagBits);
+DECLARE_REFLECTION_ENUM(VkPipelineStageFlagBits);
+DECLARE_REFLECTION_ENUM(VkBufferUsageFlagBits);
+DECLARE_REFLECTION_ENUM(VkImageUsageFlagBits);
+DECLARE_REFLECTION_ENUM(VkBufferCreateFlagBits);
+DECLARE_REFLECTION_ENUM(VkImageCreateFlagBits);
+DECLARE_REFLECTION_ENUM(VkSparseMemoryBindFlagBits);
+DECLARE_REFLECTION_ENUM(VkCommandPoolCreateFlagBits);
+DECLARE_REFLECTION_ENUM(VkCommandPoolResetFlagBits);
+DECLARE_REFLECTION_ENUM(VkCommandBufferUsageFlagBits);
+DECLARE_REFLECTION_ENUM(VkDescriptorPoolCreateFlagBits);
+DECLARE_REFLECTION_ENUM(VkFenceCreateFlagBits);
+DECLARE_REFLECTION_ENUM(VkQueryPipelineStatisticFlagBits);
+DECLARE_REFLECTION_ENUM(VkQueryControlFlagBits);
+DECLARE_REFLECTION_ENUM(VkQueryResultFlagBits);
+DECLARE_REFLECTION_ENUM(VkAttachmentDescriptionFlagBits);
+DECLARE_REFLECTION_ENUM(VkSampleCountFlagBits);
+DECLARE_REFLECTION_ENUM(VkImageAspectFlagBits);
+DECLARE_REFLECTION_ENUM(VkDependencyFlagBits);
+DECLARE_REFLECTION_ENUM(VkShaderStageFlagBits);
+DECLARE_REFLECTION_ENUM(VkMemoryHeapFlagBits);
+DECLARE_REFLECTION_ENUM(VkMemoryPropertyFlagBits);
+DECLARE_REFLECTION_ENUM(VkAccessFlagBits);
+DECLARE_REFLECTION_ENUM(VkStencilFaceFlagBits);
+DECLARE_REFLECTION_ENUM(VkCullModeFlagBits);
+DECLARE_REFLECTION_ENUM(VkPipelineBindPoint);
+DECLARE_REFLECTION_ENUM(VkIndexType);
+DECLARE_REFLECTION_ENUM(VkImageType);
+DECLARE_REFLECTION_ENUM(VkImageTiling);
+DECLARE_REFLECTION_ENUM(VkImageViewType);
+DECLARE_REFLECTION_ENUM(VkVertexInputRate);
+DECLARE_REFLECTION_ENUM(VkPolygonMode);
+DECLARE_REFLECTION_ENUM(VkFrontFace);
+DECLARE_REFLECTION_ENUM(VkBlendFactor);
+DECLARE_REFLECTION_ENUM(VkBlendOp);
+DECLARE_REFLECTION_ENUM(VkDynamicState);
+DECLARE_REFLECTION_ENUM(VkAttachmentLoadOp);
+DECLARE_REFLECTION_ENUM(VkAttachmentStoreOp);
+DECLARE_REFLECTION_ENUM(VkStencilOp);
+DECLARE_REFLECTION_ENUM(VkLogicOp);
+DECLARE_REFLECTION_ENUM(VkCompareOp);
+DECLARE_REFLECTION_ENUM(VkFilter);
+DECLARE_REFLECTION_ENUM(VkSamplerMipmapMode);
+DECLARE_REFLECTION_ENUM(VkSamplerAddressMode);
+DECLARE_REFLECTION_ENUM(VkBorderColor);
+DECLARE_REFLECTION_ENUM(VkPrimitiveTopology);
+DECLARE_REFLECTION_ENUM(VkDescriptorType);
+DECLARE_REFLECTION_ENUM(VkQueryType);
+DECLARE_REFLECTION_ENUM(VkPhysicalDeviceType);
+DECLARE_REFLECTION_ENUM(VkSharingMode);
+DECLARE_REFLECTION_ENUM(VkCommandBufferLevel);
+DECLARE_REFLECTION_ENUM(VkSubpassContents);
+DECLARE_REFLECTION_ENUM(VkImageLayout);
+DECLARE_REFLECTION_ENUM(VkStructureType);
+DECLARE_REFLECTION_ENUM(VkComponentSwizzle);
+DECLARE_REFLECTION_ENUM(VkFormat);
+DECLARE_REFLECTION_ENUM(VkResult);
+DECLARE_REFLECTION_ENUM(VkSurfaceTransformFlagBitsKHR);
+DECLARE_REFLECTION_ENUM(VkCompositeAlphaFlagBitsKHR);
+DECLARE_REFLECTION_ENUM(VkColorSpaceKHR);
+DECLARE_REFLECTION_ENUM(VkPresentModeKHR);
diff --git a/renderdoc/driver/vulkan/vk_debug.cpp b/renderdoc/driver/vulkan/vk_debug.cpp
index 2bfbc0c11..65a74813d 100644
--- a/renderdoc/driver/vulkan/vk_debug.cpp
+++ b/renderdoc/driver/vulkan/vk_debug.cpp
@@ -4955,6 +4955,8 @@ struct VulkanQuadOverdrawCallback : public VulkanDrawcallCallback
m_pDriver->GetResourceManager()->WrapResource(Unwrap(dev), module);
+ m_pDriver->GetResourceManager()->AddLiveResource(GetResID(module), module);
+
bool found = false;
for(uint32_t i = 0; i < pipeCreateInfo.stageCount; i++)
{
diff --git a/renderdoc/driver/vulkan/vk_info.cpp b/renderdoc/driver/vulkan/vk_info.cpp
index 5b256bc98..82957206b 100644
--- a/renderdoc/driver/vulkan/vk_info.cpp
+++ b/renderdoc/driver/vulkan/vk_info.cpp
@@ -58,15 +58,7 @@ void DescSetLayout::Init(VulkanResourceManager *resourceMan, VulkanCreationInfo
bindings[b].immutableSampler = new ResourceId[bindings[b].descriptorCount];
for(uint32_t s = 0; s < bindings[b].descriptorCount; s++)
- {
- // during writing, the create info contains the *wrapped* objects.
- // on replay, we have the wrapper map so we can look it up
- if(resourceMan->IsWriting())
- bindings[b].immutableSampler[s] = GetResID(pCreateInfo->pBindings[i].pImmutableSamplers[s]);
- else
- bindings[b].immutableSampler[s] =
- resourceMan->GetNonDispWrapper(pCreateInfo->pBindings[i].pImmutableSamplers[s])->id;
- }
+ bindings[b].immutableSampler[s] = GetResID(pCreateInfo->pBindings[i].pImmutableSamplers[s]);
}
}
}
@@ -125,8 +117,8 @@ void VulkanCreationInfo::Pipeline::Init(VulkanResourceManager *resourceMan, Vulk
{
flags = pCreateInfo->flags;
- layout = resourceMan->GetNonDispWrapper(pCreateInfo->layout)->id;
- renderpass = resourceMan->GetNonDispWrapper(pCreateInfo->renderPass)->id;
+ layout = GetResID(pCreateInfo->layout);
+ renderpass = GetResID(pCreateInfo->renderPass);
subpass = pCreateInfo->subpass;
// need to figure out which states are valid to be NULL
@@ -134,7 +126,7 @@ void VulkanCreationInfo::Pipeline::Init(VulkanResourceManager *resourceMan, Vulk
// VkPipelineShaderStageCreateInfo
for(uint32_t i = 0; i < pCreateInfo->stageCount; i++)
{
- ResourceId id = resourceMan->GetNonDispWrapper(pCreateInfo->pStages[i].module)->id;
+ ResourceId id = GetResID(pCreateInfo->pStages[i].module);
// convert shader bit to shader index
int stageIndex = StageIndex(pCreateInfo->pStages[i].stage);
@@ -358,13 +350,13 @@ void VulkanCreationInfo::Pipeline::Init(VulkanResourceManager *resourceMan, Vulk
{
flags = pCreateInfo->flags;
- layout = resourceMan->GetNonDispWrapper(pCreateInfo->layout)->id;
+ layout = GetResID(pCreateInfo->layout);
// need to figure out which states are valid to be NULL
// VkPipelineShaderStageCreateInfo
{
- ResourceId id = resourceMan->GetNonDispWrapper(pCreateInfo->stage.module)->id;
+ ResourceId id = GetResID(pCreateInfo->stage.module);
Shader &shad = shaders[5]; // 5 is the compute shader's index (VS, TCS, TES, GS, FS, CS)
shad.module = id;
@@ -451,7 +443,7 @@ void VulkanCreationInfo::PipelineLayout::Init(VulkanResourceManager *resourceMan
{
descSetLayouts.resize(pCreateInfo->setLayoutCount);
for(uint32_t i = 0; i < pCreateInfo->setLayoutCount; i++)
- descSetLayouts[i] = resourceMan->GetNonDispWrapper(pCreateInfo->pSetLayouts[i])->id;
+ descSetLayouts[i] = GetResID(pCreateInfo->pSetLayouts[i]);
pushRanges.reserve(pCreateInfo->pushConstantRangeCount);
for(uint32_t i = 0; i < pCreateInfo->pushConstantRangeCount; i++)
@@ -514,7 +506,7 @@ void VulkanCreationInfo::Framebuffer::Init(VulkanResourceManager *resourceMan,
attachments.resize(pCreateInfo->attachmentCount);
for(uint32_t i = 0; i < pCreateInfo->attachmentCount; i++)
{
- attachments[i].view = resourceMan->GetNonDispWrapper(pCreateInfo->pAttachments[i])->id;
+ attachments[i].view = GetResID(pCreateInfo->pAttachments[i]);
attachments[i].format = info.m_ImageView[attachments[i].view].format;
}
}
@@ -536,7 +528,7 @@ void VulkanCreationInfo::BufferView::Init(VulkanResourceManager *resourceMan,
VulkanCreationInfo &info,
const VkBufferViewCreateInfo *pCreateInfo)
{
- buffer = resourceMan->GetNonDispWrapper(pCreateInfo->buffer)->id;
+ buffer = GetResID(pCreateInfo->buffer);
offset = pCreateInfo->offset;
size = pCreateInfo->range;
}
@@ -608,7 +600,7 @@ static TextureSwizzle Convert(VkComponentSwizzle s, int i)
void VulkanCreationInfo::ImageView::Init(VulkanResourceManager *resourceMan, VulkanCreationInfo &info,
const VkImageViewCreateInfo *pCreateInfo)
{
- image = resourceMan->GetNonDispWrapper(pCreateInfo->image)->id;
+ image = GetResID(pCreateInfo->image);
format = pCreateInfo->format;
range = pCreateInfo->subresourceRange;
diff --git a/renderdoc/driver/vulkan/vk_manager.cpp b/renderdoc/driver/vulkan/vk_manager.cpp
index c733661c1..2a41c78ce 100644
--- a/renderdoc/driver/vulkan/vk_manager.cpp
+++ b/renderdoc/driver/vulkan/vk_manager.cpp
@@ -25,16 +25,6 @@
#include "vk_manager.h"
#include "vk_core.h"
-template <>
-void Serialiser::Serialise(const char *name, ImageRegionState &el)
-{
- ScopedContext scope(this, name, "ImageRegionState", 0, true);
-
- Serialise("range", el.subresourceRange);
- Serialise("prevstate", el.oldLayout);
- Serialise("state", el.newLayout);
-}
-
bool VulkanResourceManager::SerialisableResource(ResourceId id, VkResourceRecord *record)
{
if(record->SpecialResource || id == m_Core->GetContextResourceID())
@@ -208,7 +198,7 @@ void VulkanResourceManager::RecordBarriers(vectorid : GetResID(t.image);
+ ResourceId id = IsReplayMode(m_State) ? GetNonDispWrapper(t.image)->id : GetResID(t.image);
if(id == ResourceId())
{
diff --git a/renderdoc/driver/vulkan/vk_replay.cpp b/renderdoc/driver/vulkan/vk_replay.cpp
index c6c2f49f8..0b886c28e 100644
--- a/renderdoc/driver/vulkan/vk_replay.cpp
+++ b/renderdoc/driver/vulkan/vk_replay.cpp
@@ -3293,8 +3293,7 @@ void VulkanReplay::SavePipelineState()
}
else if(info[a].imageInfo.sampler != VK_NULL_HANDLE)
{
- dst.bindings[b].binds[a].sampler =
- rm->GetNonDispWrapper(info[a].imageInfo.sampler)->id;
+ dst.bindings[b].binds[a].sampler = GetResID(info[a].imageInfo.sampler);
}
if(dst.bindings[b].binds[a].sampler != ResourceId())
@@ -3339,7 +3338,7 @@ void VulkanReplay::SavePipelineState()
if(view != VK_NULL_HANDLE)
{
- ResourceId viewid = rm->GetNonDispWrapper(view)->id;
+ ResourceId viewid = GetResID(view);
dst.bindings[b].binds[a].view = rm->GetOriginalID(viewid);
dst.bindings[b].binds[a].res = rm->GetOriginalID(c.m_ImageView[viewid].image);
@@ -3369,7 +3368,7 @@ void VulkanReplay::SavePipelineState()
if(view != VK_NULL_HANDLE)
{
- ResourceId viewid = rm->GetNonDispWrapper(view)->id;
+ ResourceId viewid = GetResID(view);
dst.bindings[b].binds[a].view = rm->GetOriginalID(viewid);
dst.bindings[b].binds[a].res = rm->GetOriginalID(c.m_BufferView[viewid].buffer);
@@ -3408,7 +3407,7 @@ void VulkanReplay::SavePipelineState()
if(info[a].bufferInfo.buffer != VK_NULL_HANDLE)
dst.bindings[b].binds[a].res =
- rm->GetOriginalID(rm->GetNonDispWrapper(info[a].bufferInfo.buffer)->id);
+ rm->GetOriginalID(GetResID(info[a].bufferInfo.buffer));
dst.bindings[b].binds[a].offset = info[a].bufferInfo.offset;
if(dynamicOffset)
diff --git a/renderdoc/driver/vulkan/vk_resources.h b/renderdoc/driver/vulkan/vk_resources.h
index 8bf1c6f8c..b5594f0bc 100644
--- a/renderdoc/driver/vulkan/vk_resources.h
+++ b/renderdoc/driver/vulkan/vk_resources.h
@@ -817,6 +817,8 @@ struct ImageRegionState
VkImageLayout newLayout;
};
+DECLARE_REFLECTION_STRUCT(ImageRegionState);
+
struct SwapchainInfo
{
VkFormat format;
@@ -1147,6 +1149,8 @@ struct ImageLayouts
VkFormat format;
};
+DECLARE_REFLECTION_STRUCT(ImageLayouts);
+
bool IsBlockFormat(VkFormat f);
bool IsDepthOrStencilFormat(VkFormat f);
bool IsDepthAndStencilFormat(VkFormat f);
diff --git a/renderdoc/driver/vulkan/vk_serialise.cpp b/renderdoc/driver/vulkan/vk_serialise.cpp
new file mode 100644
index 000000000..1874fe505
--- /dev/null
+++ b/renderdoc/driver/vulkan/vk_serialise.cpp
@@ -0,0 +1,1871 @@
+/******************************************************************************
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2015-2017 Baldur Karlsson
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ ******************************************************************************/
+
+#include "vk_common.h"
+#include "vk_manager.h"
+#include "vk_resources.h"
+
+// simple way to express "resources referenced from this struct don't have to be present."
+// since this is used during read when the processing is single-threaded, we make it a static flag.
+// If we multi-thread reading, this could be stored in the Serialiser context somehow.
+template
+struct OptionalResources
+{
+private:
+ OptionalResources() = default;
+};
+
+// does nothing on writing
+template <>
+struct OptionalResources>
+{
+ OptionalResources>(Serialiser &ser)
+ {
+ }
+ ~OptionalResources>() {}
+};
+
+template <>
+struct OptionalResources>
+{
+ OptionalResources>(Serialiser &ser)
+ {
+ Counter++;
+ }
+ ~OptionalResources>() { Counter--; }
+ static int Counter;
+};
+
+template
+OptionalResources ScopedOptional(SerialiserType &ser)
+{
+ return OptionalResources(ser);
+}
+
+int OptionalResources>::Counter = 0;
+
+bool OptionalResourcesEnabled()
+{
+ return OptionalResources>::Counter > 0;
+}
+
+// push/pop the optional flag. This doesn't allow non-optional objects in a sub-struct inside a
+// struct that had optional objects... but that doesn't come up and seems unlikely.
+#define OPTIONAL_RESOURCES() auto opt__LINE__ = ScopedOptional(ser);
+
+// serialisation of object handles via IDs.
+template
+void DoSerialiseViaResourceId(SerialiserType &ser, type &el)
+{
+ VulkanResourceManager *rm = (VulkanResourceManager *)ser.GetUserData();
+
+ ResourceId id;
+
+ if(ser.IsWriting() && rm)
+ id = GetResID(el);
+
+ DoSerialise(ser, id);
+
+ if(ser.IsReading())
+ {
+ el = VK_NULL_HANDLE;
+
+ if(id != ResourceId() && rm)
+ {
+ if(rm->HasLiveResource(id))
+ {
+ // we leave this wrapped.
+ el = rm->GetLiveHandle(id);
+ }
+ else if(!OptionalResourcesEnabled())
+ {
+ // It can be OK for a resource to have no live equivalent if the capture decided its not
+ // needed, which some APIs do fairly often.
+ RDCWARN("Capture may be missing reference to %s resource.", TypeName());
+ }
+ }
+ }
+}
+
+#undef SERIALISE_HANDLE
+#define SERIALISE_HANDLE(type) \
+ template \
+ void DoSerialise(SerialiserType &ser, type &el) \
+ { \
+ DoSerialiseViaResourceId(ser, el); \
+ } \
+ INSTANTIATE_SERIALISE_TYPE(type);
+
+SERIALISE_VK_HANDLES();
+
+template
+static void SerialiseNext(SerialiserType &ser, VkStructureType &sType, const void *&pNext)
+{
+ ser.Serialise("sType", sType);
+
+ if(ser.IsReading())
+ {
+ pNext = NULL;
+ }
+ else
+ {
+ if(pNext == NULL)
+ return;
+
+ VkGenericStruct *next = (VkGenericStruct *)pNext;
+
+ while(next)
+ {
+ // we can ignore this entirely, we don't need to serialise or replay it as we won't
+ // actually use external memory. Unwrapping, if necessary, happens elsewhere
+ if(next->sType == VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO_NV ||
+ next->sType == VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO_NV ||
+ next->sType == VK_STRUCTURE_TYPE_IMPORT_MEMORY_WIN32_HANDLE_INFO_NV ||
+ next->sType == VK_STRUCTURE_TYPE_EXPORT_MEMORY_WIN32_HANDLE_INFO_NV ||
+ next->sType == VK_STRUCTURE_TYPE_WIN32_KEYED_MUTEX_ACQUIRE_RELEASE_INFO_NV ||
+
+ next->sType == VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO_KHR ||
+ next->sType == VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO_KHR ||
+ next->sType == VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_BUFFER_CREATE_INFO_KHR ||
+ next->sType == VK_STRUCTURE_TYPE_IMPORT_MEMORY_WIN32_HANDLE_INFO_KHR ||
+ next->sType == VK_STRUCTURE_TYPE_EXPORT_MEMORY_WIN32_HANDLE_INFO_KHR ||
+ next->sType == VK_STRUCTURE_TYPE_IMPORT_MEMORY_FD_INFO_KHR ||
+ next->sType == VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_CREATE_INFO_KHR ||
+ next->sType == VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_WIN32_HANDLE_INFO_KHR)
+ {
+ // do nothing
+ }
+ // likewise we don't create real swapchains, so we can ignore surface counters
+ else if(next->sType == VK_STRUCTURE_TYPE_SWAPCHAIN_COUNTER_CREATE_INFO_EXT)
+ {
+ // do nothing
+ }
+ // for now we don't serialise dedicated memory on replay as it's only a performance hint,
+ // and is only required in conjunction with shared memory (which we don't replay). In future
+ // it might be helpful to serialise this for informational purposes.
+ else if(next->sType == VK_STRUCTURE_TYPE_DEDICATED_ALLOCATION_MEMORY_ALLOCATE_INFO_NV ||
+ next->sType == VK_STRUCTURE_TYPE_DEDICATED_ALLOCATION_IMAGE_CREATE_INFO_NV ||
+ next->sType == VK_STRUCTURE_TYPE_DEDICATED_ALLOCATION_BUFFER_CREATE_INFO_NV ||
+ next->sType == VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO_KHR)
+ {
+ // do nothing
+ }
+ else
+ {
+ RDCERR("Unrecognised extension structure type %d", next->sType);
+ }
+
+ next = (VkGenericStruct *)next->pNext;
+ }
+ }
+}
+
+template
+void DoSerialise(SerialiserType &ser, VkDeviceQueueCreateInfo &el)
+{
+ if(ser.IsWriting() && el.sType != VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO)
+ RDCWARN("sType not set properly: %u", el.sType);
+ SerialiseNext(ser, el.sType, el.pNext);
+
+ SERIALISE_MEMBER_TYPED(VkFlagWithNoBits, flags);
+ SERIALISE_MEMBER(queueFamilyIndex);
+ SERIALISE_MEMBER(queueCount);
+ SERIALISE_MEMBER_ARRAY(pQueuePriorities, queueCount);
+}
+
+// technically this doesn't need a serialise function as it's POD,
+// but we give it one just for ease of printing etc.
+template
+void DoSerialise(SerialiserType &ser, VkPhysicalDeviceFeatures &el)
+{
+ SERIALISE_MEMBER(robustBufferAccess);
+ SERIALISE_MEMBER(fullDrawIndexUint32);
+ SERIALISE_MEMBER(imageCubeArray);
+ SERIALISE_MEMBER(independentBlend);
+ SERIALISE_MEMBER(geometryShader);
+ SERIALISE_MEMBER(tessellationShader);
+ SERIALISE_MEMBER(sampleRateShading);
+ SERIALISE_MEMBER(dualSrcBlend);
+ SERIALISE_MEMBER(logicOp);
+ SERIALISE_MEMBER(multiDrawIndirect);
+ SERIALISE_MEMBER(drawIndirectFirstInstance);
+ SERIALISE_MEMBER(depthClamp);
+ SERIALISE_MEMBER(depthBiasClamp);
+ SERIALISE_MEMBER(fillModeNonSolid);
+ SERIALISE_MEMBER(depthBounds);
+ SERIALISE_MEMBER(wideLines);
+ SERIALISE_MEMBER(largePoints);
+ SERIALISE_MEMBER(alphaToOne);
+ SERIALISE_MEMBER(multiViewport);
+ SERIALISE_MEMBER(samplerAnisotropy);
+ SERIALISE_MEMBER(textureCompressionETC2);
+ SERIALISE_MEMBER(textureCompressionASTC_LDR);
+ SERIALISE_MEMBER(textureCompressionBC);
+ SERIALISE_MEMBER(occlusionQueryPrecise);
+ SERIALISE_MEMBER(pipelineStatisticsQuery);
+ SERIALISE_MEMBER(vertexPipelineStoresAndAtomics);
+ SERIALISE_MEMBER(fragmentStoresAndAtomics);
+ SERIALISE_MEMBER(shaderTessellationAndGeometryPointSize);
+ SERIALISE_MEMBER(shaderImageGatherExtended);
+ SERIALISE_MEMBER(shaderStorageImageExtendedFormats);
+ SERIALISE_MEMBER(shaderStorageImageMultisample);
+ SERIALISE_MEMBER(shaderStorageImageReadWithoutFormat);
+ SERIALISE_MEMBER(shaderStorageImageWriteWithoutFormat);
+ SERIALISE_MEMBER(shaderUniformBufferArrayDynamicIndexing);
+ SERIALISE_MEMBER(shaderSampledImageArrayDynamicIndexing);
+ SERIALISE_MEMBER(shaderStorageBufferArrayDynamicIndexing);
+ SERIALISE_MEMBER(shaderStorageImageArrayDynamicIndexing);
+ SERIALISE_MEMBER(shaderClipDistance);
+ SERIALISE_MEMBER(shaderCullDistance);
+ SERIALISE_MEMBER(shaderFloat64);
+ SERIALISE_MEMBER(shaderInt64);
+ SERIALISE_MEMBER(shaderInt16);
+ SERIALISE_MEMBER(shaderResourceResidency);
+ SERIALISE_MEMBER(shaderResourceMinLod);
+ SERIALISE_MEMBER(sparseBinding);
+ SERIALISE_MEMBER(sparseResidencyBuffer);
+ SERIALISE_MEMBER(sparseResidencyImage2D);
+ SERIALISE_MEMBER(sparseResidencyImage3D);
+ SERIALISE_MEMBER(sparseResidency2Samples);
+ SERIALISE_MEMBER(sparseResidency4Samples);
+ SERIALISE_MEMBER(sparseResidency8Samples);
+ SERIALISE_MEMBER(sparseResidency16Samples);
+ SERIALISE_MEMBER(sparseResidencyAliased);
+ SERIALISE_MEMBER(variableMultisampleRate);
+ SERIALISE_MEMBER(inheritedQueries);
+}
+
+template
+void DoSerialise(SerialiserType &ser, VkMemoryHeap &el)
+{
+ SERIALISE_MEMBER(size);
+ SERIALISE_MEMBER(flags);
+}
+
+template
+void DoSerialise(SerialiserType &ser, VkMemoryType &el)
+{
+ SERIALISE_MEMBER(propertyFlags);
+ SERIALISE_MEMBER(heapIndex);
+}
+
+template
+void DoSerialise(SerialiserType &ser, VkPhysicalDeviceMemoryProperties &el)
+{
+ SERIALISE_MEMBER(memoryTypeCount);
+ SERIALISE_MEMBER(memoryTypes);
+ SERIALISE_MEMBER(memoryHeapCount);
+ SERIALISE_MEMBER(memoryHeaps);
+}
+
+template
+void DoSerialise(SerialiserType &ser, VkPhysicalDeviceLimits &el)
+{
+ SERIALISE_MEMBER(maxImageDimension1D);
+ SERIALISE_MEMBER(maxImageDimension2D);
+ SERIALISE_MEMBER(maxImageDimension3D);
+ SERIALISE_MEMBER(maxImageDimensionCube);
+ SERIALISE_MEMBER(maxImageArrayLayers);
+ SERIALISE_MEMBER(maxTexelBufferElements);
+ SERIALISE_MEMBER(maxUniformBufferRange);
+ SERIALISE_MEMBER(maxStorageBufferRange);
+ SERIALISE_MEMBER(maxPushConstantsSize);
+ SERIALISE_MEMBER(maxMemoryAllocationCount);
+ SERIALISE_MEMBER(maxSamplerAllocationCount);
+ SERIALISE_MEMBER(bufferImageGranularity);
+ SERIALISE_MEMBER(sparseAddressSpaceSize);
+ SERIALISE_MEMBER(maxBoundDescriptorSets);
+ SERIALISE_MEMBER(maxPerStageDescriptorSamplers);
+ SERIALISE_MEMBER(maxPerStageDescriptorUniformBuffers);
+ SERIALISE_MEMBER(maxPerStageDescriptorStorageBuffers);
+ SERIALISE_MEMBER(maxPerStageDescriptorSampledImages);
+ SERIALISE_MEMBER(maxPerStageDescriptorStorageImages);
+ SERIALISE_MEMBER(maxPerStageDescriptorInputAttachments);
+ SERIALISE_MEMBER(maxPerStageResources);
+ SERIALISE_MEMBER(maxDescriptorSetSamplers);
+ SERIALISE_MEMBER(maxDescriptorSetUniformBuffers);
+ SERIALISE_MEMBER(maxDescriptorSetUniformBuffersDynamic);
+ SERIALISE_MEMBER(maxDescriptorSetStorageBuffers);
+ SERIALISE_MEMBER(maxDescriptorSetStorageBuffersDynamic);
+ SERIALISE_MEMBER(maxDescriptorSetSampledImages);
+ SERIALISE_MEMBER(maxDescriptorSetStorageImages);
+ SERIALISE_MEMBER(maxDescriptorSetInputAttachments);
+ SERIALISE_MEMBER(maxVertexInputAttributes);
+ SERIALISE_MEMBER(maxVertexInputBindings);
+ SERIALISE_MEMBER(maxVertexInputAttributeOffset);
+ SERIALISE_MEMBER(maxVertexInputBindingStride);
+ SERIALISE_MEMBER(maxVertexOutputComponents);
+ SERIALISE_MEMBER(maxTessellationGenerationLevel);
+ SERIALISE_MEMBER(maxTessellationPatchSize);
+ SERIALISE_MEMBER(maxTessellationControlPerVertexInputComponents);
+ SERIALISE_MEMBER(maxTessellationControlPerVertexOutputComponents);
+ SERIALISE_MEMBER(maxTessellationControlPerPatchOutputComponents);
+ SERIALISE_MEMBER(maxTessellationControlTotalOutputComponents);
+ SERIALISE_MEMBER(maxTessellationEvaluationInputComponents);
+ SERIALISE_MEMBER(maxTessellationEvaluationOutputComponents);
+ SERIALISE_MEMBER(maxGeometryShaderInvocations);
+ SERIALISE_MEMBER(maxGeometryInputComponents);
+ SERIALISE_MEMBER(maxGeometryOutputComponents);
+ SERIALISE_MEMBER(maxGeometryOutputVertices);
+ SERIALISE_MEMBER(maxGeometryTotalOutputComponents);
+ SERIALISE_MEMBER(maxFragmentInputComponents);
+ SERIALISE_MEMBER(maxFragmentOutputAttachments);
+ SERIALISE_MEMBER(maxFragmentDualSrcAttachments);
+ SERIALISE_MEMBER(maxFragmentCombinedOutputResources);
+ SERIALISE_MEMBER(maxComputeSharedMemorySize);
+ SERIALISE_MEMBER(maxComputeWorkGroupCount);
+ SERIALISE_MEMBER(maxComputeWorkGroupInvocations);
+ SERIALISE_MEMBER(maxComputeWorkGroupSize);
+ SERIALISE_MEMBER(subPixelPrecisionBits);
+ SERIALISE_MEMBER(subTexelPrecisionBits);
+ SERIALISE_MEMBER(mipmapPrecisionBits);
+ SERIALISE_MEMBER(maxDrawIndexedIndexValue);
+ SERIALISE_MEMBER(maxDrawIndirectCount);
+ SERIALISE_MEMBER(maxSamplerLodBias);
+ SERIALISE_MEMBER(maxSamplerAnisotropy);
+ SERIALISE_MEMBER(maxViewports);
+ SERIALISE_MEMBER(maxViewportDimensions);
+ SERIALISE_MEMBER(viewportBoundsRange);
+ SERIALISE_MEMBER(viewportSubPixelBits);
+
+ // don't serialise size_t, otherwise capture/replay between different bit-ness won't work
+ {
+ uint64_t minMemoryMapAlignment = (uint64_t)el.minMemoryMapAlignment;
+ ser.Serialise("minMemoryMapAlignment", minMemoryMapAlignment);
+ if(ser.IsReading())
+ el.minMemoryMapAlignment = (size_t)minMemoryMapAlignment;
+ }
+
+ SERIALISE_MEMBER(minTexelBufferOffsetAlignment);
+ SERIALISE_MEMBER(minUniformBufferOffsetAlignment);
+ SERIALISE_MEMBER(minStorageBufferOffsetAlignment);
+ SERIALISE_MEMBER(minTexelOffset);
+ SERIALISE_MEMBER(maxTexelOffset);
+ SERIALISE_MEMBER(minTexelGatherOffset);
+ SERIALISE_MEMBER(maxTexelGatherOffset);
+ SERIALISE_MEMBER(minInterpolationOffset);
+ SERIALISE_MEMBER(maxInterpolationOffset);
+ SERIALISE_MEMBER(subPixelInterpolationOffsetBits);
+ SERIALISE_MEMBER(maxFramebufferWidth);
+ SERIALISE_MEMBER(maxFramebufferHeight);
+ SERIALISE_MEMBER(maxFramebufferLayers);
+ SERIALISE_MEMBER(framebufferColorSampleCounts);
+ SERIALISE_MEMBER(framebufferDepthSampleCounts);
+ SERIALISE_MEMBER(framebufferStencilSampleCounts);
+ SERIALISE_MEMBER(framebufferNoAttachmentsSampleCounts);
+ SERIALISE_MEMBER(maxColorAttachments);
+ SERIALISE_MEMBER(sampledImageColorSampleCounts);
+ SERIALISE_MEMBER(sampledImageIntegerSampleCounts);
+ SERIALISE_MEMBER(sampledImageDepthSampleCounts);
+ SERIALISE_MEMBER(sampledImageStencilSampleCounts);
+ SERIALISE_MEMBER(storageImageSampleCounts);
+ SERIALISE_MEMBER(maxSampleMaskWords);
+ SERIALISE_MEMBER(timestampComputeAndGraphics);
+ SERIALISE_MEMBER(timestampPeriod);
+ SERIALISE_MEMBER(maxClipDistances);
+ SERIALISE_MEMBER(maxCullDistances);
+ SERIALISE_MEMBER(maxCombinedClipAndCullDistances);
+ SERIALISE_MEMBER(discreteQueuePriorities);
+ SERIALISE_MEMBER(pointSizeRange);
+ SERIALISE_MEMBER(lineWidthRange);
+ SERIALISE_MEMBER(pointSizeGranularity);
+ SERIALISE_MEMBER(lineWidthGranularity);
+ SERIALISE_MEMBER(strictLines);
+ SERIALISE_MEMBER(standardSampleLocations);
+ SERIALISE_MEMBER(optimalBufferCopyOffsetAlignment);
+ SERIALISE_MEMBER(optimalBufferCopyRowPitchAlignment);
+ SERIALISE_MEMBER(nonCoherentAtomSize);
+}
+
+template
+void DoSerialise(SerialiserType &ser, VkPhysicalDeviceSparseProperties &el)
+{
+ SERIALISE_MEMBER(residencyStandard2DBlockShape);
+ SERIALISE_MEMBER(residencyStandard2DMultisampleBlockShape);
+ SERIALISE_MEMBER(residencyStandard3DBlockShape);
+ SERIALISE_MEMBER(residencyAlignedMipSize);
+ SERIALISE_MEMBER(residencyNonResidentStrict);
+}
+
+template
+void DoSerialise(SerialiserType &ser, VkQueueFamilyProperties &el)
+{
+ SERIALISE_MEMBER(queueFlags);
+ SERIALISE_MEMBER(queueCount);
+ SERIALISE_MEMBER(timestampValidBits);
+ SERIALISE_MEMBER(minImageTransferGranularity);
+}
+
+template
+void DoSerialise(SerialiserType &ser, VkPhysicalDeviceProperties &el)
+{
+ SERIALISE_MEMBER(apiVersion);
+ SERIALISE_MEMBER(driverVersion);
+ SERIALISE_MEMBER(vendorID);
+ SERIALISE_MEMBER(deviceID);
+ SERIALISE_MEMBER(deviceType);
+ SERIALISE_MEMBER(deviceName);
+ SERIALISE_MEMBER(pipelineCacheUUID);
+ SERIALISE_MEMBER(limits);
+ SERIALISE_MEMBER(sparseProperties);
+}
+
+template
+void DoSerialise(SerialiserType &ser, VkDeviceCreateInfo &el)
+{
+ RDCASSERT(ser.IsReading() || el.sType == VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO);
+ SerialiseNext(ser, el.sType, el.pNext);
+
+ SERIALISE_MEMBER_TYPED(VkFlagWithNoBits, flags);
+ SERIALISE_MEMBER_ARRAY(pQueueCreateInfos, queueCreateInfoCount);
+ SERIALISE_MEMBER_ARRAY(ppEnabledExtensionNames, enabledExtensionCount);
+ SERIALISE_MEMBER_ARRAY(ppEnabledLayerNames, enabledLayerCount);
+ SERIALISE_MEMBER_OPT(pEnabledFeatures);
+}
+
+template <>
+void Deserialise(const VkDeviceCreateInfo &el)
+{
+ RDCASSERT(el.pNext == NULL); // otherwise delete
+ for(uint32_t i = 0; i < el.queueCreateInfoCount; i++)
+ delete[] el.pQueueCreateInfos[i].pQueuePriorities;
+ delete[] el.pQueueCreateInfos;
+ delete[] el.ppEnabledExtensionNames;
+ delete[] el.ppEnabledLayerNames;
+ delete el.pEnabledFeatures;
+}
+
+template
+void DoSerialise(SerialiserType &ser, VkBufferCreateInfo &el)
+{
+ RDCASSERT(ser.IsReading() || el.sType == VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO);
+ SerialiseNext(ser, el.sType, el.pNext);
+
+ SERIALISE_MEMBER_TYPED(VkBufferCreateFlagBits, flags);
+ SERIALISE_MEMBER(size);
+ SERIALISE_MEMBER_TYPED(VkBufferUsageFlagBits, usage);
+ SERIALISE_MEMBER(sharingMode);
+
+ // pQueueFamilyIndices should *only* be read if the sharing mode is concurrent
+ if(el.sharingMode == VK_SHARING_MODE_CONCURRENT)
+ {
+ SERIALISE_MEMBER_ARRAY(pQueueFamilyIndices, queueFamilyIndexCount);
+ }
+ else if(ser.IsReading())
+ {
+ // otherwise just set to NULL for sanity
+ el.pQueueFamilyIndices = NULL;
+ el.queueFamilyIndexCount = 0;
+ }
+}
+
+template <>
+void Deserialise(const VkBufferCreateInfo &el)
+{
+ RDCASSERT(el.pNext == NULL); // otherwise delete
+ delete[] el.pQueueFamilyIndices;
+}
+
+template
+void DoSerialise(SerialiserType &ser, VkBufferViewCreateInfo &el)
+{
+ RDCASSERT(ser.IsReading() || el.sType == VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO);
+ SerialiseNext(ser, el.sType, el.pNext);
+
+ SERIALISE_MEMBER_TYPED(VkFlagWithNoBits, flags);
+ SERIALISE_MEMBER(buffer);
+ SERIALISE_MEMBER(format);
+ SERIALISE_MEMBER(offset);
+ SERIALISE_MEMBER(range);
+}
+
+template
+void DoSerialise(SerialiserType &ser, VkImageCreateInfo &el)
+{
+ RDCASSERT(ser.IsReading() || el.sType == VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO);
+ SerialiseNext(ser, el.sType, el.pNext);
+
+ SERIALISE_MEMBER_TYPED(VkImageCreateFlagBits, flags);
+ SERIALISE_MEMBER(imageType);
+ SERIALISE_MEMBER(format);
+ SERIALISE_MEMBER(extent);
+ SERIALISE_MEMBER(mipLevels);
+ SERIALISE_MEMBER(arrayLayers);
+ SERIALISE_MEMBER(samples);
+ SERIALISE_MEMBER(tiling);
+ SERIALISE_MEMBER_TYPED(VkImageUsageFlagBits, usage);
+ SERIALISE_MEMBER(sharingMode);
+ SERIALISE_MEMBER(initialLayout);
+
+ // pQueueFamilyIndices should *only* be read if the sharing mode is concurrent
+ if(el.sharingMode == VK_SHARING_MODE_CONCURRENT)
+ {
+ SERIALISE_MEMBER_ARRAY(pQueueFamilyIndices, queueFamilyIndexCount);
+ }
+ else if(ser.IsReading())
+ {
+ // otherwise just set to NULL for sanity
+ el.pQueueFamilyIndices = NULL;
+ el.queueFamilyIndexCount = 0;
+ }
+}
+
+template <>
+void Deserialise(const VkImageCreateInfo &el)
+{
+ RDCASSERT(el.pNext == NULL); // otherwise delete
+ delete[] el.pQueueFamilyIndices;
+}
+
+template
+void DoSerialise(SerialiserType &ser, VkImageViewCreateInfo &el)
+{
+ RDCASSERT(ser.IsReading() || el.sType == VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO);
+ SerialiseNext(ser, el.sType, el.pNext);
+
+ SERIALISE_MEMBER_TYPED(VkFlagWithNoBits, flags);
+ SERIALISE_MEMBER(image);
+ SERIALISE_MEMBER(viewType);
+ SERIALISE_MEMBER(format);
+ SERIALISE_MEMBER(components);
+ SERIALISE_MEMBER(subresourceRange);
+}
+
+template
+void DoSerialise(SerialiserType &ser, VkSparseMemoryBind &el)
+{
+ SERIALISE_MEMBER(resourceOffset);
+ SERIALISE_MEMBER(size);
+ SERIALISE_MEMBER(memory);
+ SERIALISE_MEMBER(memoryOffset);
+ SERIALISE_MEMBER_TYPED(VkSparseMemoryBindFlagBits, flags);
+}
+
+template
+void DoSerialise(SerialiserType &ser, VkSparseBufferMemoryBindInfo &el)
+{
+ SERIALISE_MEMBER(buffer);
+ SERIALISE_MEMBER_ARRAY(pBinds, bindCount);
+}
+
+template
+void DoSerialise(SerialiserType &ser, VkSparseImageOpaqueMemoryBindInfo &el)
+{
+ SERIALISE_MEMBER(image);
+ SERIALISE_MEMBER_ARRAY(pBinds, bindCount);
+}
+
+template
+void DoSerialise(SerialiserType &ser, VkSparseImageMemoryBind &el)
+{
+ SERIALISE_MEMBER(subresource);
+ SERIALISE_MEMBER(offset);
+ SERIALISE_MEMBER(extent);
+ SERIALISE_MEMBER(memory);
+ SERIALISE_MEMBER(memoryOffset);
+ SERIALISE_MEMBER_TYPED(VkSparseMemoryBindFlagBits, flags);
+}
+
+template
+void DoSerialise(SerialiserType &ser, VkSparseImageMemoryBindInfo &el)
+{
+ SERIALISE_MEMBER(image);
+ SERIALISE_MEMBER_ARRAY(pBinds, bindCount);
+}
+
+template
+void DoSerialise(SerialiserType &ser, VkBindSparseInfo &el)
+{
+ RDCASSERT(ser.IsReading() || el.sType == VK_STRUCTURE_TYPE_BIND_SPARSE_INFO);
+ SerialiseNext(ser, el.sType, el.pNext);
+
+ SERIALISE_MEMBER_ARRAY(pWaitSemaphores, waitSemaphoreCount);
+
+ SERIALISE_MEMBER_ARRAY(pBufferBinds, bufferBindCount);
+ SERIALISE_MEMBER_ARRAY(pImageOpaqueBinds, imageOpaqueBindCount);
+ SERIALISE_MEMBER_ARRAY(pImageBinds, imageBindCount);
+
+ SERIALISE_MEMBER_ARRAY(pSignalSemaphores, signalSemaphoreCount);
+}
+
+template <>
+void Deserialise(const VkBindSparseInfo &el)
+{
+ RDCASSERT(el.pNext == NULL); // otherwise delete
+ delete[] el.pWaitSemaphores;
+ for(uint32_t i = 0; i < el.bufferBindCount; i++)
+ delete[] el.pBufferBinds[i].pBinds;
+ delete[] el.pBufferBinds;
+ for(uint32_t i = 0; i < el.imageOpaqueBindCount; i++)
+ delete[] el.pImageOpaqueBinds[i].pBinds;
+ delete[] el.pImageOpaqueBinds;
+ for(uint32_t i = 0; i < el.imageBindCount; i++)
+ delete[] el.pImageBinds[i].pBinds;
+ delete[] el.pImageBinds;
+ delete[] el.pSignalSemaphores;
+}
+
+template
+void DoSerialise(SerialiserType &ser, VkSubmitInfo &el)
+{
+ RDCASSERT(ser.IsReading() || el.sType == VK_STRUCTURE_TYPE_SUBMIT_INFO);
+ SerialiseNext(ser, el.sType, el.pNext);
+
+ // bit of a hack, we alias the ptr here to the bits type so we serialise with better type info
+ union
+ {
+ const VkPipelineStageFlagBits **typed;
+ const VkPipelineStageFlags **orig;
+ } u;
+ u.orig = &el.pWaitDstStageMask;
+
+ ser.Serialise("pWaitDstStageMask", *u.typed, el.waitSemaphoreCount,
+ SerialiserFlags::AllocateMemory);
+ SERIALISE_MEMBER_ARRAY(pWaitSemaphores, waitSemaphoreCount);
+ SERIALISE_MEMBER_ARRAY(pCommandBuffers, commandBufferCount);
+ SERIALISE_MEMBER_ARRAY(pSignalSemaphores, signalSemaphoreCount);
+}
+
+template <>
+void Deserialise(const VkSubmitInfo &el)
+{
+ RDCASSERT(el.pNext == NULL); // otherwise delete
+ delete[] el.pWaitSemaphores;
+ delete[] el.pCommandBuffers;
+ delete[] el.pSignalSemaphores;
+}
+
+template
+void DoSerialise(SerialiserType &ser, VkFramebufferCreateInfo &el)
+{
+ RDCASSERT(ser.IsReading() || el.sType == VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO);
+ SerialiseNext(ser, el.sType, el.pNext);
+
+ SERIALISE_MEMBER_TYPED(VkFlagWithNoBits, flags);
+ SERIALISE_MEMBER(renderPass);
+ SERIALISE_MEMBER(width);
+ SERIALISE_MEMBER(height);
+ SERIALISE_MEMBER(layers);
+ SERIALISE_MEMBER_ARRAY(pAttachments, attachmentCount);
+}
+
+template <>
+void Deserialise(const VkFramebufferCreateInfo &el)
+{
+ RDCASSERT(el.pNext == NULL); // otherwise delete
+ delete[] el.pAttachments;
+}
+
+template
+void DoSerialise(SerialiserType &ser, VkAttachmentDescription &el)
+{
+ SERIALISE_MEMBER_TYPED(VkAttachmentDescriptionFlagBits, flags);
+ SERIALISE_MEMBER(format);
+ SERIALISE_MEMBER(samples);
+ SERIALISE_MEMBER(loadOp);
+ SERIALISE_MEMBER(storeOp);
+ SERIALISE_MEMBER(stencilLoadOp);
+ SERIALISE_MEMBER(stencilStoreOp);
+ SERIALISE_MEMBER(initialLayout);
+ SERIALISE_MEMBER(finalLayout);
+}
+
+template
+void DoSerialise(SerialiserType &ser, VkSubpassDescription &el)
+{
+ SERIALISE_MEMBER_TYPED(VkFlagWithNoBits, flags);
+ SERIALISE_MEMBER(pipelineBindPoint);
+ SERIALISE_MEMBER_OPT(pDepthStencilAttachment);
+ SERIALISE_MEMBER_ARRAY(pInputAttachments, inputAttachmentCount);
+ SERIALISE_MEMBER_ARRAY(pResolveAttachments, colorAttachmentCount);
+ SERIALISE_MEMBER_ARRAY(pColorAttachments, colorAttachmentCount);
+ SERIALISE_MEMBER_ARRAY(pPreserveAttachments, preserveAttachmentCount);
+}
+
+template
+void DoSerialise(SerialiserType &ser, VkSubpassDependency &el)
+{
+ SERIALISE_MEMBER(srcSubpass);
+ SERIALISE_MEMBER(dstSubpass);
+ SERIALISE_MEMBER_TYPED(VkPipelineStageFlagBits, srcStageMask);
+ SERIALISE_MEMBER_TYPED(VkPipelineStageFlagBits, dstStageMask);
+ SERIALISE_MEMBER_TYPED(VkAccessFlagBits, srcAccessMask);
+ SERIALISE_MEMBER_TYPED(VkAccessFlagBits, dstAccessMask);
+ SERIALISE_MEMBER_TYPED(VkDependencyFlagBits, dependencyFlags);
+}
+
+template
+void DoSerialise(SerialiserType &ser, VkAttachmentReference &el)
+{
+ SERIALISE_MEMBER(attachment);
+ SERIALISE_MEMBER(layout);
+}
+
+template
+void DoSerialise(SerialiserType &ser, VkRenderPassCreateInfo &el)
+{
+ RDCASSERT(ser.IsReading() || el.sType == VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO);
+ SerialiseNext(ser, el.sType, el.pNext);
+
+ SERIALISE_MEMBER_TYPED(VkFlagWithNoBits, flags);
+ SERIALISE_MEMBER_ARRAY(pAttachments, attachmentCount);
+ SERIALISE_MEMBER_ARRAY(pSubpasses, subpassCount);
+ SERIALISE_MEMBER_ARRAY(pDependencies, dependencyCount);
+}
+
+template <>
+void Deserialise(const VkRenderPassCreateInfo &el)
+{
+ RDCASSERT(el.pNext == NULL); // otherwise delete
+ delete[] el.pAttachments;
+ for(uint32_t i = 0; i < el.subpassCount; i++)
+ {
+ delete el.pSubpasses[i].pDepthStencilAttachment;
+ delete[] el.pSubpasses[i].pInputAttachments;
+ delete[] el.pSubpasses[i].pColorAttachments;
+ delete[] el.pSubpasses[i].pResolveAttachments;
+ if(el.pSubpasses[i].pPreserveAttachments)
+ delete[] el.pSubpasses[i].pPreserveAttachments;
+ }
+ delete[] el.pSubpasses;
+ delete[] el.pDependencies;
+}
+
+template
+void DoSerialise(SerialiserType &ser, VkRenderPassBeginInfo &el)
+{
+ RDCASSERT(ser.IsReading() || el.sType == VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO);
+ SerialiseNext(ser, el.sType, el.pNext);
+
+ SERIALISE_MEMBER(renderPass);
+ SERIALISE_MEMBER(framebuffer);
+ SERIALISE_MEMBER(renderArea);
+ SERIALISE_MEMBER_ARRAY(pClearValues, clearValueCount);
+}
+
+template <>
+void Deserialise(const VkRenderPassBeginInfo &el)
+{
+ RDCASSERT(el.pNext == NULL); // otherwise delete
+ delete[] el.pClearValues;
+}
+
+template
+void DoSerialise(SerialiserType &ser, VkVertexInputBindingDescription &el)
+{
+ SERIALISE_MEMBER(binding);
+ SERIALISE_MEMBER(stride);
+ SERIALISE_MEMBER(inputRate);
+}
+
+template
+void DoSerialise(SerialiserType &ser, VkVertexInputAttributeDescription &el)
+{
+ SERIALISE_MEMBER(location);
+ SERIALISE_MEMBER(binding);
+ SERIALISE_MEMBER(format);
+ SERIALISE_MEMBER(offset);
+}
+
+template
+void DoSerialise(SerialiserType &ser, VkPipelineVertexInputStateCreateInfo &el)
+{
+ RDCASSERT(ser.IsReading() || el.sType == VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO);
+ SerialiseNext(ser, el.sType, el.pNext);
+
+ SERIALISE_MEMBER_TYPED(VkFlagWithNoBits, flags);
+ SERIALISE_MEMBER_ARRAY(pVertexBindingDescriptions, vertexBindingDescriptionCount);
+ SERIALISE_MEMBER_ARRAY(pVertexAttributeDescriptions, vertexAttributeDescriptionCount);
+}
+
+template
+void DoSerialise(SerialiserType &ser, VkPipelineInputAssemblyStateCreateInfo &el)
+{
+ RDCASSERT(ser.IsReading() ||
+ el.sType == VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO);
+ SerialiseNext(ser, el.sType, el.pNext);
+
+ SERIALISE_MEMBER_TYPED(VkFlagWithNoBits, flags);
+ SERIALISE_MEMBER(topology);
+ SERIALISE_MEMBER(primitiveRestartEnable);
+}
+
+template
+void DoSerialise(SerialiserType &ser, VkPipelineTessellationStateCreateInfo &el)
+{
+ RDCASSERT(ser.IsReading() || el.sType == VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO);
+ SerialiseNext(ser, el.sType, el.pNext);
+
+ SERIALISE_MEMBER_TYPED(VkFlagWithNoBits, flags);
+ SERIALISE_MEMBER(patchControlPoints);
+}
+
+template
+void DoSerialise(SerialiserType &ser, VkPipelineViewportStateCreateInfo &el)
+{
+ RDCASSERT(ser.IsReading() || el.sType == VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO);
+ SerialiseNext(ser, el.sType, el.pNext);
+
+ SERIALISE_MEMBER_TYPED(VkFlagWithNoBits, flags);
+
+ SERIALISE_MEMBER_ARRAY(pViewports, viewportCount);
+ SERIALISE_MEMBER_ARRAY(pScissors, scissorCount);
+
+ // need to handle these arrays potentially being NULL if they're dynamic, we still want the count
+ SERIALISE_MEMBER(viewportCount);
+ SERIALISE_MEMBER(scissorCount);
+}
+
+template
+void DoSerialise(SerialiserType &ser, VkPipelineRasterizationStateCreateInfo &el)
+{
+ RDCASSERT(ser.IsReading() ||
+ el.sType == VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO);
+ SerialiseNext(ser, el.sType, el.pNext);
+
+ SERIALISE_MEMBER_TYPED(VkFlagWithNoBits, flags);
+ SERIALISE_MEMBER(depthClampEnable);
+ SERIALISE_MEMBER(rasterizerDiscardEnable);
+ SERIALISE_MEMBER(polygonMode);
+ SERIALISE_MEMBER(cullMode);
+ SERIALISE_MEMBER(frontFace);
+ SERIALISE_MEMBER(depthBiasEnable);
+ SERIALISE_MEMBER(depthBiasConstantFactor);
+ SERIALISE_MEMBER(depthBiasClamp);
+ SERIALISE_MEMBER(depthBiasSlopeFactor);
+ SERIALISE_MEMBER(lineWidth);
+}
+
+template
+void DoSerialise(SerialiserType &ser, VkPipelineMultisampleStateCreateInfo &el)
+{
+ RDCASSERT(ser.IsReading() || el.sType == VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO);
+ SerialiseNext(ser, el.sType, el.pNext);
+
+ SERIALISE_MEMBER_TYPED(VkFlagWithNoBits, flags);
+ SERIALISE_MEMBER(rasterizationSamples);
+ RDCASSERT(el.rasterizationSamples <= VK_SAMPLE_COUNT_32_BIT);
+ SERIALISE_MEMBER(sampleShadingEnable);
+ SERIALISE_MEMBER(minSampleShading);
+ SERIALISE_MEMBER_OPT(pSampleMask);
+ SERIALISE_MEMBER(alphaToCoverageEnable);
+ SERIALISE_MEMBER(alphaToOneEnable);
+}
+
+template
+void DoSerialise(SerialiserType &ser, VkPipelineColorBlendAttachmentState &el)
+{
+ SERIALISE_MEMBER(blendEnable);
+ SERIALISE_MEMBER(srcColorBlendFactor);
+ SERIALISE_MEMBER(dstColorBlendFactor);
+ SERIALISE_MEMBER(colorBlendOp);
+ SERIALISE_MEMBER(srcAlphaBlendFactor);
+ SERIALISE_MEMBER(dstAlphaBlendFactor);
+ SERIALISE_MEMBER(alphaBlendOp);
+ SERIALISE_MEMBER(colorWriteMask);
+}
+
+template
+void DoSerialise(SerialiserType &ser, VkPipelineColorBlendStateCreateInfo &el)
+{
+ RDCASSERT(ser.IsReading() || el.sType == VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO);
+ SerialiseNext(ser, el.sType, el.pNext);
+
+ SERIALISE_MEMBER_TYPED(VkFlagWithNoBits, flags);
+ SERIALISE_MEMBER(logicOpEnable);
+ SERIALISE_MEMBER(logicOp);
+ SERIALISE_MEMBER_ARRAY(pAttachments, attachmentCount);
+ SERIALISE_MEMBER(blendConstants);
+}
+
+template
+void DoSerialise(SerialiserType &ser, VkPipelineDepthStencilStateCreateInfo &el)
+{
+ RDCASSERT(ser.IsReading() ||
+ el.sType == VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO);
+ SerialiseNext(ser, el.sType, el.pNext);
+
+ SERIALISE_MEMBER_TYPED(VkFlagWithNoBits, flags);
+ SERIALISE_MEMBER(depthTestEnable);
+ SERIALISE_MEMBER(depthWriteEnable);
+ SERIALISE_MEMBER(depthCompareOp);
+ SERIALISE_MEMBER(depthBoundsTestEnable);
+ SERIALISE_MEMBER(stencilTestEnable);
+ SERIALISE_MEMBER(front);
+ SERIALISE_MEMBER(back);
+ SERIALISE_MEMBER(minDepthBounds);
+ SERIALISE_MEMBER(maxDepthBounds);
+}
+
+template
+void DoSerialise(SerialiserType &ser, VkPipelineDynamicStateCreateInfo &el)
+{
+ RDCASSERT(ser.IsReading() || el.sType == VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO);
+ SerialiseNext(ser, el.sType, el.pNext);
+
+ SERIALISE_MEMBER_TYPED(VkFlagWithNoBits, flags);
+ SERIALISE_MEMBER_ARRAY(pDynamicStates, dynamicStateCount);
+}
+
+template
+void DoSerialise(SerialiserType &ser, VkCommandPoolCreateInfo &el)
+{
+ RDCASSERT(ser.IsReading() || el.sType == VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO);
+ SerialiseNext(ser, el.sType, el.pNext);
+
+ SERIALISE_MEMBER_TYPED(VkCommandPoolCreateFlagBits, flags);
+ SERIALISE_MEMBER(queueFamilyIndex);
+}
+
+template
+void DoSerialise(SerialiserType &ser, VkCommandBufferAllocateInfo &el)
+{
+ RDCASSERT(ser.IsReading() || el.sType == VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO);
+ SerialiseNext(ser, el.sType, el.pNext);
+
+ SERIALISE_MEMBER(commandPool);
+ SERIALISE_MEMBER(level);
+ SERIALISE_MEMBER(commandBufferCount);
+}
+
+template
+void DoSerialise(SerialiserType &ser, VkCommandBufferInheritanceInfo &el)
+{
+ RDCASSERT(ser.IsReading() || el.sType == VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO);
+ SerialiseNext(ser, el.sType, el.pNext);
+
+ SERIALISE_MEMBER(renderPass);
+ SERIALISE_MEMBER(subpass);
+ SERIALISE_MEMBER(framebuffer);
+ SERIALISE_MEMBER(occlusionQueryEnable);
+ SERIALISE_MEMBER_TYPED(VkQueryControlFlagBits, queryFlags);
+ SERIALISE_MEMBER_TYPED(VkQueryPipelineStatisticFlagBits, pipelineStatistics);
+}
+
+template
+void DoSerialise(SerialiserType &ser, VkCommandBufferBeginInfo &el)
+{
+ RDCASSERT(ser.IsReading() || el.sType == VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO);
+ SerialiseNext(ser, el.sType, el.pNext);
+
+ SERIALISE_MEMBER_TYPED(VkCommandBufferUsageFlagBits, flags);
+ SERIALISE_MEMBER_OPT(pInheritanceInfo);
+}
+
+template <>
+void Deserialise(const VkCommandBufferBeginInfo &el)
+{
+ RDCASSERT(el.pNext == NULL); // otherwise delete
+ delete el.pInheritanceInfo;
+}
+
+template
+void DoSerialise(SerialiserType &ser, VkStencilOpState &el)
+{
+ SERIALISE_MEMBER(failOp);
+ SERIALISE_MEMBER(passOp);
+ SERIALISE_MEMBER(depthFailOp);
+ SERIALISE_MEMBER(compareOp);
+ SERIALISE_MEMBER(compareMask);
+ SERIALISE_MEMBER(writeMask);
+ SERIALISE_MEMBER(reference);
+}
+
+template
+void DoSerialise(SerialiserType &ser, VkQueryPoolCreateInfo &el)
+{
+ RDCASSERT(ser.IsReading() || el.sType == VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO);
+ SerialiseNext(ser, el.sType, el.pNext);
+
+ SERIALISE_MEMBER_TYPED(VkFlagWithNoBits, flags);
+ SERIALISE_MEMBER(queryType);
+ SERIALISE_MEMBER(queryCount);
+ SERIALISE_MEMBER_TYPED(VkQueryPipelineStatisticFlagBits, pipelineStatistics);
+}
+
+template
+void DoSerialise(SerialiserType &ser, VkSemaphoreCreateInfo &el)
+{
+ RDCASSERT(ser.IsReading() || el.sType == VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO);
+ SerialiseNext(ser, el.sType, el.pNext);
+
+ SERIALISE_MEMBER_TYPED(VkFlagWithNoBits, flags);
+}
+
+template
+void DoSerialise(SerialiserType &ser, VkEventCreateInfo &el)
+{
+ RDCASSERT(ser.IsReading() || el.sType == VK_STRUCTURE_TYPE_EVENT_CREATE_INFO);
+ SerialiseNext(ser, el.sType, el.pNext);
+
+ SERIALISE_MEMBER_TYPED(VkFlagWithNoBits, flags);
+}
+
+template
+void DoSerialise(SerialiserType &ser, VkFenceCreateInfo &el)
+{
+ RDCASSERT(ser.IsReading() || el.sType == VK_STRUCTURE_TYPE_FENCE_CREATE_INFO);
+ SerialiseNext(ser, el.sType, el.pNext);
+
+ SERIALISE_MEMBER_TYPED(VkFenceCreateFlagBits, flags);
+}
+
+template
+void DoSerialise(SerialiserType &ser, VkSamplerCreateInfo &el)
+{
+ RDCASSERT(ser.IsReading() || el.sType == VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO);
+ SerialiseNext(ser, el.sType, el.pNext);
+
+ SERIALISE_MEMBER_TYPED(VkFlagWithNoBits, flags);
+ SERIALISE_MEMBER(minFilter);
+ SERIALISE_MEMBER(magFilter);
+ SERIALISE_MEMBER(mipmapMode);
+ SERIALISE_MEMBER(addressModeU);
+ SERIALISE_MEMBER(addressModeV);
+ SERIALISE_MEMBER(addressModeW);
+ SERIALISE_MEMBER(mipLodBias);
+ SERIALISE_MEMBER(anisotropyEnable);
+ SERIALISE_MEMBER(maxAnisotropy);
+ SERIALISE_MEMBER(compareEnable);
+ SERIALISE_MEMBER(compareOp);
+ SERIALISE_MEMBER(minLod);
+ SERIALISE_MEMBER(maxLod);
+ SERIALISE_MEMBER(borderColor);
+ SERIALISE_MEMBER(unnormalizedCoordinates);
+}
+
+template
+void DoSerialise(SerialiserType &ser, VkPipelineShaderStageCreateInfo &el)
+{
+ RDCASSERT(ser.IsReading() || el.sType == VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO);
+ SerialiseNext(ser, el.sType, el.pNext);
+
+ SERIALISE_MEMBER_TYPED(VkFlagWithNoBits, flags);
+ SERIALISE_MEMBER(stage);
+ SERIALISE_MEMBER(module);
+ SERIALISE_MEMBER(pName);
+ SERIALISE_MEMBER_OPT(pSpecializationInfo);
+}
+
+template
+void DoSerialise(SerialiserType &ser, VkSpecializationMapEntry &el)
+{
+ SERIALISE_MEMBER(constantID);
+ SERIALISE_MEMBER(offset);
+ SERIALISE_MEMBER(constantID);
+
+ // don't serialise size_t, otherwise capture/replay between different bit-ness won't work
+ {
+ uint64_t size = el.size;
+ ser.Serialise("size", size);
+ if(ser.IsReading())
+ el.size = (size_t)size;
+ }
+}
+
+template
+void DoSerialise(SerialiserType &ser, VkSpecializationInfo &el)
+{
+ SERIALISE_MEMBER_ARRAY(pData, dataSize);
+ SERIALISE_MEMBER_ARRAY(pMapEntries, mapEntryCount);
+}
+
+template
+void DoSerialise(SerialiserType &ser, VkPipelineCacheCreateInfo &el)
+{
+ RDCASSERT(ser.IsReading() || el.sType == VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO);
+ SerialiseNext(ser, el.sType, el.pNext);
+
+ SERIALISE_MEMBER_TYPED(VkFlagWithNoBits, flags);
+
+ // don't serialise size_t, otherwise capture/replay between different bit-ness won't work
+ {
+ uint64_t initialDataSize = el.initialDataSize;
+ ser.Serialise("initialDataSize", initialDataSize);
+ if(ser.IsReading())
+ el.initialDataSize = (size_t)initialDataSize;
+ }
+
+ SERIALISE_MEMBER_ARRAY(pInitialData, initialDataSize);
+}
+
+template <>
+void Deserialise(const VkPipelineCacheCreateInfo &el)
+{
+ RDCASSERT(el.pNext == NULL); // otherwise delete
+ FreeAlignedBuffer((byte *)el.pInitialData);
+}
+
+template
+void DoSerialise(SerialiserType &ser, VkPipelineLayoutCreateInfo &el)
+{
+ RDCASSERT(ser.IsReading() || el.sType == VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO);
+ SerialiseNext(ser, el.sType, el.pNext);
+
+ SERIALISE_MEMBER_TYPED(VkFlagWithNoBits, flags);
+ SERIALISE_MEMBER_ARRAY(pSetLayouts, setLayoutCount);
+ SERIALISE_MEMBER_ARRAY(pPushConstantRanges, pushConstantRangeCount);
+}
+
+template <>
+void Deserialise(const VkPipelineLayoutCreateInfo &el)
+{
+ RDCASSERT(el.pNext == NULL); // otherwise delete
+ delete[] el.pSetLayouts;
+ delete[] el.pPushConstantRanges;
+}
+
+template
+void DoSerialise(SerialiserType &ser, VkShaderModuleCreateInfo &el)
+{
+ RDCASSERT(ser.IsReading() || el.sType == VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO);
+ SerialiseNext(ser, el.sType, el.pNext);
+
+ SERIALISE_MEMBER_TYPED(VkFlagWithNoBits, flags);
+
+ // serialise as void* so it goes through as a buffer, not an actual array of integers.
+ {
+ const void *pCode = el.pCode;
+ ser.Serialise("pCode", pCode, el.codeSize, SerialiserFlags::AllocateMemory);
+ if(ser.IsReading())
+ el.pCode = (uint32_t *)pCode;
+ }
+}
+
+template <>
+void Deserialise(const VkShaderModuleCreateInfo &el)
+{
+ RDCASSERT(el.pNext == NULL); // otherwise delete
+ FreeAlignedBuffer((byte *)el.pCode);
+}
+
+template
+void DoSerialise(SerialiserType &ser, VkImageSubresourceRange &el)
+{
+ SERIALISE_MEMBER_TYPED(VkImageAspectFlagBits, aspectMask);
+ SERIALISE_MEMBER(baseMipLevel);
+ SERIALISE_MEMBER(levelCount);
+ SERIALISE_MEMBER(baseArrayLayer);
+ SERIALISE_MEMBER(layerCount);
+}
+
+template
+void DoSerialise(SerialiserType &ser, VkImageSubresourceLayers &el)
+{
+ SERIALISE_MEMBER_TYPED(VkImageAspectFlagBits, aspectMask);
+ SERIALISE_MEMBER(mipLevel);
+ SERIALISE_MEMBER(baseArrayLayer);
+ SERIALISE_MEMBER(layerCount);
+}
+
+template
+void DoSerialise(SerialiserType &ser, VkImageSubresource &el)
+{
+ SERIALISE_MEMBER_TYPED(VkImageAspectFlagBits, aspectMask);
+ SERIALISE_MEMBER(mipLevel);
+ SERIALISE_MEMBER(arrayLayer);
+}
+
+template
+void DoSerialise(SerialiserType &ser, VkMemoryAllocateInfo &el)
+{
+ RDCASSERT(ser.IsReading() || el.sType == VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO);
+ SerialiseNext(ser, el.sType, el.pNext);
+
+ SERIALISE_MEMBER(allocationSize);
+ SERIALISE_MEMBER(memoryTypeIndex);
+}
+
+template
+void DoSerialise(SerialiserType &ser, VkMemoryBarrier &el)
+{
+ RDCASSERT(ser.IsReading() || el.sType == VK_STRUCTURE_TYPE_MEMORY_BARRIER);
+ SerialiseNext(ser, el.sType, el.pNext);
+
+ SERIALISE_MEMBER_TYPED(VkAccessFlagBits, srcAccessMask);
+ SERIALISE_MEMBER_TYPED(VkAccessFlagBits, dstAccessMask);
+}
+
+template
+void DoSerialise(SerialiserType &ser, VkBufferMemoryBarrier &el)
+{
+ RDCASSERT(ser.IsReading() || el.sType == VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER);
+ SerialiseNext(ser, el.sType, el.pNext);
+
+ SERIALISE_MEMBER_TYPED(VkAccessFlagBits, srcAccessMask);
+ SERIALISE_MEMBER_TYPED(VkAccessFlagBits, dstAccessMask);
+ // serialise as signed because then QUEUE_FAMILY_IGNORED is -1 and queue
+ // family index won't be legitimately larger than 2 billion
+ SERIALISE_MEMBER_TYPED(int32_t, srcQueueFamilyIndex);
+ SERIALISE_MEMBER_TYPED(int32_t, dstQueueFamilyIndex);
+ SERIALISE_MEMBER(buffer);
+ SERIALISE_MEMBER(offset);
+ SERIALISE_MEMBER(size);
+}
+
+template
+void DoSerialise(SerialiserType &ser, VkImageMemoryBarrier &el)
+{
+ RDCASSERT(ser.IsReading() || el.sType == VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER);
+ SerialiseNext(ser, el.sType, el.pNext);
+
+ SERIALISE_MEMBER_TYPED(VkAccessFlagBits, srcAccessMask);
+ SERIALISE_MEMBER_TYPED(VkAccessFlagBits, dstAccessMask);
+ SERIALISE_MEMBER(oldLayout);
+ SERIALISE_MEMBER(newLayout);
+ // serialise as signed because then QUEUE_FAMILY_IGNORED is -1 and queue
+ // family index won't be legitimately larger than 2 billion
+ SERIALISE_MEMBER_TYPED(int32_t, srcQueueFamilyIndex);
+ SERIALISE_MEMBER_TYPED(int32_t, dstQueueFamilyIndex);
+ SERIALISE_MEMBER(image);
+ SERIALISE_MEMBER(subresourceRange);
+}
+
+template
+void DoSerialise(SerialiserType &ser, VkGraphicsPipelineCreateInfo &el)
+{
+ RDCASSERT(ser.IsReading() || el.sType == VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO);
+ SerialiseNext(ser, el.sType, el.pNext);
+
+ SERIALISE_MEMBER_TYPED(VkPipelineCreateFlagBits, flags);
+ SERIALISE_MEMBER(layout);
+ SERIALISE_MEMBER(renderPass);
+ SERIALISE_MEMBER(subpass);
+ SERIALISE_MEMBER(basePipelineHandle);
+ SERIALISE_MEMBER(basePipelineIndex);
+
+ SERIALISE_MEMBER_OPT(pVertexInputState);
+ SERIALISE_MEMBER_OPT(pInputAssemblyState);
+ SERIALISE_MEMBER_OPT(pTessellationState);
+ SERIALISE_MEMBER_OPT(pViewportState);
+ SERIALISE_MEMBER_OPT(pRasterizationState);
+ SERIALISE_MEMBER_OPT(pMultisampleState);
+ SERIALISE_MEMBER_OPT(pDepthStencilState);
+ SERIALISE_MEMBER_OPT(pColorBlendState);
+ SERIALISE_MEMBER_OPT(pDynamicState);
+ SERIALISE_MEMBER_ARRAY(pStages, stageCount);
+}
+
+template <>
+void Deserialise(const VkGraphicsPipelineCreateInfo &el)
+{
+ RDCASSERT(el.pNext == NULL); // otherwise delete
+ if(el.pVertexInputState)
+ {
+ RDCASSERT(el.pVertexInputState->pNext == NULL); // otherwise delete
+ delete[] el.pVertexInputState->pVertexBindingDescriptions;
+ delete[] el.pVertexInputState->pVertexAttributeDescriptions;
+ delete el.pVertexInputState;
+ }
+ if(el.pInputAssemblyState)
+ {
+ RDCASSERT(el.pInputAssemblyState->pNext == NULL); // otherwise delete
+ delete el.pInputAssemblyState;
+ }
+ if(el.pTessellationState)
+ {
+ RDCASSERT(el.pTessellationState->pNext == NULL); // otherwise delete
+ delete el.pTessellationState;
+ }
+ if(el.pViewportState)
+ {
+ RDCASSERT(el.pViewportState->pNext == NULL); // otherwise delete
+ if(el.pViewportState->pViewports)
+ delete[] el.pViewportState->pViewports;
+ if(el.pViewportState->pScissors)
+ delete[] el.pViewportState->pScissors;
+ delete el.pViewportState;
+ }
+ if(el.pRasterizationState)
+ {
+ RDCASSERT(el.pRasterizationState->pNext == NULL); // otherwise delete
+ delete el.pRasterizationState;
+ }
+ if(el.pMultisampleState)
+ {
+ RDCASSERT(el.pMultisampleState->pNext == NULL); // otherwise delete
+ delete el.pMultisampleState->pSampleMask;
+ delete el.pMultisampleState;
+ }
+ if(el.pDepthStencilState)
+ {
+ RDCASSERT(el.pDepthStencilState->pNext == NULL); // otherwise delete
+ delete el.pDepthStencilState;
+ }
+ if(el.pColorBlendState)
+ {
+ RDCASSERT(el.pColorBlendState->pNext == NULL); // otherwise delete
+ delete[] el.pColorBlendState->pAttachments;
+ delete el.pColorBlendState;
+ }
+ if(el.pDynamicState)
+ {
+ RDCASSERT(el.pDynamicState->pNext == NULL); // otherwise delete
+ if(el.pDynamicState->pDynamicStates)
+ delete[] el.pDynamicState->pDynamicStates;
+ delete el.pDynamicState;
+ }
+ for(uint32_t i = 0; i < el.stageCount; i++)
+ {
+ RDCASSERT(el.pStages[i].pNext == NULL); // otherwise delete
+ if(el.pStages[i].pSpecializationInfo)
+ {
+ FreeAlignedBuffer((byte *)el.pStages[i].pSpecializationInfo->pData);
+ delete[] el.pStages[i].pSpecializationInfo->pMapEntries;
+ delete el.pStages[i].pSpecializationInfo;
+ }
+ }
+ delete[] el.pStages;
+}
+
+template
+void DoSerialise(SerialiserType &ser, VkComputePipelineCreateInfo &el)
+{
+ RDCASSERT(ser.IsReading() || el.sType == VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO);
+ SerialiseNext(ser, el.sType, el.pNext);
+
+ SERIALISE_MEMBER(stage);
+ SERIALISE_MEMBER_TYPED(VkPipelineCreateFlagBits, flags);
+ SERIALISE_MEMBER(layout);
+ SERIALISE_MEMBER(basePipelineHandle);
+ SERIALISE_MEMBER(basePipelineIndex);
+}
+
+template <>
+void Deserialise(const VkComputePipelineCreateInfo &el)
+{
+ RDCASSERT(el.pNext == NULL); // otherwise delete
+ RDCASSERT(el.stage.pNext == NULL); // otherwise delete
+ if(el.stage.pSpecializationInfo)
+ {
+ FreeAlignedBuffer((byte *)(el.stage.pSpecializationInfo->pData));
+ delete[] el.stage.pSpecializationInfo->pMapEntries;
+ delete el.stage.pSpecializationInfo;
+ }
+}
+
+template
+void DoSerialise(SerialiserType &ser, VkDescriptorPoolSize &el)
+{
+ SERIALISE_MEMBER(type);
+ SERIALISE_MEMBER(descriptorCount);
+}
+
+template
+void DoSerialise(SerialiserType &ser, VkDescriptorPoolCreateInfo &el)
+{
+ RDCASSERT(ser.IsReading() || el.sType == VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO);
+ SerialiseNext(ser, el.sType, el.pNext);
+
+ SERIALISE_MEMBER_TYPED(VkDescriptorPoolCreateFlagBits, flags);
+ SERIALISE_MEMBER(maxSets);
+ SERIALISE_MEMBER_ARRAY(pPoolSizes, poolSizeCount);
+}
+
+template <>
+void Deserialise(const VkDescriptorPoolCreateInfo &el)
+{
+ RDCASSERT(el.pNext == NULL); // otherwise delete
+ delete[] el.pPoolSizes;
+}
+
+template
+void DoSerialise(SerialiserType &ser, VkDescriptorSetAllocateInfo &el)
+{
+ RDCASSERT(ser.IsReading() || el.sType == VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO);
+ SerialiseNext(ser, el.sType, el.pNext);
+
+ SERIALISE_MEMBER(descriptorPool);
+ SERIALISE_MEMBER_ARRAY(pSetLayouts, descriptorSetCount);
+}
+
+template <>
+void Deserialise(const VkDescriptorSetAllocateInfo &el)
+{
+ RDCASSERT(el.pNext == NULL); // otherwise delete
+ delete[] el.pSetLayouts;
+}
+
+template
+void DoSerialise(SerialiserType &ser, VkDescriptorImageInfo &el)
+{
+ // Resources in this struct are optional, because if we decided a descriptor wasn't used - we
+ // might still have recorded some updates to it
+ OPTIONAL_RESOURCES();
+
+ SERIALISE_MEMBER(sampler);
+ SERIALISE_MEMBER(imageView);
+ SERIALISE_MEMBER(imageLayout);
+}
+
+template
+void DoSerialise(SerialiserType &ser, VkDescriptorBufferInfo &el)
+{
+ // Resources in this struct are optional, because if we decided a descriptor wasn't used - we
+ // might still have recorded some updates to it
+ OPTIONAL_RESOURCES();
+
+ SERIALISE_MEMBER(buffer);
+ SERIALISE_MEMBER(offset);
+ SERIALISE_MEMBER(range);
+}
+
+template
+void DoSerialise(SerialiserType &ser, VkWriteDescriptorSet &el)
+{
+ // Resources in this struct are optional, because if we decided a descriptor wasn't used - we
+ // might still have recorded some updates to it
+ OPTIONAL_RESOURCES();
+
+ RDCASSERT(ser.IsReading() || el.sType == VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET);
+ SerialiseNext(ser, el.sType, el.pNext);
+
+ SERIALISE_MEMBER(dstSet);
+ SERIALISE_MEMBER(dstBinding);
+ SERIALISE_MEMBER(dstArrayElement);
+ SERIALISE_MEMBER(descriptorType);
+
+ if(ser.IsReading())
+ {
+ el.pImageInfo = NULL;
+ el.pBufferInfo = NULL;
+ el.pTexelBufferView = NULL;
+ }
+
+ // only serialise the array type used, the others are ignored
+ if(el.descriptorType == VK_DESCRIPTOR_TYPE_SAMPLER ||
+ el.descriptorType == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER ||
+ el.descriptorType == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE ||
+ el.descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_IMAGE ||
+ el.descriptorType == VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT)
+ {
+ SERIALISE_MEMBER_ARRAY(pImageInfo, descriptorCount);
+ }
+ else if(el.descriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER ||
+ el.descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER ||
+ el.descriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC ||
+ el.descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC)
+ {
+ SERIALISE_MEMBER_ARRAY(pBufferInfo, descriptorCount);
+ }
+ else if(el.descriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER ||
+ el.descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER)
+ {
+ SERIALISE_MEMBER_ARRAY(pTexelBufferView, descriptorCount);
+ }
+}
+
+template <>
+void Deserialise(const VkWriteDescriptorSet &el)
+{
+ RDCASSERT(el.pNext == NULL); // otherwise delete
+ if(el.pImageInfo)
+ delete[] el.pImageInfo;
+ if(el.pBufferInfo)
+ delete[] el.pBufferInfo;
+ if(el.pTexelBufferView)
+ delete[] el.pTexelBufferView;
+}
+
+template
+void DoSerialise(SerialiserType &ser, VkCopyDescriptorSet &el)
+{
+ // Resources in this struct are optional, because if we decided a descriptor wasn't used - we
+ // might still have recorded some copies to or from it
+ OPTIONAL_RESOURCES();
+
+ RDCASSERT(ser.IsReading() || el.sType == VK_STRUCTURE_TYPE_COPY_DESCRIPTOR_SET);
+ SerialiseNext(ser, el.sType, el.pNext);
+
+ SERIALISE_MEMBER(srcSet);
+ SERIALISE_MEMBER(srcBinding);
+ SERIALISE_MEMBER(srcArrayElement);
+ SERIALISE_MEMBER(dstSet);
+ SERIALISE_MEMBER(dstBinding);
+ SERIALISE_MEMBER(dstArrayElement);
+ SERIALISE_MEMBER(descriptorCount);
+}
+
+template
+void DoSerialise(SerialiserType &ser, VkPushConstantRange &el)
+{
+ SERIALISE_MEMBER_TYPED(VkShaderStageFlagBits, stageFlags);
+ SERIALISE_MEMBER(offset);
+ SERIALISE_MEMBER(size);
+}
+
+template
+void DoSerialise(SerialiserType &ser, VkDescriptorSetLayoutBinding &el)
+{
+ SERIALISE_MEMBER(binding);
+ SERIALISE_MEMBER(descriptorType);
+ SERIALISE_MEMBER_TYPED(VkShaderStageFlagBits, stageFlags);
+ SERIALISE_MEMBER_ARRAY(pImmutableSamplers, descriptorCount);
+
+ // serialise count separately after, as if pImmutableSamplers is NULL, count would be set to 0
+ SERIALISE_MEMBER(descriptorCount);
+}
+
+template
+void DoSerialise(SerialiserType &ser, VkDescriptorSetLayoutCreateInfo &el)
+{
+ RDCASSERT(ser.IsReading() || el.sType == VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO);
+ SerialiseNext(ser, el.sType, el.pNext);
+
+ SERIALISE_MEMBER_TYPED(VkFlagWithNoBits, flags);
+ SERIALISE_MEMBER_ARRAY(pBindings, bindingCount);
+}
+
+template <>
+void Deserialise(const VkDescriptorSetLayoutCreateInfo &el)
+{
+ RDCASSERT(el.pNext == NULL); // otherwise delete
+ for(uint32_t i = 0; i < el.bindingCount; i++)
+ if(el.pBindings[i].pImmutableSamplers)
+ delete[] el.pBindings[i].pImmutableSamplers;
+ delete[] el.pBindings;
+}
+
+template
+void DoSerialise(SerialiserType &ser, VkComponentMapping &el)
+{
+ SERIALISE_MEMBER(r);
+ SERIALISE_MEMBER(g);
+ SERIALISE_MEMBER(b);
+ SERIALISE_MEMBER(a);
+}
+
+template
+void DoSerialise(SerialiserType &ser, VkMappedMemoryRange &el)
+{
+ RDCASSERT(ser.IsReading() || el.sType == VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE);
+ SerialiseNext(ser, el.sType, el.pNext);
+
+ SERIALISE_MEMBER(memory);
+ SERIALISE_MEMBER(offset);
+ SERIALISE_MEMBER(size);
+}
+
+template
+void DoSerialise(SerialiserType &ser, VkBufferImageCopy &el)
+{
+ SERIALISE_MEMBER(bufferOffset);
+ SERIALISE_MEMBER(bufferRowLength);
+ SERIALISE_MEMBER(bufferImageHeight);
+ SERIALISE_MEMBER(imageSubresource);
+ SERIALISE_MEMBER(imageOffset);
+ SERIALISE_MEMBER(imageExtent);
+}
+
+template
+void DoSerialise(SerialiserType &ser, VkBufferCopy &el)
+{
+ SERIALISE_MEMBER(srcOffset);
+ SERIALISE_MEMBER(dstOffset);
+ SERIALISE_MEMBER(size);
+}
+
+template
+void DoSerialise(SerialiserType &ser, VkImageCopy &el)
+{
+ SERIALISE_MEMBER(srcSubresource);
+ SERIALISE_MEMBER(srcOffset);
+ SERIALISE_MEMBER(dstSubresource);
+ SERIALISE_MEMBER(dstOffset);
+ SERIALISE_MEMBER(extent);
+}
+
+template
+void DoSerialise(SerialiserType &ser, VkImageBlit &el)
+{
+ SERIALISE_MEMBER(srcSubresource);
+ SERIALISE_MEMBER(srcOffsets);
+ SERIALISE_MEMBER(dstSubresource);
+ SERIALISE_MEMBER(dstOffsets);
+}
+
+template
+void DoSerialise(SerialiserType &ser, VkImageResolve &el)
+{
+ SERIALISE_MEMBER(srcSubresource);
+ SERIALISE_MEMBER(srcOffset);
+ SERIALISE_MEMBER(dstSubresource);
+ SERIALISE_MEMBER(dstOffset);
+ SERIALISE_MEMBER(extent);
+}
+
+template
+void DoSerialise(SerialiserType &ser, VkClearColorValue &el)
+{
+ SERIALISE_MEMBER(uint32);
+}
+
+template
+void DoSerialise(SerialiserType &ser, VkClearDepthStencilValue &el)
+{
+ SERIALISE_MEMBER(depth);
+ SERIALISE_MEMBER(stencil);
+}
+
+template
+void DoSerialise(SerialiserType &ser, VkClearValue &el)
+{
+ SERIALISE_MEMBER(depthStencil);
+ SERIALISE_MEMBER(color);
+}
+
+template
+void DoSerialise(SerialiserType &ser, VkClearRect &el)
+{
+ SERIALISE_MEMBER(rect);
+ SERIALISE_MEMBER(baseArrayLayer);
+ SERIALISE_MEMBER(layerCount);
+}
+
+template
+void DoSerialise(SerialiserType &ser, VkClearAttachment &el)
+{
+ SERIALISE_MEMBER(aspectMask);
+ SERIALISE_MEMBER(colorAttachment);
+ SERIALISE_MEMBER(clearValue);
+}
+
+template
+void DoSerialise(SerialiserType &ser, VkRect2D &el)
+{
+ SERIALISE_MEMBER(offset);
+ SERIALISE_MEMBER(extent);
+}
+
+template
+void DoSerialise(SerialiserType &ser, VkOffset2D &el)
+{
+ SERIALISE_MEMBER(x);
+ SERIALISE_MEMBER(y);
+}
+
+template
+void DoSerialise(SerialiserType &ser, VkOffset3D &el)
+{
+ SERIALISE_MEMBER(x);
+ SERIALISE_MEMBER(y);
+ SERIALISE_MEMBER(z);
+}
+
+template
+void DoSerialise(SerialiserType &ser, VkExtent2D &el)
+{
+ SERIALISE_MEMBER(width);
+ SERIALISE_MEMBER(height);
+}
+
+template
+void DoSerialise(SerialiserType &ser, VkExtent3D &el)
+{
+ SERIALISE_MEMBER(width);
+ SERIALISE_MEMBER(height);
+ SERIALISE_MEMBER(depth);
+}
+
+template
+void DoSerialise(SerialiserType &ser, VkViewport &el)
+{
+ SERIALISE_MEMBER(x);
+ SERIALISE_MEMBER(y);
+ SERIALISE_MEMBER(width);
+ SERIALISE_MEMBER(height);
+ SERIALISE_MEMBER(minDepth);
+ SERIALISE_MEMBER(maxDepth);
+}
+
+template
+void DoSerialise(SerialiserType &ser, VkSwapchainCreateInfoKHR &el)
+{
+ RDCASSERT(ser.IsReading() || el.sType == VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR);
+ SerialiseNext(ser, el.sType, el.pNext);
+
+ SERIALISE_MEMBER_TYPED(VkFlagWithNoBits, flags);
+
+ // don't need the surface
+
+ SERIALISE_MEMBER(minImageCount);
+ SERIALISE_MEMBER(imageFormat);
+ SERIALISE_MEMBER(imageColorSpace);
+ SERIALISE_MEMBER(imageExtent);
+ SERIALISE_MEMBER(imageArrayLayers);
+ SERIALISE_MEMBER(imageUsage);
+ SERIALISE_MEMBER(imageSharingMode);
+
+ // SHARING: queueFamilyCount, pQueueFamilyIndices
+
+ SERIALISE_MEMBER(preTransform);
+ SERIALISE_MEMBER(compositeAlpha);
+ SERIALISE_MEMBER(presentMode);
+ SERIALISE_MEMBER(clipped);
+
+ // don't need the old swap chain
+}
+
+template
+void DoSerialise(SerialiserType &ser, VkDebugMarkerMarkerInfoEXT &el)
+{
+ RDCASSERT(ser.IsReading() || el.sType == VK_STRUCTURE_TYPE_DEBUG_MARKER_MARKER_INFO_EXT);
+ SerialiseNext(ser, el.sType, el.pNext);
+
+ SERIALISE_MEMBER(pMarkerName);
+ SERIALISE_MEMBER(color);
+}
+
+// this isn't a real vulkan type, it's our own "anything that could be in a descriptor"
+// structure that
+template
+void DoSerialise(SerialiserType &ser, DescriptorSetSlot &el)
+{
+ // Resources in this struct are optional, because if we decided a descriptor wasn't used - we
+ // might still have recorded the contents of it
+ OPTIONAL_RESOURCES();
+
+ SERIALISE_MEMBER(bufferInfo);
+ SERIALISE_MEMBER(imageInfo);
+ SERIALISE_MEMBER(texelBufferView);
+}
+
+template
+void DoSerialise(SerialiserType &ser, ImageRegionState &el)
+{
+ SERIALISE_MEMBER(subresourceRange);
+ SERIALISE_MEMBER(oldLayout);
+ SERIALISE_MEMBER(newLayout);
+}
+
+template
+void DoSerialise(SerialiserType &ser, ImageLayouts &el)
+{
+ SERIALISE_MEMBER(subresourceStates);
+ SERIALISE_MEMBER(layerCount);
+ SERIALISE_MEMBER(levelCount);
+ SERIALISE_MEMBER(sampleCount);
+ SERIALISE_MEMBER(extent);
+ SERIALISE_MEMBER(format);
+}
+
+INSTANTIATE_SERIALISE_TYPE(VkOffset2D);
+INSTANTIATE_SERIALISE_TYPE(VkExtent2D);
+INSTANTIATE_SERIALISE_TYPE(VkMemoryType);
+INSTANTIATE_SERIALISE_TYPE(VkMemoryHeap);
+INSTANTIATE_SERIALISE_TYPE(VkPhysicalDeviceLimits);
+INSTANTIATE_SERIALISE_TYPE(VkPhysicalDeviceSparseProperties);
+INSTANTIATE_SERIALISE_TYPE(VkQueueFamilyProperties);
+INSTANTIATE_SERIALISE_TYPE(VkExtent3D);
+INSTANTIATE_SERIALISE_TYPE(VkPipelineShaderStageCreateInfo);
+INSTANTIATE_SERIALISE_TYPE(VkOffset3D);
+INSTANTIATE_SERIALISE_TYPE(VkCommandBufferInheritanceInfo);
+INSTANTIATE_SERIALISE_TYPE(VkPipelineVertexInputStateCreateInfo);
+INSTANTIATE_SERIALISE_TYPE(VkSparseBufferMemoryBindInfo);
+INSTANTIATE_SERIALISE_TYPE(VkSparseImageOpaqueMemoryBindInfo);
+INSTANTIATE_SERIALISE_TYPE(VkSparseImageMemoryBindInfo);
+INSTANTIATE_SERIALISE_TYPE(VkAttachmentDescription);
+INSTANTIATE_SERIALISE_TYPE(VkSubpassDescription);
+INSTANTIATE_SERIALISE_TYPE(VkSubpassDependency);
+INSTANTIATE_SERIALISE_TYPE(VkClearValue);
+INSTANTIATE_SERIALISE_TYPE(VkClearColorValue);
+INSTANTIATE_SERIALISE_TYPE(VkClearDepthStencilValue);
+INSTANTIATE_SERIALISE_TYPE(VkClearAttachment);
+INSTANTIATE_SERIALISE_TYPE(VkClearRect);
+INSTANTIATE_SERIALISE_TYPE(VkViewport);
+INSTANTIATE_SERIALISE_TYPE(VkPipelineColorBlendAttachmentState);
+INSTANTIATE_SERIALISE_TYPE(VkDescriptorPoolSize);
+INSTANTIATE_SERIALISE_TYPE(VkDescriptorImageInfo);
+INSTANTIATE_SERIALISE_TYPE(VkDescriptorBufferInfo);
+INSTANTIATE_SERIALISE_TYPE(VkSpecializationInfo);
+INSTANTIATE_SERIALISE_TYPE(VkAttachmentReference);
+INSTANTIATE_SERIALISE_TYPE(VkSparseImageMemoryBind);
+INSTANTIATE_SERIALISE_TYPE(VkVertexInputBindingDescription);
+INSTANTIATE_SERIALISE_TYPE(VkVertexInputAttributeDescription);
+INSTANTIATE_SERIALISE_TYPE(VkSpecializationMapEntry);
+INSTANTIATE_SERIALISE_TYPE(VkRect2D);
+INSTANTIATE_SERIALISE_TYPE(VkDeviceQueueCreateInfo);
+INSTANTIATE_SERIALISE_TYPE(VkPhysicalDeviceFeatures);
+INSTANTIATE_SERIALISE_TYPE(VkPhysicalDeviceMemoryProperties);
+INSTANTIATE_SERIALISE_TYPE(VkPhysicalDeviceProperties);
+INSTANTIATE_SERIALISE_TYPE(VkDeviceCreateInfo);
+INSTANTIATE_SERIALISE_TYPE(VkBufferCreateInfo);
+INSTANTIATE_SERIALISE_TYPE(VkBufferViewCreateInfo);
+INSTANTIATE_SERIALISE_TYPE(VkImageCreateInfo);
+INSTANTIATE_SERIALISE_TYPE(VkImageViewCreateInfo);
+INSTANTIATE_SERIALISE_TYPE(VkSparseMemoryBind);
+INSTANTIATE_SERIALISE_TYPE(VkBindSparseInfo);
+INSTANTIATE_SERIALISE_TYPE(VkSubmitInfo);
+INSTANTIATE_SERIALISE_TYPE(VkFramebufferCreateInfo);
+INSTANTIATE_SERIALISE_TYPE(VkRenderPassCreateInfo);
+INSTANTIATE_SERIALISE_TYPE(VkRenderPassBeginInfo);
+INSTANTIATE_SERIALISE_TYPE(VkPipelineInputAssemblyStateCreateInfo);
+INSTANTIATE_SERIALISE_TYPE(VkPipelineTessellationStateCreateInfo);
+INSTANTIATE_SERIALISE_TYPE(VkPipelineViewportStateCreateInfo);
+INSTANTIATE_SERIALISE_TYPE(VkPipelineRasterizationStateCreateInfo);
+INSTANTIATE_SERIALISE_TYPE(VkPipelineMultisampleStateCreateInfo);
+INSTANTIATE_SERIALISE_TYPE(VkPipelineDepthStencilStateCreateInfo);
+INSTANTIATE_SERIALISE_TYPE(VkPipelineColorBlendStateCreateInfo);
+INSTANTIATE_SERIALISE_TYPE(VkPipelineDynamicStateCreateInfo);
+INSTANTIATE_SERIALISE_TYPE(VkPipelineLayoutCreateInfo);
+INSTANTIATE_SERIALISE_TYPE(VkPushConstantRange);
+INSTANTIATE_SERIALISE_TYPE(VkDescriptorSetLayoutBinding);
+INSTANTIATE_SERIALISE_TYPE(VkDescriptorSetLayoutCreateInfo);
+INSTANTIATE_SERIALISE_TYPE(VkDescriptorPoolCreateInfo);
+INSTANTIATE_SERIALISE_TYPE(VkDescriptorSetAllocateInfo);
+INSTANTIATE_SERIALISE_TYPE(VkWriteDescriptorSet);
+INSTANTIATE_SERIALISE_TYPE(VkCopyDescriptorSet);
+INSTANTIATE_SERIALISE_TYPE(VkCommandPoolCreateInfo);
+INSTANTIATE_SERIALISE_TYPE(VkCommandBufferAllocateInfo);
+INSTANTIATE_SERIALISE_TYPE(VkCommandBufferBeginInfo);
+INSTANTIATE_SERIALISE_TYPE(VkStencilOpState);
+INSTANTIATE_SERIALISE_TYPE(VkQueryPoolCreateInfo);
+INSTANTIATE_SERIALISE_TYPE(VkSemaphoreCreateInfo);
+INSTANTIATE_SERIALISE_TYPE(VkEventCreateInfo);
+INSTANTIATE_SERIALISE_TYPE(VkFenceCreateInfo);
+INSTANTIATE_SERIALISE_TYPE(VkSamplerCreateInfo);
+INSTANTIATE_SERIALISE_TYPE(VkPipelineCacheCreateInfo);
+INSTANTIATE_SERIALISE_TYPE(VkShaderModuleCreateInfo);
+INSTANTIATE_SERIALISE_TYPE(VkImageSubresourceRange);
+INSTANTIATE_SERIALISE_TYPE(VkImageSubresource);
+INSTANTIATE_SERIALISE_TYPE(VkImageSubresourceLayers);
+INSTANTIATE_SERIALISE_TYPE(VkMemoryAllocateInfo);
+INSTANTIATE_SERIALISE_TYPE(VkMemoryBarrier);
+INSTANTIATE_SERIALISE_TYPE(VkBufferMemoryBarrier);
+INSTANTIATE_SERIALISE_TYPE(VkImageMemoryBarrier);
+INSTANTIATE_SERIALISE_TYPE(VkGraphicsPipelineCreateInfo);
+INSTANTIATE_SERIALISE_TYPE(VkComputePipelineCreateInfo);
+INSTANTIATE_SERIALISE_TYPE(VkComponentMapping);
+INSTANTIATE_SERIALISE_TYPE(VkMappedMemoryRange);
+INSTANTIATE_SERIALISE_TYPE(VkBufferImageCopy);
+INSTANTIATE_SERIALISE_TYPE(VkBufferCopy);
+INSTANTIATE_SERIALISE_TYPE(VkImageCopy);
+INSTANTIATE_SERIALISE_TYPE(VkImageBlit);
+INSTANTIATE_SERIALISE_TYPE(VkImageResolve);
+INSTANTIATE_SERIALISE_TYPE(VkSwapchainCreateInfoKHR);
+INSTANTIATE_SERIALISE_TYPE(VkDebugMarkerMarkerInfoEXT);
+
+INSTANTIATE_SERIALISE_TYPE(DescriptorSetSlot);
+INSTANTIATE_SERIALISE_TYPE(ImageRegionState);
+INSTANTIATE_SERIALISE_TYPE(ImageLayouts);
\ No newline at end of file
diff --git a/renderdoc/driver/vulkan/vk_stringise.cpp b/renderdoc/driver/vulkan/vk_stringise.cpp
index 1ab231677..971267039 100644
--- a/renderdoc/driver/vulkan/vk_stringise.cpp
+++ b/renderdoc/driver/vulkan/vk_stringise.cpp
@@ -1310,106 +1310,6 @@ std::string DoStringise(const VkResult &el)
END_ENUM_STRINGISE();
}
-template <>
-std::string DoStringise(const VkMemoryType &el)
-{
- return StringFormat::Fmt("VkMemoryType", el.heapIndex,
- ToStr((VkMemoryPropertyFlagBits)el.propertyFlags).c_str());
-}
-
-template <>
-std::string DoStringise(const VkMemoryHeap &el)
-{
- return StringFormat::Fmt("VkMemoryHeap<%.3fMB, %s>", float(el.size) / (1024.0f * 1024.0f),
- ToStr((VkMemoryHeapFlagBits)el.flags).c_str());
-}
-
-template <>
-std::string DoStringise(const VkRect2D &el)
-{
- return StringFormat::Fmt("VkRect2D<%dx%d+%d+%d>", el.extent.width, el.extent.height, el.offset.x,
- el.offset.y);
-}
-
-template <>
-std::string DoStringise(const VkClearRect &el)
-{
- return StringFormat::Fmt("VkClearRect<%dx%d+%d+%d %u->%u>", el.rect.extent.width,
- el.rect.extent.height, el.rect.offset.x, el.rect.offset.y,
- el.baseArrayLayer, el.baseArrayLayer + el.layerCount);
-}
-
-template <>
-std::string DoStringise(const VkClearAttachment &el)
-{
- return StringFormat::Fmt("%s[%u] = %s", ToStr((VkImageAspectFlagBits)el.aspectMask).c_str(),
- el.colorAttachment, ToStr(el.clearValue).c_str());
-}
-
-template <>
-std::string DoStringise(const VkQueueFamilyProperties &el)
-{
- return StringFormat::Fmt("%s x %u, %u bits, %s", ToStr((VkQueueFlagBits)el.queueFlags).c_str(),
- el.queueCount, el.timestampValidBits,
- ToStr(el.minImageTransferGranularity).c_str());
-}
-
-template <>
-std::string DoStringise(const VkExtent2D &el)
-{
- return StringFormat::Fmt("VkExtent<%u,%u>", el.width, el.height);
-}
-
-template <>
-std::string DoStringise(const VkExtent3D &el)
-{
- return StringFormat::Fmt("VkExtent<%u,%u,%u>", el.width, el.height, el.depth);
-}
-
-template <>
-std::string DoStringise(const VkOffset2D &el)
-{
- return StringFormat::Fmt("VkOffset<%d,%d>", el.x, el.y);
-}
-
-template <>
-std::string DoStringise(const VkOffset3D &el)
-{
- return StringFormat::Fmt("VkOffset<%d,%d,%d>", el.x, el.y, el.z);
-}
-
-template <>
-std::string DoStringise(const VkViewport &el)
-{
- return StringFormat::Fmt("VkViewport<%f,%f, %fx%f, %f-%f>", el.x, el.y, el.width, el.height,
- el.minDepth, el.maxDepth);
-}
-
-template <>
-std::string DoStringise(const VkClearColorValue &el)
-{
- return StringFormat::Fmt("VkClearColorValue<%f,%f,%f,%f>", el.float32[0], el.float32[1],
- el.float32[2], el.float32[3]);
-}
-template <>
-std::string DoStringise(const VkClearDepthStencilValue &el)
-{
- return StringFormat::Fmt("VkClearDepthStencilValue<%f %u>", el.depth, el.stencil);
-}
-template <>
-std::string DoStringise(const VkClearValue &el)
-{
- return StringFormat::Fmt("VkClearValue[ col:<%f,%f,%f,%f> / d:%f s:%u ]", el.color.float32[0],
- el.color.float32[1], el.color.float32[2], el.color.float32[3],
- el.depthStencil.depth, el.depthStencil.stencil);
-}
-
-template <>
-std::string DoStringise(const VkAttachmentReference &el)
-{
- return StringFormat::Fmt("VkAttachmentReference<%u, %s>", el.attachment, ToStr(el.layout).c_str());
-}
-
////////////////////////////////////////////////////////////
// VK_KHR_surface
////////////////////////////////////////////////////////////
@@ -1484,3 +1384,9 @@ std::string DoStringise(const VkPresentModeKHR &el)
}
END_ENUM_STRINGISE();
}
+
+template <>
+std::string DoStringise(const VkExtent3D &el)
+{
+ return StringFormat::Fmt("VkExtent3D(%u, %u, %u)", el.width, el.height, el.depth);
+}