From b8d7cd17ec216aa134b17faba9761b2de663f5aa Mon Sep 17 00:00:00 2001 From: baldurk Date: Fri, 25 Jun 2021 15:51:43 +0100 Subject: [PATCH] When serialising an SDObject with lazy children, populate on-the-fly * If an object has enoug children, the lazy generator can take multiple seconds on e.g. android to fully populate. This is a long enough stall to cause the host side to timeout while waiting for the next piece of data. Instead of populating everything up front before starting serialising, we now populate as we go for each child, so that there's a steadier stream of data and avoid any timeouts. --- renderdoc/api/replay/structured_data.h | 6 +++ renderdoc/serialise/serialiser.cpp | 74 ++++++++++++-------------- 2 files changed, 41 insertions(+), 39 deletions(-) diff --git a/renderdoc/api/replay/structured_data.h b/renderdoc/api/replay/structured_data.h index 17ee7cf4c..25af4b446 100644 --- a/renderdoc/api/replay/structured_data.h +++ b/renderdoc/api/replay/structured_data.h @@ -375,6 +375,10 @@ private: friend void DoSerialise(SerialiserType &ser, SDObjectData &el); template friend void DoSerialise(SerialiserType &ser, SDObject *el); + template + friend void DoSerialise(SerialiserType &ser, SDObject &el); + template + friend void DoSerialise(SerialiserType &ser, SDChunk &el); DOCUMENT("A list of :class:`SDObject` containing the children of this :class:`SDObject`."); mutable StructuredObjectList children; @@ -932,6 +936,8 @@ private: friend void DoSerialise(SerialiserType &ser, SDObject &el); template friend void DoSerialise(SerialiserType &ser, SDChunk &el); + template + friend void DoSerialise(SerialiserType &ser, SDObject &el, StructuredObjectList &children); void DeleteLazyGenerator() const { diff --git a/renderdoc/serialise/serialiser.cpp b/renderdoc/serialise/serialiser.cpp index 55be7c4e5..56767843d 100644 --- a/renderdoc/serialise/serialiser.cpp +++ b/renderdoc/serialise/serialiser.cpp @@ -686,53 +686,53 @@ void DoSerialise(SerialiserType &ser, SDObjectPODData &el) SERIALISE_MEMBER(u); } -template -void DoSerialise(SerialiserType &ser, StructuredObjectList &el) -{ - // since structured objects aren't intended to be exported as nice structured data, only for pure - // transfer purposes, we don't make a proper array here and instead just manually serialise count - // + elements - uint64_t count = el.size(); - ser.Serialise("count"_lit, count); - - if(ser.IsReading()) - el.resize((size_t)count); - - for(size_t c = 0; c < (size_t)count; c++) - { - // we also assume that the caller serialising these objects will handle lifetime management. - if(ser.IsReading()) - el[c] = new SDObject(""_lit, ""_lit); - - ser.Serialise("$el"_lit, *el[c]); - } -} - template void DoSerialise(SerialiserType &ser, SDObjectData &el) { SERIALISE_MEMBER(basic); SERIALISE_MEMBER(str); - SERIALISE_MEMBER(children); + + // this is deliberately not serialised here, it's serialised in the parent SDObject. See below + // SERIALISE_MEMBER(children); +} + +template +void DoSerialise(SerialiserType &ser, SDObject &el, StructuredObjectList &children) +{ + // serialising the data above doesn't serialise the children, so we can do it here using a + // potential lazy generator. This is so that we don't incur the full cost of populating lazy + // children all at once (which could be slow). This is a bit of a hack as this can take many + // seconds and cause a timeout during transfer, and it would be uglier to try and keep the + // connection alive while serialising chunks. + uint64_t childCount = children.size(); + SERIALISE_ELEMENT(childCount).Hidden(); + + if(ser.IsReading()) + children.resize((size_t)childCount); + + for(size_t c = 0; c < el.NumChildren(); c++) + { + // we also assume that the caller serialising these objects will handle lifetime management. + if(ser.IsReading()) + children[c] = new SDObject(""_lit, ""_lit); + else + el.PopulateChild(c); + + ser.Serialise("$el"_lit, *children[c]); + + if(ser.IsReading()) + children[c]->m_Parent = ⪙ + } } template void DoSerialise(SerialiserType &ser, SDObject &el) { - if(ser.IsWriting()) - { - el.PopulateAllChildren(); - } - SERIALISE_MEMBER(name); SERIALISE_MEMBER(type); SERIALISE_MEMBER(data); - if(ser.IsReading()) - { - for(size_t i = 0; i < el.NumChildren(); i++) - el.GetChild(i)->m_Parent = ⪙ - } + DoSerialise(ser, el, el.data.children); } template @@ -740,14 +740,10 @@ void DoSerialise(SerialiserType &ser, SDChunk &el) { SERIALISE_MEMBER(name); SERIALISE_MEMBER(type); - SERIALISE_MEMBER(data); SERIALISE_MEMBER(metadata); + SERIALISE_MEMBER(data); - if(ser.IsReading()) - { - for(size_t i = 0; i < el.NumChildren(); i++) - el.GetChild(i)->m_Parent = ⪙ - } + DoSerialise(ser, el, el.data.children); } INSTANTIATE_SERIALISE_TYPE(SDChunk);