diff --git a/renderdoc/driver/vulkan/vk_serialise.cpp b/renderdoc/driver/vulkan/vk_serialise.cpp index eac1590d7..cfbcd3c13 100644 --- a/renderdoc/driver/vulkan/vk_serialise.cpp +++ b/renderdoc/driver/vulkan/vk_serialise.cpp @@ -1509,6 +1509,15 @@ void Deserialise(const VkDescriptorSetAllocateInfo &el) delete[] el.pSetLayouts; } +enum class VkDescriptorImageInfoValidity +{ + Neither = 0x0, + Sampler = 0x1, + ImageView = 0x100, +}; + +BITMASK_OPERATORS(VkDescriptorImageInfoValidity); + template void DoSerialise(SerialiserType &ser, VkDescriptorImageInfo &el) { @@ -1516,8 +1525,20 @@ void DoSerialise(SerialiserType &ser, VkDescriptorImageInfo &el) // might still have recorded some updates to it OPTIONAL_RESOURCES(); - SERIALISE_MEMBER(sampler); - SERIALISE_MEMBER(imageView); + VkDescriptorImageInfoValidity validity = (VkDescriptorImageInfoValidity)ser.GetStructArg(); + + RDCASSERT(validity != VkDescriptorImageInfoValidity::Neither, (uint64_t)validity); + + if(validity & VkDescriptorImageInfoValidity::Sampler) + SERIALISE_MEMBER(sampler); + else + SERIALISE_MEMBER_EMPTY(sampler); + + if(validity & VkDescriptorImageInfoValidity::ImageView) + SERIALISE_MEMBER(imageView); + else + SERIALISE_MEMBER_EMPTY(imageView); + SERIALISE_MEMBER(imageLayout); } @@ -1556,6 +1577,23 @@ void DoSerialise(SerialiserType &ser, VkWriteDescriptorSet &el) el.descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_IMAGE || el.descriptorType == VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT) { + VkDescriptorImageInfoValidity validity = VkDescriptorImageInfoValidity::Neither; + + if(el.descriptorType == VK_DESCRIPTOR_TYPE_SAMPLER || + el.descriptorType == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER) + validity = validity | VkDescriptorImageInfoValidity::Sampler; + + if(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) + validity = validity | VkDescriptorImageInfoValidity::ImageView; + + // set the validity flags so the serialisation of VkDescriptorImageInfo knows which members are + // safe to read. We pass this as just flags so the comparisons happen here once, not per-element + // in this array + ser.SetStructArg((uint64_t)validity); + SERIALISE_MEMBER_ARRAY(pImageInfo, descriptorCount); } else @@ -1861,6 +1899,11 @@ void DoSerialise(SerialiserType &ser, DescriptorSetSlot &el) // might still have recorded the contents of it OPTIONAL_RESOURCES(); + // all members are valid because it's either NULL or pointing at an existing element, it won't + // point to garbage. + ser.SetStructArg( + uint64_t(VkDescriptorImageInfoValidity::Sampler | VkDescriptorImageInfoValidity::ImageView)); + SERIALISE_MEMBER(bufferInfo); SERIALISE_MEMBER(imageInfo); SERIALISE_MEMBER(texelBufferView); diff --git a/renderdoc/serialise/serialiser.h b/renderdoc/serialise/serialiser.h index 8a61fd35d..0ce6ebd19 100644 --- a/renderdoc/serialise/serialiser.h +++ b/renderdoc/serialise/serialiser.h @@ -134,6 +134,11 @@ public: SDFile &GetStructuredFile() { return *m_StructuredFile; } void WriteStructuredFile(const SDFile &file, RENDERDOC_ProgressCallback progress); void SetDrawChunk() { m_DrawChunk = true; } + // the struct argument allows nested structs to pass a bit of data so a child struct can have + // context from a parent struct if needed to serialise properly. Rarely used, primarily to be able + // to flag if some context-sensitive members might be invalid + void SetStructArg(uint64_t arg) { m_StructArg = arg; } + uint64_t GetStructArg() { return m_StructArg; } ////////////////////////////////////////// // Public serialisation interface @@ -1562,6 +1567,8 @@ private: void *m_pUserData = NULL; + uint64_t m_StructArg = 0; + StreamWriter *m_Write = NULL; StreamReader *m_Read = NULL;