diff options
Diffstat (limited to 'PhysX_3.4/Source/PhysXExtensions/src/serialization/Binary')
17 files changed, 4842 insertions, 0 deletions
diff --git a/PhysX_3.4/Source/PhysXExtensions/src/serialization/Binary/SnBinaryDeserialization.cpp b/PhysX_3.4/Source/PhysXExtensions/src/serialization/Binary/SnBinaryDeserialization.cpp new file mode 100644 index 00000000..981cfa2a --- /dev/null +++ b/PhysX_3.4/Source/PhysXExtensions/src/serialization/Binary/SnBinaryDeserialization.cpp @@ -0,0 +1,305 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and related documentation and +// any modifications thereto. Any use, reproduction, disclosure, or +// distribution of this software and related documentation without an express +// license agreement from NVIDIA Corporation is strictly prohibited. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + +#include "PsHash.h" +#include "PsHashMap.h" +#include "PsFoundation.h" +#include "CmIO.h" +#include "SnFile.h" +#include "PsString.h" +#include "extensions/PxSerialization.h" +#include "PxPhysics.h" +#include "PxPhysicsSerialization.h" +#include "SnSerializationContext.h" +#include "PxSerializer.h" +#include "serialization/SnSerializationRegistry.h" +#include "serialization/SnSerialUtils.h" +#include "CmCollection.h" +#include "SnConvX_Align.h" + +using namespace physx; +using namespace Sn; + +namespace +{ + PX_INLINE PxU8* alignPtr(PxU8* ptr, PxU32 alignment = PX_SERIAL_ALIGN) + { + if(!alignment) + return ptr; + + const PxU32 padding = getPadding(size_t(ptr), alignment); + PX_ASSERT(!getPadding(size_t(ptr + padding), alignment)); + return ptr + padding; + } + + PX_FORCE_INLINE PxU32 read32(PxU8*& address) + { + const PxU32 value = *reinterpret_cast<PxU32*>(address); + address += sizeof(PxU32); + return value; + } + + bool readHeader(PxU8*& address, PxU32& version) + { + const PxU32 header = read32(address); + PX_UNUSED(header); + + version = read32(address); + + const PxU32 binaryVersion = read32(address); + PX_UNUSED(binaryVersion); + const PxU32 buildNumber = read32(address); + PX_UNUSED(buildNumber); + const PxU32 platformTag = read32(address); + PX_UNUSED(platformTag); + const PxU32 markedPadding = read32(address); + PX_UNUSED(markedPadding); + +#if PX_CHECKED + if (header != PX_MAKE_FOURCC('S','E','B','D')) + { + Ps::getFoundation().error(physx::PxErrorCode::eINVALID_PARAMETER, __FILE__, __LINE__, + "Buffer contains data with wrong header indicating invalid binary data."); + return false; + } + + if (!checkCompatibility(version, binaryVersion)) + { + char buffer[512]; + getCompatibilityVersionsStr(buffer, 512); + + Ps::getFoundation().error(physx::PxErrorCode::eINVALID_PARAMETER, __FILE__, __LINE__, + "Buffer contains data version (%x-%d) is incompatible with this PhysX sdk.\n These versions would be compatible: %s", + version, binaryVersion, buffer); + return false; + } + + if (platformTag != getBinaryPlatformTag()) + { + Ps::getFoundation().error(physx::PxErrorCode::eINVALID_PARAMETER, __FILE__, __LINE__, + "Buffer contains data with platform mismatch:\nExpected: %s \nActual: %s\n", + getBinaryPlatformName(getBinaryPlatformTag()), + getBinaryPlatformName(platformTag)); + return false; + } +#endif + return true; + } + + bool checkImportReferences(const ImportReference* importReferences, PxU32 nbImportReferences, const Cm::Collection* externalRefs) + { + if (!externalRefs) + { + if (nbImportReferences > 0) + { + Ps::getFoundation().error(PxErrorCode::eINVALID_PARAMETER, __FILE__, __LINE__, "PxSerialization::createCollectionFromBinary: External references needed but no externalRefs collection specified."); + return false; + } + } + else + { + for (PxU32 i=0; i<nbImportReferences;i++) + { + PxSerialObjectId id = importReferences[i].id; + PxType type = importReferences[i].type; + + PxBase* referencedObject = externalRefs->find(id); + if (!referencedObject) + { + Ps::getFoundation().error(PxErrorCode::eINVALID_PARAMETER, __FILE__, __LINE__, "PxSerialization::createCollectionFromBinary: External reference %" PX_PRIu64 " expected in externalRefs collection but not found.", id); + return false; + } + if (referencedObject->getConcreteType() != type) + { + Ps::getFoundation().error(PxErrorCode::eINVALID_PARAMETER, __FILE__, __LINE__, "PxSerialization::createCollectionFromBinary: External reference %d type mismatch. Expected %d but found %d in externalRefs collection.", type, referencedObject->getConcreteType()); + return false; + } + } + } + return true; + } + +} + +PxCollection* PxSerialization::createCollectionFromBinary(void* memBlock, PxSerializationRegistry& sr, const PxCollection* pxExternalRefs) +{ +#if PX_CHECKED + if(size_t(memBlock) & (PX_SERIAL_FILE_ALIGN-1)) + { + Ps::getFoundation().error(PxErrorCode::eINVALID_PARAMETER, __FILE__, __LINE__, "Buffer must be 128-bytes aligned."); + return NULL; + } +#endif + PxU8* address = reinterpret_cast<PxU8*>(memBlock); + const Cm::Collection* externalRefs = static_cast<const Cm::Collection*>(pxExternalRefs); + + PxU32 version; + if (!readHeader(address, version)) + { + return NULL; + } + + ManifestEntry* manifestTable; + PxU32 nbObjectsInCollection; + PxU32 objectDataEndOffset; + + // read number of objects in collection + address = alignPtr(address); + nbObjectsInCollection = read32(address); + + // read manifest (PxU32 offset, PxConcreteType type) + { + address = alignPtr(address); + PxU32 nbManifestEntries = read32(address); + PX_ASSERT(*reinterpret_cast<PxU32*>(address) == 0); //first offset is always 0 + manifestTable = (nbManifestEntries > 0) ? reinterpret_cast<ManifestEntry*>(address) : NULL; + address += nbManifestEntries*sizeof(ManifestEntry); + objectDataEndOffset = read32(address); + } + + ImportReference* importReferences; + PxU32 nbImportReferences; + // read import references + { + address = alignPtr(address); + nbImportReferences = read32(address); + importReferences = (nbImportReferences > 0) ? reinterpret_cast<ImportReference*>(address) : NULL; + address += nbImportReferences*sizeof(ImportReference); + } + + if (!checkImportReferences(importReferences, nbImportReferences, externalRefs)) + { + return NULL; + } + + ExportReference* exportReferences; + PxU32 nbExportReferences; + // read export references + { + address = alignPtr(address); + nbExportReferences = read32(address); + exportReferences = (nbExportReferences > 0) ? reinterpret_cast<ExportReference*>(address) : NULL; + address += nbExportReferences*sizeof(ExportReference); + } + + // read internal references arrays + PxU32 nbInternalPtrReferences = 0; + PxU32 nbInternalIdxReferences = 0; + InternalReferencePtr* internalPtrReferences = NULL; + InternalReferenceIdx* internalIdxReferences = NULL; + { + address = alignPtr(address); + + nbInternalPtrReferences = read32(address); + internalPtrReferences = (nbInternalPtrReferences > 0) ? reinterpret_cast<InternalReferencePtr*>(address) : NULL; + address += nbInternalPtrReferences*sizeof(InternalReferencePtr); + + nbInternalIdxReferences = read32(address); + internalIdxReferences = (nbInternalIdxReferences > 0) ? reinterpret_cast<InternalReferenceIdx*>(address) : NULL; + address += nbInternalIdxReferences*sizeof(InternalReferenceIdx); + } + + // create internal references map + PxF32 loadFactor = 0.75f; + PxF32 _loadFactor = 1.0f / loadFactor; + PxU32 hashSize = PxU32((nbInternalPtrReferences + nbInternalIdxReferences + 1)*_loadFactor); + InternalRefMap internalReferencesMap(hashSize, loadFactor); + { + //create hash (we should load the hashes directly from memory) + for (PxU32 i=0;i<nbInternalPtrReferences;i++) + { + const InternalReferencePtr& ref = internalPtrReferences[i]; + internalReferencesMap.insertUnique( InternalRefKey(ref.reference, ref.kind), SerialObjectIndex(ref.objIndex)); + } + for (PxU32 i=0;i<nbInternalIdxReferences;i++) + { + const InternalReferenceIdx& ref = internalIdxReferences[i]; + internalReferencesMap.insertUnique(InternalRefKey(ref.reference, ref.kind), SerialObjectIndex(ref.objIndex)); + } + } + + SerializationRegistry& sn = static_cast<SerializationRegistry&>(sr); + Cm::Collection* collection = static_cast<Cm::Collection*>(PxCreateCollection()); + PX_ASSERT(collection); + collection->mObjects.reserve(PxU32(nbObjectsInCollection*_loadFactor) + 1); + if(nbExportReferences > 0) + collection->mIds.reserve(PxU32(nbExportReferences*_loadFactor) + 1); + + PxU8* addressObjectData = alignPtr(address); + PxU8* addressExtraData = alignPtr(addressObjectData + objectDataEndOffset); + + DeserializationContext context(manifestTable, importReferences, addressObjectData, internalReferencesMap, externalRefs, addressExtraData, version); + + // iterate over memory containing PxBase objects, create the instances, resolve the addresses, import the external data, add to collection. + { + PxU32 nbObjects = nbObjectsInCollection; + + while(nbObjects--) + { + address = alignPtr(address); + context.alignExtraData(); + + // read PxBase header with type and get corresponding serializer. + PxBase* header = reinterpret_cast<PxBase*>(address); + const PxType classType = header->getConcreteType(); + const PxSerializer* serializer = sn.getSerializer(classType); + PX_ASSERT(serializer); + + PxBase* instance = serializer->createObject(address, context); + if (!instance) + { + Ps::getFoundation().error(physx::PxErrorCode::eINVALID_PARAMETER, __FILE__, __LINE__, + "Cannot create class instance for concrete type %d.", classType); + collection->release(); + return NULL; + } + + collection->internalAdd(instance); + } + } + + PX_ASSERT(nbObjectsInCollection == collection->internalGetNbObjects()); + + // update new collection with export references + { + PX_ASSERT(addressObjectData != NULL); + for (PxU32 i=0;i<nbExportReferences;i++) + { + bool isExternal; + PxU32 manifestIndex = exportReferences[i].objIndex.getIndex(isExternal); + PX_ASSERT(!isExternal); + PxBase* obj = reinterpret_cast<PxBase*>(addressObjectData + manifestTable[manifestIndex].offset); + collection->mIds.insertUnique(exportReferences[i].id, obj); + collection->mObjects[obj] = exportReferences[i].id; + } + } + + PxAddCollectionToPhysics(*collection); + return collection; +} diff --git a/PhysX_3.4/Source/PhysXExtensions/src/serialization/Binary/SnBinarySerialization.cpp b/PhysX_3.4/Source/PhysXExtensions/src/serialization/Binary/SnBinarySerialization.cpp new file mode 100644 index 00000000..f9a8b1b9 --- /dev/null +++ b/PhysX_3.4/Source/PhysXExtensions/src/serialization/Binary/SnBinarySerialization.cpp @@ -0,0 +1,402 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and related documentation and +// any modifications thereto. Any use, reproduction, disclosure, or +// distribution of this software and related documentation without an express +// license agreement from NVIDIA Corporation is strictly prohibited. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + +#include "PsHash.h" +#include "PsHashMap.h" +#include "CmIO.h" +#include "SnFile.h" +#include "PsString.h" +#include "PsIntrinsics.h" +#include "extensions/PxSerialization.h" +#include "SnSerializationContext.h" +#include "PxSerializer.h" +#include "serialization/SnSerialUtils.h" +#include "serialization/SnSerializationRegistry.h" +#include "SnConvX_Align.h" +#include "PxDefaultStreams.h" +#include "CmCollection.h" +#include "PxPhysicsVersion.h" +#include "PsUtilities.h" + +using namespace physx; +using namespace Cm; +using namespace Sn; + +//------------------------------------------------------------------------------------ +//// Binary Serialized PxCollection, format documentation +//------------------------------------------------------------------------------------ +// +// +//------------------------------------------------------------------------------------ +//// overview: +//// header information +//// manifest table +//// import references +//// export references +//// internal references +//// object data +//// extra data +//------------------------------------------------------------------------------------ +// +// +//------------------------------------------------------------------------------------ +//// header information: +//// header tag plus various version and platform information +//------------------------------------------------------------------------------------ +// header SEBD +// PX_PHYSICS_VERSION +// PX_BINARY_SERIAL_VERSION +// PX_BUILD_NUMBER (or 0 if not defined) +// platform tag +// markedPadding (on for PX_CHECKED) +// nbObjectsInCollection +// +// +//------------------------------------------------------------------------------------ +//// manifest table: +//// one entry per collected object +//// offsets relative to object data buffer +//------------------------------------------------------------------------------------ +// alignment +// PxU32 size +// (PxU32 offset, PxType type)*size +// PxU32 endOffset +// +// +//------------------------------------------------------------------------------------ +//// import references: +//// one entry per required reference to external collection +//------------------------------------------------------------------------------------ +// alignment +// PxU32 size +// (PxSerialObjectId id, PxType type)*size +// +// +//------------------------------------------------------------------------------------ +//// export references: +//// one entry per object in the collection with id +//// object indices point into the manifest table (objects in the same collection) +//------------------------------------------------------------------------------------ +// alignment +// PxU32 size +// (PxSerialObjectId id, SerialObjectIndex objIndex)*size +// +// +//------------------------------------------------------------------------------------ +//// internal references: +//// one entry per reference, kind pair +//// object indices point either into the manifest table or into the import references +//// depending on whether the entry references the same collection or the external one +//// one section for pointer type references and one for index type references. +//------------------------------------------------------------------------------------ +// alignment +// PxU32 sizePtrs; +// (size_t reference, PxU32 kind, SerialObjectIndex objIndex)*sizePtrs +// PxU32 sizeIdx; +// (PxU32 reference, PxU32 kind, SerialObjectIndex objIndex)*sizePtrs +// +// +//------------------------------------------------------------------------------------ +//// object data: +//// serialized PxBase derived class instances +//// each object size depends on specific class +//// offsets are stored in manifest table +//------------------------------------------------------------------------------------ +// alignment +// (PxConcreteType type, -----) +// alignment +// (PxConcreteType type, --------) +// alignment +// (PxConcreteType type, --) +// . +// . +// +// +// ----------------------------------------------------------------------------------- +//// extra data: +//// extra data memory block +//// serialized and deserialized by PxBase implementations +////---------------------------------------------------------------------------------- +// extra data +// +//------------------------------------------------------------------------------------ + +namespace +{ + + class LegacySerialStream : public PxSerializationContext + { + public: + LegacySerialStream(OutputStreamWriter& writer, + const PxCollection& collection, + bool exportNames) : mWriter(writer), mCollection(collection), mExportNames(exportNames) {} + void writeData(const void* buffer, PxU32 size) { mWriter.write(buffer, size); } + PxU32 getTotalStoredSize() { return mWriter.getStoredSize(); } + void alignData(PxU32 alignment) + { + if(!alignment) + return; + + PxI32 bytesToPad = PxI32(getPadding(getTotalStoredSize(), alignment)); + static const PxI32 BUFSIZE = 64; + char buf[BUFSIZE]; + PxMemSet(buf, 0, bytesToPad < BUFSIZE ? PxU32(bytesToPad) : PxU32(BUFSIZE)); + while(bytesToPad > 0) + { + writeData(buf, bytesToPad < BUFSIZE ? PxU32(bytesToPad) : PxU32(BUFSIZE)); + bytesToPad -= BUFSIZE; + } + PX_ASSERT(!getPadding(getTotalStoredSize(), alignment)); + } + + virtual void registerReference(PxBase&, PxU32, size_t) + { + Ps::getFoundation().error(physx::PxErrorCode::eINVALID_OPERATION, __FILE__, __LINE__, + "Cannot register references during exportData, exportExtraData."); + } + + virtual const PxCollection& getCollection() const + { + return mCollection; + } + virtual void writeName(const char* name) + { + PxU32 len = name && mExportNames ? PxU32(strlen(name)) + 1 : 0; + writeData(&len, sizeof(len)); + if(len) writeData(name, len); + } + + private: + LegacySerialStream& operator=(const LegacySerialStream&); + OutputStreamWriter& mWriter; + const PxCollection& mCollection; + bool mExportNames; + }; + + void writeHeader(PxSerializationContext& stream, bool hasDeserializedAssets) + { + PX_UNUSED(hasDeserializedAssets); + struct Header + { + PxU32 header; + PxU32 version; + PxU32 binaryVersion; + PxU32 buildNumber; + PxU32 platformTag; + PxU32 markedPadding; + PxU32 materialOffset; + }; + + //serialized binary data. + const PxU32 header = PX_MAKE_FOURCC('S','E','B','D'); + stream.writeData(&header, sizeof(PxU32)); + + PxU32 version = PX_PHYSICS_VERSION; + stream.writeData(&version, sizeof(PxU32)); + + PxU32 binaryVersion = PX_BINARY_SERIAL_VERSION; + stream.writeData(&binaryVersion, sizeof(PxU32)); + + PxU32 buildNumber = 0; +#if defined(PX_BUILD_NUMBER) + buildNumber = PX_BUILD_NUMBER; +#endif + stream.writeData(&buildNumber, sizeof(PxU32)); + + PxU32 platformTag = getBinaryPlatformTag(); + stream.writeData(&platformTag, sizeof(PxU32)); + + PxU32 markedPadding = 0; +#if PX_CHECKED + if(!hasDeserializedAssets) + markedPadding = 1; +#endif + stream.writeData(&markedPadding, sizeof(PxU32)); + } +} + +bool PxSerialization::serializeCollectionToBinary(PxOutputStream& outputStream, PxCollection& pxCollection, PxSerializationRegistry& sr, const PxCollection* pxExternalRefs, bool exportNames) +{ + if(!PxSerialization::isSerializable(pxCollection, sr, pxExternalRefs)) + return false; + + Collection& collection = static_cast<Collection&>(pxCollection); + const Collection* externalRefs = static_cast<const Collection*>(pxExternalRefs); + + //temporary memory stream which allows fixing up data up stream + + SerializationRegistry& sn = static_cast<SerializationRegistry&>(sr); + + // sort collection by "order" value (this will be the order in which they get serialized) + sortCollection(collection, sn, false); + + //initialized the context with the sorted collection. + SerializationContext context(collection, externalRefs); + + // gather reference information + bool hasDeserializedAssets = false; + { + const PxU32 nb = collection.internalGetNbObjects(); + for(PxU32 i=0;i<nb;i++) + { + PxBase* s = collection.internalGetObject(i); + PX_ASSERT(s && s->getConcreteType()); +#if PX_CHECKED + //can't guarantee marked padding for deserialized instances + if(!(s->getBaseFlags() & PxBaseFlag::eOWNS_MEMORY)) + hasDeserializedAssets = true; +#endif + const PxSerializer* serializer = sn.getSerializer(s->getConcreteType()); + PX_ASSERT(serializer); + serializer->registerReferences(*s, context); + } + } + + // now start the actual serialization into the output stream + OutputStreamWriter writer(outputStream); + LegacySerialStream stream(writer, collection, exportNames); + + writeHeader(stream, hasDeserializedAssets); + + // write size of collection + stream.alignData(PX_SERIAL_ALIGN); + PxU32 nbObjectsInCollection = collection.internalGetNbObjects(); + stream.writeData(&nbObjectsInCollection, sizeof(PxU32)); + + // write the manifest table (PxU32 offset, PxConcreteType type) + { + Ps::Array<ManifestEntry> manifestTable(collection.internalGetNbObjects()); + PxU32 headerOffset = 0; + for(PxU32 i=0;i<collection.internalGetNbObjects();i++) + { + PxBase* s = collection.internalGetObject(i); + PX_ASSERT(s && s->getConcreteType()); + PxType concreteType = s->getConcreteType(); + const PxSerializer* serializer = sn.getSerializer(concreteType); + PX_ASSERT(serializer); + manifestTable[i] = ManifestEntry(headerOffset, concreteType); + PxU32 classSize = PxU32(serializer->getClassSize()); + headerOffset += getPadding(classSize, PX_SERIAL_ALIGN) + classSize; + } + stream.alignData(PX_SERIAL_ALIGN); + const PxU32 nb = manifestTable.size(); + stream.writeData(&nb, sizeof(PxU32)); + stream.writeData(manifestTable.begin(), manifestTable.size()*sizeof(ManifestEntry)); + + //store offset for end of object buffer (PxU32 offset) + stream.writeData(&headerOffset, sizeof(PxU32)); + } + + // write import references + { + const Ps::Array<ImportReference>& importReferences = context.getImportReferences(); + stream.alignData(PX_SERIAL_ALIGN); + const PxU32 nb = importReferences.size(); + stream.writeData(&nb, sizeof(PxU32)); + stream.writeData(importReferences.begin(), importReferences.size()*sizeof(ImportReference)); + } + + // write export references + { + PxU32 nbIds = collection.getNbIds(); + Ps::Array<ExportReference> exportReferences(nbIds); + //we can't get quickly from id to object index in collection. + //if we only need this here, its not worth to build a hash + nbIds = 0; + for (PxU32 i=0;i<collection.getNbObjects();i++) + { + PxBase& obj = collection.getObject(i); + PxSerialObjectId id = collection.getId(obj); + if (id != PX_SERIAL_OBJECT_ID_INVALID) + { + SerialObjectIndex objIndex(i, false); //i corresponds to manifest entry + exportReferences[nbIds++] = ExportReference(id, objIndex); + } + } + stream.alignData(PX_SERIAL_ALIGN); + stream.writeData(&nbIds, sizeof(PxU32)); + stream.writeData(exportReferences.begin(), exportReferences.size()*sizeof(ExportReference)); + } + + // write internal references + { + InternalRefMap& internalReferencesPtrMap = context.getInternalReferencesPtrMap(); + Ps::Array<InternalReferencePtr> internalReferencesPtr(internalReferencesPtrMap.size()); + PxU32 nbInternalPtrReferences = 0; + for(InternalRefMap::Iterator iter = internalReferencesPtrMap.getIterator(); !iter.done(); ++iter) + internalReferencesPtr[nbInternalPtrReferences++] = InternalReferencePtr(iter->first.first, iter->first.second, iter->second); + + InternalRefMap& internalReferencesIdxMap = context.getInternalReferencesIdxMap(); + Ps::Array<InternalReferenceIdx> internalReferencesIdx(internalReferencesIdxMap.size()); + PxU32 nbInternalIdxReferences = 0; + for(InternalRefMap::Iterator iter = internalReferencesIdxMap.getIterator(); !iter.done(); ++iter) + internalReferencesIdx[nbInternalIdxReferences++] = InternalReferenceIdx(Ps::to32(iter->first.first), iter->first.second, iter->second); + + stream.alignData(PX_SERIAL_ALIGN); + + stream.writeData(&nbInternalPtrReferences, sizeof(PxU32)); + stream.writeData(internalReferencesPtr.begin(), internalReferencesPtr.size()*sizeof(InternalReferencePtr)); + + stream.writeData(&nbInternalIdxReferences, sizeof(PxU32)); + stream.writeData(internalReferencesIdx.begin(), internalReferencesIdx.size()*sizeof(InternalReferenceIdx)); + } + + // write object data + { + stream.alignData(PX_SERIAL_ALIGN); + const PxU32 nb = collection.internalGetNbObjects(); + for(PxU32 i=0;i<nb;i++) + { + PxBase* s = collection.internalGetObject(i); + PX_ASSERT(s && s->getConcreteType()); + const PxSerializer* serializer = sn.getSerializer(s->getConcreteType()); + PX_ASSERT(serializer); + stream.alignData(PX_SERIAL_ALIGN); + serializer->exportData(*s, stream); + } + } + + // write extra data + { + const PxU32 nb = collection.internalGetNbObjects(); + for(PxU32 i=0;i<nb;i++) + { + PxBase* s = collection.internalGetObject(i); + PX_ASSERT(s && s->getConcreteType()); + + const PxSerializer* serializer = sn.getSerializer(s->getConcreteType()); + PX_ASSERT(serializer); + + stream.alignData(PX_SERIAL_ALIGN); + serializer->exportExtraData(*s, stream); + } + } + + return true; +} diff --git a/PhysX_3.4/Source/PhysXExtensions/src/serialization/Binary/SnConvX.cpp b/PhysX_3.4/Source/PhysXExtensions/src/serialization/Binary/SnConvX.cpp new file mode 100644 index 00000000..ad486c2d --- /dev/null +++ b/PhysX_3.4/Source/PhysXExtensions/src/serialization/Binary/SnConvX.cpp @@ -0,0 +1,156 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and related documentation and +// any modifications thereto. Any use, reproduction, disclosure, or +// distribution of this software and related documentation without an express +// license agreement from NVIDIA Corporation is strictly prohibited. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 NVIDIA Corporation. All rights reserved. + +/* +- get rid of STL + +- NpArticulationLinkArray with more than 4 entries +- big convexes Xbox => PC + +- put a cache in "convertClass" function +- remove MD one at a time and check what happens in the converter. Make it robust/report errors +- for xbox, compare against source xbox file if it exists +- maybe put some info in the header to display "File generated by ConvX 1.xx" on screen (to debug) +- report inconsistent naming convention in each class!!!! +- try to automatically discover padding bytes? use "0xcd" pattern? +* do last param of XXXX_ITEMS macro automatically +- what if source files are 64bits? can we safely convert a 64bit ptr to 32bit? +*/ + +#include "foundation/PxErrorCallback.h" +#include "foundation/PxAllocatorCallback.h" +#include "foundation/PxIO.h" +#include "SnConvX.h" +#include "serialization/SnSerializationRegistry.h" +#include <assert.h> +#include "PsFoundation.h" + +using namespace physx; + +Sn::ConvX::ConvX() : + mMetaData_Src (NULL), + mMetaData_Dst (NULL), + mOutStream (NULL), + mMustFlip (false), + mOutputSize (0), + mSrcPtrSize (0), + mDstPtrSize (0), + mNullPtr (false), + mNoOutput (false), + mMarkedPadding (false), + mNbErrors (0), + mNbWarnings (0), + mReportMode (PxConverterReportMode::eNORMAL), + mPerformConversion (true) +{ + // memset(mZeros, 0, CONVX_ZERO_BUFFER_SIZE); + memset(mZeros, 0x42, CONVX_ZERO_BUFFER_SIZE); +} + +Sn::ConvX::~ConvX() +{ + resetNbErrors(); + resetConvexFlags(); + releaseMetaData(); + resetUnions(); +} + +void Sn::ConvX::release() +{ + delete this; +} + +bool Sn::ConvX::setMetaData(PxInputStream& inputStream, MetaDataType type) +{ + resetNbErrors(); + return (loadMetaData(inputStream, type) != NULL); +} + +bool Sn::ConvX::setMetaData(PxInputStream& srcMetaData, PxInputStream& dstMetaData) +{ + releaseMetaData(); + resetUnions(); + + if(!setMetaData(srcMetaData, META_DATA_SRC)) + return false; + if(!setMetaData(dstMetaData, META_DATA_DST)) + return false; + + return true; +} + + +bool Sn::ConvX::convert(PxInputStream& srcStream, PxU32 srcSize, PxOutputStream& targetStream) +{ + if(!mMetaData_Src || !mMetaData_Dst) + { + Ps::getFoundation().error(PxErrorCode::eINVALID_OPERATION, __FILE__, __LINE__, + "PxBinaryConverter: metadata not defined. Call PxBinaryConverter::setMetaData first.\n"); + return false; + } + + resetConvexFlags(); + resetNbErrors(); + + bool conversionStatus = false; + if(mPerformConversion) + { + if(srcSize == 0) + { + Ps::getFoundation().error(PxErrorCode::eINVALID_PARAMETER, __FILE__, __LINE__, + "PxBinaryConverter: source serialized data size is zero.\n"); + return false; + } + + void* memory = PX_ALLOC_TEMP(srcSize+ALIGN_FILE, "ConvX source file"); + void* memoryA = reinterpret_cast<void*>((size_t(memory) + ALIGN_FILE)&~(ALIGN_FILE-1)); + + const PxU32 nbBytesRead = srcStream.read(memoryA, srcSize); + if(nbBytesRead != srcSize) + { + Ps::getFoundation().error(PxErrorCode::eINVALID_PARAMETER, __FILE__, __LINE__, + "PxBinaryConverter: failure on reading source serialized data.\n"); + PX_FREE(memory); + return false; + } + + displayMessage(PxErrorCode::eDEBUG_INFO, "\n\nConverting...\n\n"); + + { + if(!initOutput(targetStream)) + { + PX_FREE(memory); + return false; + } + conversionStatus = convert(memoryA, int(srcSize)); + closeOutput(); + } + + PX_FREE(memory); + } + return conversionStatus; +} diff --git a/PhysX_3.4/Source/PhysXExtensions/src/serialization/Binary/SnConvX.h b/PhysX_3.4/Source/PhysXExtensions/src/serialization/Binary/SnConvX.h new file mode 100644 index 00000000..9ce9d86f --- /dev/null +++ b/PhysX_3.4/Source/PhysXExtensions/src/serialization/Binary/SnConvX.h @@ -0,0 +1,182 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and related documentation and +// any modifications thereto. Any use, reproduction, disclosure, or +// distribution of this software and related documentation without an express +// license agreement from NVIDIA Corporation is strictly prohibited. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 NVIDIA Corporation. All rights reserved. + +#ifndef PX_CONVX_H +#define PX_CONVX_H + +#include "foundation/PxErrors.h" +#include "PxBinaryConverter.h" +#include "PxTypeInfo.h" +#include "CmPhysXCommon.h" +#include "PsUserAllocated.h" +#include "PsArray.h" +#include "SnConvX_Common.h" +#include "SnConvX_Union.h" +#include "SnConvX_MetaData.h" +#include "SnConvX_Align.h" + +#define CONVX_ZERO_BUFFER_SIZE 256 + +namespace physx { + +class PxSerializationRegistry; + +namespace Sn { + + struct HeightFieldData; + class PointerRemap + { + public: + PointerRemap(); + ~PointerRemap(); + + bool checkRefIsNotUsed(PxU32 ref) const; + void setObjectRef(PxU64 object64, PxU32 ref); + bool getObjectRef(PxU64 object64, PxU32& ref) const; + + struct InternalData + { + PxU64 object; + PxU32 id; + }; + + Ps::Array<InternalData> mData; + }; + + class ConvX : public physx::PxBinaryConverter, public shdfnd::UserAllocated + { + public: + ConvX(); + virtual ~ConvX(); + + virtual void release(); + virtual void setReportMode(PxConverterReportMode::Enum mode) { mReportMode = mode; } + PX_FORCE_INLINE bool silentMode() const { return mReportMode==PxConverterReportMode::eNONE; } + PX_FORCE_INLINE bool verboseMode() const { return mReportMode==PxConverterReportMode::eVERBOSE; } + + virtual bool setMetaData(PxInputStream& srcMetaData, PxInputStream& dstMetaData); + virtual bool convert(PxInputStream& srcStream, PxU32 srcSize, PxOutputStream& targetStream); + + private: + ConvX& operator=(const ConvX&); + bool setMetaData(PxInputStream& inputStream, MetaDataType type); + + // Meta-data + void releaseMetaData(); + const MetaData* loadMetaData(PxInputStream& inputStream, MetaDataType type); + const MetaData* getBinaryMetaData(MetaDataType type); + int getNbMetaClasses(MetaDataType type); + MetaClass* getMetaClass(unsigned int i, MetaDataType type) const; + MetaClass* getMetaClass(const char* name, MetaDataType type) const; + MetaClass* getMetaClass(PxConcreteType::Enum concreteType, MetaDataType type); + MetaData* mMetaData_Src; + MetaData* mMetaData_Dst; + + // Convert + + bool convert(const void* buffer, int fileSize); + void resetConvexFlags(); + void _enumerateFields(const MetaClass* mc, ExtraDataEntry2* entries, int& nb, int baseOffset, MetaDataType type) const; + void _enumerateExtraData(const char* address, const MetaClass* mc, ExtraDataEntry* entries, int& nb, int offset, MetaDataType type) const; + PxU64 read64(const void*& buffer); + int read32(const void*& buffer); + short read16(const void*& buffer); + bool convertClass(const char* buffer, const MetaClass* mc, int offset); + const char* convertExtraData_Array(const char* Address, const char* lastAddress, const char* objectAddress, const ExtraDataEntry& ed); + const char* convertExtraData_Ptr(const char* Address, const char* lastAddress, const PxMetaDataEntry& entry, int count, int ptrSize_Src, int ptrSize_Dst); + int getConcreteType(const char* buffer); + bool convertCollection(const void* buffer, int fileSize, int nbObjects); + const void* convertManifestTable(const void* buffer, int& fileSize); + const void* convertImportReferences(const void* buffer, int& fileSize); + const void* convertExportReferences(const void* buffer, int& fileSize); + const void* convertInternalReferences(const void* buffer, int& fileSize); + const void* convertReferenceTables(const void* buffer, int& fileSize, int& nbObjectsInCollection); + bool checkPaddingBytes(const char* buffer, int byteCount); + + // ---- big convex surgery ---- + PsArray<bool> mConvexFlags; + // Align + const char* alignStream(const char* buffer, int alignment=ALIGN_DEFAULT); + void alignTarget(int alignment); + + char mZeros[CONVX_ZERO_BUFFER_SIZE]; + // Unions + bool registerUnion(const char* name); + bool registerUnionType(const char* unionName, const char* typeName, int typeValue); + const char* getTypeName(const char* unionName, int typeValue); + void resetUnions(); + PsArray<Union> mUnions; + // Output + void setNullPtr(bool); + void setNoOutput(bool); + bool initOutput(PxOutputStream& targetStream); + void closeOutput(); + int getCurrentOutputSize(); + void output(short value); + void output(int value); + void output(PxU64 value); + void output(const char* buffer, int nbBytes); + void convert8 (const char* src, const PxMetaDataEntry& entry, const PxMetaDataEntry& dstEntry); + void convertPad8 (const char* src, const PxMetaDataEntry& entry, const PxMetaDataEntry& dstEntry); + void convert16 (const char* src, const PxMetaDataEntry& entry, const PxMetaDataEntry& dstEntry); + void convert32 (const char* src, const PxMetaDataEntry& entry, const PxMetaDataEntry& dstEntry); + void convert64 (const char* src, const PxMetaDataEntry& entry, const PxMetaDataEntry& dstEntry); + void convertFloat(const char* src, const PxMetaDataEntry& entry, const PxMetaDataEntry& dstEntry); + void convertPtr (const char* src, const PxMetaDataEntry& entry, const PxMetaDataEntry& dstEntry); + PxOutputStream* mOutStream; + bool mMustFlip; + int mOutputSize; + int mSrcPtrSize; + int mDstPtrSize; + bool mNullPtr; + bool mNoOutput; + bool mMarkedPadding; + + // Errors + void resetNbErrors(); + int getNbErrors() const; + void displayMessage(physx::PxErrorCode::Enum code, const char* format, ...); + int mNbErrors; + int mNbWarnings; + + // Settings + PxConverterReportMode::Enum mReportMode; + bool mPerformConversion; + + // Remap pointers + void exportIntAsPtr(int value); + void exportInt(int value); + void exportInt64(PxU64 value); + PointerRemap mRemap; + PointerRemap* mActiveRemap; + PxU32 mPointerRemapCounter; + + friend class MetaData; + friend struct MetaClass; + }; +} } +#endif diff --git a/PhysX_3.4/Source/PhysXExtensions/src/serialization/Binary/SnConvX_Align.cpp b/PhysX_3.4/Source/PhysXExtensions/src/serialization/Binary/SnConvX_Align.cpp new file mode 100644 index 00000000..5c576f5c --- /dev/null +++ b/PhysX_3.4/Source/PhysXExtensions/src/serialization/Binary/SnConvX_Align.cpp @@ -0,0 +1,63 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and related documentation and +// any modifications thereto. Any use, reproduction, disclosure, or +// distribution of this software and related documentation without an express +// license agreement from NVIDIA Corporation is strictly prohibited. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 NVIDIA Corporation. All rights reserved. + +#include "SnConvX.h" +#include "SnConvX_Align.h" +#include <assert.h> +using namespace physx; + +void Sn::ConvX::alignTarget(int alignment) +{ + const int outputSize = getCurrentOutputSize(); + const PxU32 outPadding = getPadding(size_t(outputSize), PxU32(alignment)); + if(outPadding) + { + assert(outPadding<CONVX_ZERO_BUFFER_SIZE); + output(mZeros, int(outPadding)); + } +} + +const char* Sn::ConvX::alignStream(const char* buffer, int alignment) +{ + const PxU32 padding = getPadding(size_t(buffer), PxU32(alignment)); + assert(!getPadding(size_t(buffer + padding), PxU32(alignment))); + + const int outputSize = getCurrentOutputSize(); + const PxU32 outPadding = getPadding(size_t(outputSize), PxU32(alignment)); + if(outPadding==padding) + { + assert(outPadding<CONVX_ZERO_BUFFER_SIZE); + output(mZeros, int(outPadding)); + } + else if(outPadding) + { + assert(outPadding<CONVX_ZERO_BUFFER_SIZE); + output(mZeros, int(outPadding)); + } + + return buffer + padding; +} diff --git a/PhysX_3.4/Source/PhysXExtensions/src/serialization/Binary/SnConvX_Align.h b/PhysX_3.4/Source/PhysXExtensions/src/serialization/Binary/SnConvX_Align.h new file mode 100644 index 00000000..b3ec81c2 --- /dev/null +++ b/PhysX_3.4/Source/PhysXExtensions/src/serialization/Binary/SnConvX_Align.h @@ -0,0 +1,44 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and related documentation and +// any modifications thereto. Any use, reproduction, disclosure, or +// distribution of this software and related documentation without an express +// license agreement from NVIDIA Corporation is strictly prohibited. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 NVIDIA Corporation. All rights reserved. + +#ifndef PX_CONVX_ALIGN_H +#define PX_CONVX_ALIGN_H + +namespace physx { namespace Sn { + #define ALIGN_DEFAULT 16 + #define ALIGN_FILE 128 + + PX_INLINE PxU32 getPadding(size_t value, PxU32 alignment) + { + const PxU32 mask = alignment-1; + const PxU32 overhead = PxU32(value) & mask; + return (alignment - overhead) & mask; + } + +} } + +#endif diff --git a/PhysX_3.4/Source/PhysXExtensions/src/serialization/Binary/SnConvX_Common.h b/PhysX_3.4/Source/PhysXExtensions/src/serialization/Binary/SnConvX_Common.h new file mode 100644 index 00000000..677480e4 --- /dev/null +++ b/PhysX_3.4/Source/PhysXExtensions/src/serialization/Binary/SnConvX_Common.h @@ -0,0 +1,43 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and related documentation and +// any modifications thereto. Any use, reproduction, disclosure, or +// distribution of this software and related documentation without an express +// license agreement from NVIDIA Corporation is strictly prohibited. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 NVIDIA Corporation. All rights reserved. + +#ifndef PX_CONVX_COMMON_H +#define PX_CONVX_COMMON_H + +#if PX_VC +#pragma warning(disable:4121) // alignment of a member was sensitive to packing +#endif + +#include "common/PxPhysXCommonConfig.h" + +#define DELETESINGLE(x) if(x){ delete x; x = NULL; } +#define DELETEARRAY(x) if(x){ delete []x; x = NULL; } + +#define inline_ PX_FORCE_INLINE +#define PsArray physx::shdfnd::Array + +#endif diff --git a/PhysX_3.4/Source/PhysXExtensions/src/serialization/Binary/SnConvX_Convert.cpp b/PhysX_3.4/Source/PhysXExtensions/src/serialization/Binary/SnConvX_Convert.cpp new file mode 100644 index 00000000..a9fe0b9c --- /dev/null +++ b/PhysX_3.4/Source/PhysXExtensions/src/serialization/Binary/SnConvX_Convert.cpp @@ -0,0 +1,1434 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and related documentation and +// any modifications thereto. Any use, reproduction, disclosure, or +// distribution of this software and related documentation without an express +// license agreement from NVIDIA Corporation is strictly prohibited. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 NVIDIA Corporation. All rights reserved. + +#include "foundation/PxErrorCallback.h" +#include "SnConvX.h" +#include "serialization/SnSerialUtils.h" +#include "PsAlloca.h" +#include "CmUtils.h" +#include "PxDefaultStreams.h" +#include <assert.h> + +using namespace physx; +using namespace physx::Sn; +using namespace Cm; + +void Sn::ConvX::resetConvexFlags() +{ + mConvexFlags.clear(); +} + +void Sn::ConvX::_enumerateFields(const MetaClass* mc, ExtraDataEntry2* entries, int& nb, int baseOffset, MetaDataType type) const +{ + PxU32 nbFields = mc->mFields.size(); + int offsetCheck = baseOffset; + for(PxU32 j=0;j<nbFields;j++) + { + const PxMetaDataEntry& entry = mc->mFields[j]; + if(entry.mFlags & PxMetaDataFlag::eCLASS || entry.mFlags & PxMetaDataFlag::eEXTRA_DATA) + continue; + + assert(offsetCheck == baseOffset + entry.mOffset); + + int currentOffset = baseOffset + entry.mOffset; + + //for(int c=0;c<entry.mCount;c++) + { + if(entry.mFlags & PxMetaDataFlag::eUNION) + { + entries[nb].entry = entry; + entries[nb].offset = currentOffset; + entries[nb].cb = 0; + nb++; + } + else if(entry.mFlags & PxMetaDataFlag::ePTR) // This also takes care of the vtable pointer + { + entries[nb].entry = entry; + entries[nb].offset = currentOffset; + entries[nb].cb = &Sn::ConvX::convertPtr; + nb++; + } + else + { + MetaClass* fieldType = getMetaClass(entry.mType, type); + assert(fieldType); + if(fieldType->mCallback) + { + entries[nb].entry = entry; + entries[nb].offset = currentOffset; + entries[nb].cb = fieldType->mCallback; + nb++; + } + else + { + for(int c=0;c<entry.mCount;c++) + { + _enumerateFields(fieldType, entries, nb, currentOffset, type); + currentOffset += entry.mSize/entry.mCount; + } + } + } + } + offsetCheck += entry.mSize; + } +} + +void Sn::ConvX::_enumerateExtraData(const char* address, const MetaClass* mc, ExtraDataEntry* entries, + int& nb, int offset, MetaDataType type) const +{ + PxU32 nbFields = mc->mFields.size(); + for(PxU32 j=0;j<nbFields;j++) + { + const PxMetaDataEntry& entry = mc->mFields[j]; + if(entry.mFlags & PxMetaDataFlag::eCLASS /*|| entry.mFlags & PxMetaDataFlag::ePTR*/ || entry.mFlags & PxMetaDataFlag::eTYPEDEF) + continue; + + const char* entryType = entry.mType; + + // + // Insanely Twisted Shadow GeometryUnion + // + // Special code is needed as long as there are no meta data tags to describe our unions properly. The way it is done here is + // not future-proof at all. There should be a tag to describe where the union type can be found and the number of bytes + // this type id needs. Then a mapping needs to get added from each union type id to the proper meta class name. + // + if (entry.mFlags & PxMetaDataFlag::eUNION) + { + if (!mc->mClassName || strcmp(mc->mClassName, "Gu::GeometryUnion")!=0) + continue; + else + { + // ### hardcoded bit here, will only work when union type is the first int of the struct + const int* tmp = reinterpret_cast<const int*>(address + offset); + const int unionType = *tmp; + + ConvX* tmpConv = const_cast<ConvX*>(this); // ... don't ask + const char* typeName = tmpConv->getTypeName(entry.mType, unionType); + assert(typeName); + + bool isTriMesh = (strcmp(typeName, "PxTriangleMeshGeometryLL") == 0); + bool isHeightField = (strcmp(typeName, "PxHeightFieldGeometryLL") == 0); + if (!isTriMesh && !isHeightField) + { + continue; + } + else + { + entryType = typeName; + } + } + } + + // MetaClass* extraDataType = getMetaClass(entry.mType, type); + // if(!extraDataType) + // continue; + + if(entry.mFlags & PxMetaDataFlag::eEXTRA_DATA) + { + entries[nb].entry = entry; + entries[nb].offset = offset+entry.mOffset; + nb++; + } + else + { + if(entry.mFlags & PxMetaDataFlag::ePTR) + continue; + + MetaClass* extraDataType = getMetaClass(entryType, type); + if(!extraDataType) + continue; + + if(!extraDataType->mCallback) + _enumerateExtraData(address, extraDataType, entries, nb, offset+entry.mOffset, type); + } + } +} + +PxU64 Sn::ConvX::read64(const void*& buffer) +{ + const PxU64* buf64 = reinterpret_cast<const PxU64*>(buffer); + buffer = reinterpret_cast<const void*>(size_t(buffer) + sizeof(PxU64)); + PxU64 value = *buf64; + output(value); + return value; +} + +int Sn::ConvX::read32(const void*& buffer) +{ + const int* buf32 = reinterpret_cast<const int*>(buffer); + buffer = reinterpret_cast<const void*>(size_t(buffer) + sizeof(int)); + int value = *buf32; + output(value); + return value; +} + +short Sn::ConvX::read16(const void*& buffer) +{ + const short* buf16 = reinterpret_cast<const short*>(buffer); + buffer = reinterpret_cast<const void*>(size_t(buffer) + sizeof(short)); + short value = *buf16; + output(value); + return value; +} + +#if PX_CHECKED +extern const char* gVTable; +static bool compareEntries(const ExtraDataEntry2& e0, const ExtraDataEntry2& e1) +{ + if(e0.entry.isVTablePtr() && e1.entry.isVTablePtr()) + return true; + + if((e0.entry.mFlags & PxMetaDataFlag::eUNION) && (e1.entry.mFlags & PxMetaDataFlag::eUNION)) + { + if(e0.entry.mType && e1.entry.mType) + { + // We can't compare the ptrs since they index different string tables + if(strcmp(e0.entry.mType, e1.entry.mType)==0) + return true; + } + return false; + } + + if(e0.entry.mName && e1.entry.mName) + { + // We can't compare the ptrs since they index different string tables + if(strcmp(e0.entry.mName, e1.entry.mName)==0) + return true; + } + return false; +} +#endif + +// TODO: optimize this +bool Sn::ConvX::convertClass(const char* buffer, const MetaClass* mc, int offset) +{ + // ---- big convex surgery ---- + bool convexSurgery = false; + bool foundNbVerts = false; + bool removeBigData = false; + + // force reference + (void)foundNbVerts; + + displayMessage(PxErrorCode::eDEBUG_INFO, "%s\n", mc->mClassName); + displayMessage(PxErrorCode::eDEBUG_INFO, "+++++++++++++++++++++++++++++++++++++++++++++\n"); + + if(strcmp(mc->mClassName, "ConvexMesh")==0) + { + convexSurgery = true; + } + // ---- big convex surgery ---- + + int nbSrcEntries = 0; + PX_ALLOCA(srcEntries, ExtraDataEntry2, 256); // ### painful ctors here + int nbDstEntries = 0; + PX_ALLOCA(dstEntries, ExtraDataEntry2, 256); // ### painful ctors here + // Find corresponding meta-class for target platform + const MetaClass* target_mc = getMetaClass(mc->mClassName, META_DATA_DST); + assert(target_mc); + + if(mc->mCallback) + { + srcEntries[0].cb = mc->mCallback; + srcEntries[0].offset = offset; + srcEntries[0].entry.mType = mc->mClassName; + srcEntries[0].entry.mName = mc->mClassName; + srcEntries[0].entry.mOffset = offset; + srcEntries[0].entry.mSize = mc->mSize; + srcEntries[0].entry.mCount = 1; + srcEntries[0].entry.mFlags = 0; + nbSrcEntries = 1; + + assert(target_mc->mCallback); + dstEntries[0].cb = target_mc->mCallback; + dstEntries[0].offset = offset; + dstEntries[0].entry.mType = target_mc->mClassName; + dstEntries[0].entry.mName = target_mc->mClassName; + dstEntries[0].entry.mOffset = offset; + dstEntries[0].entry.mSize = target_mc->mSize; + dstEntries[0].entry.mCount = 1; + dstEntries[0].entry.mFlags = 0; + nbDstEntries = 1; + } + else + { + nbSrcEntries = 0; + _enumerateFields(mc, srcEntries, nbSrcEntries, 0, META_DATA_SRC); + assert(nbSrcEntries<256); + + nbDstEntries = 0; + _enumerateFields(target_mc, dstEntries, nbDstEntries, 0, META_DATA_DST); + assert(nbDstEntries<256); + + // nb = mc->mNbEntries; + // assert(nb>=0); + // memcpy(entries, mc->mEntries, nb*sizeof(ExtraDataEntry2)); + } + + int srcOffsetCheck = 0; + int dstOffsetCheck = 0; + int j = 0; + // Track cases where the vtable pointer location is different for different platforms. + // The variables indicate whether a platform has a vtable pointer entry that has not been converted yet + // and they will remember the index of the corrssponding entry. This works because there can only + // be one open vtable pointer entry at a time. + int srcOpenVTablePtrEntry = -1; + int dstOpenVTablePtrEntry = -1; + + //if the src and dst platform place the vtable pointers at different locations some fiddling with the iteration count can be necessary. + int addVTablePtrShiftIteration = 0; + const int maxNb = nbSrcEntries > nbDstEntries ? nbSrcEntries : nbDstEntries; + for(int i=0; i < (maxNb + addVTablePtrShiftIteration); i++) + { + + if (i < nbSrcEntries) + { + displayMessage(PxErrorCode::eDEBUG_INFO, "\t0x%p\t%x\t%d\t%d\t%s", buffer + srcOffsetCheck, + buffer[srcOffsetCheck], srcOffsetCheck, srcEntries[i].entry.mOffset, srcEntries[i].entry.mName); + for (int byteCount = 1; byteCount < srcEntries[i].entry.mSize; ++byteCount) + displayMessage(PxErrorCode::eDEBUG_INFO, "\t0x%p\t%x\t%d\t%d\t.", buffer + srcOffsetCheck + byteCount, + buffer[srcOffsetCheck + byteCount], srcOffsetCheck + byteCount, srcEntries[i].entry.mOffset + byteCount); + } + + bool handlePadding = true; + bool skipLoop = false; + while(handlePadding) + { + const int pad0 = i<nbSrcEntries ? srcEntries[i].entry.mFlags & PxMetaDataFlag::ePADDING : 0; + const int pad1 = j<nbDstEntries ? dstEntries[j].entry.mFlags & PxMetaDataFlag::ePADDING : 0; + if(pad0 || pad1) + { + if(pad0) + { +#if PX_CHECKED + if (mMarkedPadding && (strcmp(srcEntries[i].entry.mType, "paddingByte")==0)) + if(!checkPaddingBytes(buffer + srcOffsetCheck, srcEntries[i].entry.mSize)) + { + if(i>0) + { + displayMessage(PxErrorCode::eDEBUG_WARNING, + "PxBinaryConverter warning: Bytes after %s::%s don't look like padding bytes. Likely mismatch between binary data and metadata.\n", + mc->mClassName, srcEntries[i-1].entry.mName ); + } + else + displayMessage(PxErrorCode::eDEBUG_WARNING, + "PxBinaryConverter warning: Bytes after %s don't look like padding bytes. Likely mismatch between binary data and metadata.\n", + mc->mClassName); + + } +#endif + if(pad1) + { + // Both have padding + // ### check sizes, output bytes + if(srcEntries[i].entry.mSize==dstEntries[j].entry.mSize) + { + // I guess we can just go on with the normal code here + handlePadding = false; + } + else + { + // Output padding + assert(srcEntries[i].cb); + assert(srcEntries[i].offset == srcOffsetCheck); + + const int padSize = dstEntries[j].entry.mSize; + char* paddingBytes = reinterpret_cast<char*>(PX_ALLOC(sizeof(char)*padSize, "paddingByte")); + memset(paddingBytes, 0, size_t(padSize)); + assert(dstEntries[j].cb); + (this->*dstEntries[j].cb)(paddingBytes, dstEntries[j].entry, dstEntries[j].entry); + assert(dstOffsetCheck==dstEntries[j].offset); + dstOffsetCheck += padSize; + PX_FREE(paddingBytes); + + // srcEntries[i].cb(buffer+srcOffsetCheck, srcEntries[i].entry, dstEntries[j].entry); + // assert(dstOffsetCheck==dstEntries[j].offset); + // dstOffsetCheck += dstEntries[j].entry.mSize; + srcOffsetCheck += srcEntries[i].entry.mSize; + + // Skip dest padding field + j++; + + // continue; // ### BUG, doesn't go back to the "for" + skipLoop = true; + handlePadding = false; + } + } + else + { + // Src has padding, dst has not => skip conversion + // Don't increase j + skipLoop = true; + handlePadding = false; + srcOffsetCheck += srcEntries[i].entry.mSize; + } + } + else + { + if(pad1) + { + // Dst has padding, src has not + + // Output padding + const int padSize = dstEntries[j].entry.mSize; + char* paddingBytes = reinterpret_cast<char*>(PX_ALLOC(sizeof(char)*padSize, "paddingByte")); + memset(paddingBytes, 0, size_t(padSize)); + assert(dstEntries[j].cb); + (this->*dstEntries[j].cb)(paddingBytes, dstEntries[j].entry, dstEntries[j].entry); + assert(dstOffsetCheck==dstEntries[j].offset); + dstOffsetCheck += padSize; + PX_FREE(paddingBytes); + + // Skip dest padding field, keep same src field + j++; + } + else + { + assert(0); + } + } + } + else handlePadding = false; + } + + if(skipLoop) + continue; + + int modSrcOffsetCheck = srcOffsetCheck; + const ExtraDataEntry2* srcEntryPtr = &srcEntries[i]; + const ExtraDataEntry2* dstEntryPtr = &dstEntries[j]; + + bool isSrcVTablePtr = (i < nbSrcEntries) ? srcEntryPtr->entry.isVTablePtr() : false; + if (isSrcVTablePtr && (dstOpenVTablePtrEntry != -1)) + { + // vtable ptr position mismatch: + // this check is necessary to align src and dst index again when the + // dst vtable pointer has been written already and the src vtable ptr + // element is reached. + // + // i + // src: | a | b | vt-ptr | c | ... + // dst: | vt-ptr | a | b | c | ... + // j + // + // it needs special treatment because the following case fails otherwise + // i + // src: | a | b | vt-ptr | c | vt-ptr | ... + // dst: | vt-ptr | a | b | vt-ptr | c | ... + // j + + // + // This entry has been written already -> advance to next src entry + // + srcOffsetCheck += srcEntryPtr->entry.mSize; + i++; + isSrcVTablePtr = (i < nbSrcEntries) ? srcEntryPtr->entry.isVTablePtr() : false; + PX_ASSERT(dstOpenVTablePtrEntry < nbDstEntries); + PX_ASSERT(dstEntries[dstOpenVTablePtrEntry].entry.isVTablePtr()); + dstOpenVTablePtrEntry = -1; + PX_ASSERT(addVTablePtrShiftIteration == 0); + } + bool isDstVTablePtr = (j < nbDstEntries) ? dstEntryPtr->entry.isVTablePtr() : false; + if (isDstVTablePtr && (srcOpenVTablePtrEntry != -1)) + { + // i + // src: | vt-ptr | a | b | c | ... + // dst: | a | b | vt-ptr | c | ... + // j + + i--; // next iteration the current element should get processed + isSrcVTablePtr = true; + PX_ASSERT(srcOpenVTablePtrEntry < nbSrcEntries); + srcEntryPtr = &srcEntries[srcOpenVTablePtrEntry]; + PX_ASSERT(srcEntryPtr->entry.isVTablePtr()); + modSrcOffsetCheck = srcEntryPtr->offset; + srcOffsetCheck -= srcEntryPtr->entry.mSize; // to make sure total change is 0 after this iteration + srcOpenVTablePtrEntry = -1; + PX_ASSERT(addVTablePtrShiftIteration == 1); + addVTablePtrShiftIteration = 0; + } + + if(i==nbSrcEntries && j==nbDstEntries) + { + PX_ASSERT((srcOpenVTablePtrEntry == -1) && (dstOpenVTablePtrEntry == -1)); + break; + } + + if (isSrcVTablePtr || isDstVTablePtr) + { + if (!isSrcVTablePtr) + { + // i + // src: | a | b | vt-ptr | c | ... + // dst: | vt-ptr | a | b | c | ... + // j + + PX_ASSERT(dstOpenVTablePtrEntry == -1); // the other case should be detected and treated earlier + PX_ASSERT(srcOpenVTablePtrEntry == -1); + PX_ASSERT(addVTablePtrShiftIteration == 0); + + int k; + for(k=i+1; k < nbSrcEntries; k++) + { + if (srcEntries[k].entry.isVTablePtr()) + break; + } + PX_ASSERT(k < nbSrcEntries); + + srcEntryPtr = &srcEntries[k]; + modSrcOffsetCheck = srcEntryPtr->offset; + srcOffsetCheck -= srcEntryPtr->entry.mSize; // to make sure total change is 0 after this iteration + + dstOpenVTablePtrEntry = j; + i--; // to make sure the original entry gets processed in the next iteration + } + else if (!isDstVTablePtr) + { + // i ---> i + // src: | vt-ptr | a | b | c | ... + // dst: | a | b | vt-ptr | c | ... + // j + + PX_ASSERT(srcOpenVTablePtrEntry == -1); // the other case should be detected and treated earlier + PX_ASSERT(dstOpenVTablePtrEntry == -1); + PX_ASSERT(addVTablePtrShiftIteration == 0); + + srcOffsetCheck += srcEntryPtr->entry.mSize; + modSrcOffsetCheck = srcOffsetCheck; + srcOpenVTablePtrEntry = i; + i++; + srcEntryPtr = &srcEntries[i]; + + addVTablePtrShiftIteration = 1; // additional iteration might be needed to process vtable pointer at the end of a class + + PX_ASSERT((i < nbSrcEntries) && ((srcEntryPtr->entry.mFlags & PxMetaDataFlag::ePADDING) == 0)); + // if the second check fails, this whole section might have to be done before the padding bytes get processed. Not sure + // what other consequences that might have though. + } + } +#if PX_CHECKED + else + { + if(!compareEntries(*srcEntryPtr, *dstEntryPtr)) + { + displayMessage(PxErrorCode::eINVALID_PARAMETER, "\rConvX::convertClass: %s, src meta data and dst meta data don't match!", mc->mClassName); + return false; + } + } +#endif + + const ExtraDataEntry2& srcEntry = *srcEntryPtr; + const ExtraDataEntry2& dstEntry = *dstEntryPtr; + + if(srcEntry.entry.mFlags & PxMetaDataFlag::eUNION) + { + // ### hardcoded bit here, will only work when union type is the first int of the struct + const int* tmp = reinterpret_cast<const int*>(buffer + modSrcOffsetCheck); + const int unionType = *tmp; + + const char* typeName = getTypeName(srcEntry.entry.mType, unionType); + assert(typeName); + + MetaClass* unionMC = getMetaClass(typeName, META_DATA_SRC); + assert(unionMC); + + convertClass(buffer + modSrcOffsetCheck, unionMC, 0); // ### recurse + + dstOffsetCheck += dstEntry.entry.mSize; + + MetaClass* targetUnionMC = getMetaClass(typeName, META_DATA_DST); + assert(targetUnionMC); + + const int delta = dstEntry.entry.mSize - targetUnionMC->mSize; + char* deltaBytes = reinterpret_cast<char*>(PX_ALLOC(sizeof(char)*delta, "deltaBytes")); + memset(deltaBytes, 0, size_t(delta)); + output(deltaBytes, delta); // Skip unused bytes at the end of the union + PX_FREE(deltaBytes); + srcOffsetCheck += srcEntry.entry.mSize; // do not use modSrcOffsetCheck here! + } + else + { + assert(srcEntry.cb); + assert(srcEntry.offset == modSrcOffsetCheck); + + // ---- big convex surgery ---- + if(convexSurgery) + { + if(strcmp(srcEntry.entry.mName, "mNbHullVertices")==0) + { + assert(srcEntry.entry.mSize==1); + const int nbVerts = int(*(buffer+modSrcOffsetCheck)); + assert(!foundNbVerts); + foundNbVerts = true; + + const int gaussMapLimit = getBinaryMetaData(META_DATA_DST)->getGaussMapLimit(); + if(nbVerts > gaussMapLimit) + { + // We need a gauss map and we have one => keep it + } + else + { + // We don't need a gauss map and we have one => remove it + removeBigData = true; + } + } + else + { + if(removeBigData) + { + const bool isBigConvexData = strcmp(srcEntry.entry.mType, "BigConvexData")==0 || + strcmp(srcEntry.entry.mType, "BigConvexRawData")==0; + if(isBigConvexData) + { + assert(foundNbVerts); + setNullPtr(true); + } + } + } + } + // ---- big convex surgery ---- + + (this->*srcEntry.cb)(buffer+modSrcOffsetCheck, srcEntry.entry, dstEntry.entry); + assert(dstOffsetCheck==dstEntry.offset); + dstOffsetCheck += dstEntry.entry.mSize; + srcOffsetCheck += srcEntry.entry.mSize; // do not use modSrcOffsetCheck here! + + // ---- big convex surgery ---- + if(convexSurgery && removeBigData) + setNullPtr(false); + // ---- big convex surgery ---- + } + + j++; + } + + displayMessage(PxErrorCode::eDEBUG_INFO, "---------------------------------------------\n"); + + while(j<nbDstEntries) + { + assert(dstEntries[j].entry.mFlags & PxMetaDataFlag::ePADDING); + if(dstEntries[j].entry.mFlags & PxMetaDataFlag::ePADDING) + { + dstOffsetCheck += dstEntries[j].entry.mSize; + } + j++; + } + + assert(j==nbDstEntries); + assert(dstOffsetCheck==target_mc->mSize); + assert(srcOffsetCheck==mc->mSize); + + // ---- big convex surgery ---- + if(convexSurgery) + mConvexFlags.pushBack(removeBigData); + // ---- big convex surgery ---- + + return true; +} + +// Handles data defined with PX_DEF_BIN_METADATA_EXTRA_ARRAY +const char* Sn::ConvX::convertExtraData_Array(const char* Address, const char* lastAddress, const char* objectAddress, + const ExtraDataEntry& ed) +{ + (void)lastAddress; + MetaClass* mc = getMetaClass(ed.entry.mType, META_DATA_SRC); + assert(mc); + + // PT: safe to cast to int here since we're reading a count. + const int count = int(peek(ed.entry.mSize, objectAddress + ed.offset, ed.entry.mFlags)); + + // if(ed.entry.mCount) // Reused as align value + if(ed.entry.mAlignment) + { + Address = alignStream(Address, ed.entry.mAlignment); + // Address = alignStream(Address, ed.entry.mCount); + assert(Address<=lastAddress); + } + + for(int c=0;c<count;c++) + { + convertClass(Address, mc, 0); + Address += mc->mSize; + assert(Address<=lastAddress); + } + return Address; +} + +const char* Sn::ConvX::convertExtraData_Ptr(const char* Address, const char* lastAddress, const PxMetaDataEntry& entry, int count, + int ptrSize_Src, int ptrSize_Dst) +{ + (void)lastAddress; + + PxMetaDataEntry tmpSrc = entry; + tmpSrc.mCount = count; + tmpSrc.mSize = count * ptrSize_Src; + + PxMetaDataEntry tmpDst = entry; + tmpDst.mCount = count; + tmpDst.mSize = count * ptrSize_Dst; + + + displayMessage(PxErrorCode::eDEBUG_INFO, "extra data ptrs\n"); + displayMessage(PxErrorCode::eDEBUG_INFO, "+++++++++++++++++++++++++++++++++++++++++++++\n"); + displayMessage(PxErrorCode::eDEBUG_INFO, "\t0x%p\t%x\t\t\t%s", Address, Address[0], entry.mName); + for (int byteCount = 1; byteCount < ptrSize_Src*count; ++byteCount) + displayMessage(PxErrorCode::eDEBUG_INFO, "\t0x%p\t%x\t\t\t.", Address + byteCount, Address[byteCount]); + + convertPtr(Address, tmpSrc, tmpDst); + Address += count * ptrSize_Src; + assert(Address<=lastAddress); + return Address; +} + +static bool decodeControl(PxU64 control, const ExtraDataEntry& ed, PxU64 controlMask = 0) +{ + if(ed.entry.mFlags & PxMetaDataFlag::eCONTROL_FLIP) + { + if(controlMask) + { + return (control & controlMask) ? false : true; + } + else + { + return control==0; + } + } + else + { + if(controlMask) + { + return (control & controlMask) ? true : false; + } + else + { + return control!=0; + } + } + +} + +// ### currently hardcoded, should change +int Sn::ConvX::getConcreteType(const char* buffer) +{ + MetaClass* mc = getMetaClass("PxBase", META_DATA_SRC); + assert(mc); + PxMetaDataEntry entry; + if(mc->getFieldByType("PxType", entry)) + { + // PT: safe to cast to int here since we're reading our own PxType + return int(peek(entry.mSize, buffer + entry.mOffset)); + } + assert(0); + return 0xffffffff; +} + +struct Item : public shdfnd::UserAllocated +{ + MetaClass* mc; + const char* address; +}; + +bool Sn::ConvX::convertCollection(const void* buffer, int fileSize, int nbObjects) +{ + const char* lastAddress = reinterpret_cast<const char*>(buffer) + fileSize; + const char* Address = alignStream(reinterpret_cast<const char*>(buffer)); + + const int ptrSize_Src = mSrcPtrSize; + const int ptrSize_Dst = mDstPtrSize; + Item* objects = PX_NEW(Item)[PxU32(nbObjects)]; + + for(PxU32 i=0;i<PxU32(nbObjects);i++) + { + const float percents = float(i)/float(nbObjects); + + displayMessage(PxErrorCode::eDEBUG_INFO, "Object conversion: %d%%", int(percents*100.0f)); + + Address = alignStream(Address); + assert(Address<=lastAddress); + + PxConcreteType::Enum classType = PxConcreteType::Enum(getConcreteType(Address)); + MetaClass* metaClass = getMetaClass(classType, META_DATA_SRC); + if(!metaClass) + { + PX_DELETE_ARRAY(objects); + return false; + } + + objects[i].mc = metaClass; + objects[i].address = Address; + + if(!convertClass(Address, metaClass, 0)) + { + PX_DELETE_ARRAY(objects); + return false; + } + + Address += metaClass->mSize; + assert(Address<=lastAddress); + } + + // Fields / extra data + if(1) + { + // ---- big convex surgery ---- + unsigned int nbConvexes = 0; + // ---- big convex surgery ---- + //const char* StartAddress2 = Address; + //int startDstSize2 = getCurrentOutputSize(); + for(int i=0;i<nbObjects;i++) + { + //const char* StartAddress = Address; + //int startDstSize = getCurrentOutputSize(); + + const float percents = float(i)/float(nbObjects); + + displayMessage(PxErrorCode::eDEBUG_INFO, "Extra data conversion: %d%%", int(percents*100.0f)); + + MetaClass* mc0 = objects[i].mc; + const char* objectAddress = objects[i].address; + + // printf("%d: %s\n", i, mc->mClassName); + // if(strcmp(mc->mClassName, "TriangleMesh")==0) + // if(strcmp(mc->mClassName, "NpRigidDynamic")==0) + if(strcmp(mc0->mClassName, "HybridModel")==0) + { + int stop=1; + (void)(stop); + } + + // ### we actually need to collect all extra data for this class, including data from embedded members. + + PX_ALLOCA(entries, ExtraDataEntry, 256); + int nbEntries = 0; + _enumerateExtraData(objectAddress, mc0, entries, nbEntries, 0, META_DATA_SRC); + assert(nbEntries<256); + + Address = alignStream(Address); + assert(Address<=lastAddress); + + for(int j=0;j<nbEntries;j++) + { + const ExtraDataEntry& ed = entries[j]; + assert(ed.entry.mFlags & PxMetaDataFlag::eEXTRA_DATA); + + if(ed.entry.mFlags & PxMetaDataFlag::eEXTRA_ITEM) + { + // ---- big convex surgery ---- + if(1) + { + const bool isBigConvexData = strcmp(ed.entry.mType, "BigConvexData")==0; + if(isBigConvexData) + { + assert(nbConvexes<mConvexFlags.size()); + if(mConvexFlags[nbConvexes++]) + setNoOutput(true); + } + } + // ---- big convex surgery ---- + + MetaClass* extraDataType = getMetaClass(ed.entry.mType, META_DATA_SRC); + assert(extraDataType); + + //sschirm: we used to have ed.entry.mOffset here, but that made cloth deserialization fail. + const char* controlAddress = objectAddress + ed.offset; + const PxU64 controlValue = peek(ed.entry.mOffsetSize, controlAddress); + + if(controlValue) + { + if(ed.entry.mAlignment) + { + Address = alignStream(Address, ed.entry.mAlignment); + assert(Address<=lastAddress); + } + + const char* classAddress = Address; + convertClass(Address, extraDataType, 0); + Address += extraDataType->mSize; + assert(Address<=lastAddress); + + // Enumerate extra data for this optional class, and convert it too. + // This assumes the extra data for the optional class is always appended to the class itself, + // which is something we'll need to enforce in the SDK. So far this is only to handle optional + // inline arrays. + + // ### this should probably be recursive eventually + PX_ALLOCA(entries2, ExtraDataEntry, 256); + int nbEntries2 = 0; + _enumerateExtraData(objectAddress, extraDataType, entries2, nbEntries2, 0, META_DATA_SRC); + assert(nbEntries2<256); + for(int k=0;k<nbEntries2;k++) + { + const ExtraDataEntry& ed2 = entries2[k]; + assert(ed2.entry.mFlags & PxMetaDataFlag::eEXTRA_DATA); + if(ed2.entry.mFlags & PxMetaDataFlag::eEXTRA_ITEMS) + { + const int controlOffset = ed2.entry.mOffset; + const int controlSize = ed2.entry.mSize; + const int countOffset = ed2.entry.mCount; + const int countSize = ed2.entry.mOffsetSize; + + const PxU64 controlValue2 = peek(controlSize, classAddress + controlOffset); + + PxU64 controlMask = 0; + if(ed2.entry.mFlags & PxMetaDataFlag::eCONTROL_MASK) + { + controlMask = PxU64(ed2.entry.mFlags & (PxMetaDataFlag::eCONTROL_MASK_RANGE << 16)); + controlMask = controlMask >> 16; + } + + if(decodeControl(controlValue2, ed2, controlMask)) + { + // PT: safe to cast to int here since we're reading a count + int count = int(peek(countSize, classAddress + countOffset, ed2.entry.mFlags)); + + if(ed2.entry.mAlignment) + { + assert(0); // Never tested + Address = alignStream(Address, ed2.entry.mAlignment); + assert(Address<=lastAddress); + } + + if(ed2.entry.mFlags & PxMetaDataFlag::ePTR) + { + assert(0); // Never tested + } + else + { + MetaClass* mc = getMetaClass(ed2.entry.mType, META_DATA_SRC); + assert(mc); + + while(count--) + { + convertClass(Address, mc, 0); + Address += mc->mSize; + assert(Address<=lastAddress); + } + } + + } + } + else + { + if( (ed2.entry.mFlags & PxMetaDataFlag::eALIGNMENT) && ed2.entry.mAlignment) + { + Address = alignStream(Address, ed2.entry.mAlignment); + assert(Address<=lastAddress); + } + else + { + // We assume it's an normal array, e.g. the ones from "big convexes" + assert(!(ed2.entry.mFlags & PxMetaDataFlag::eEXTRA_ITEM)); + + Address = convertExtraData_Array(Address, lastAddress, classAddress, ed2); + } + } + } + + } + else + { + int stop = 0; + (void)(stop); + } + + // ---- big convex surgery ---- + setNoOutput(false); + // ---- big convex surgery ---- + } + else if(ed.entry.mFlags & PxMetaDataFlag::eEXTRA_ITEMS) + { + // PX_DEF_BIN_METADATA_EXTRA_ITEMS + int reloc = ed.offset - ed.entry.mOffset; // ### because the enum code only fixed the "controlOffset"! + const int controlOffset = ed.entry.mOffset; + const int controlSize = ed.entry.mSize; + const int countOffset = ed.entry.mCount; + const int countSize = ed.entry.mOffsetSize; + + // const int controlValue2 = peek(controlSize, objectAddress + controlOffset); + const PxU64 controlValue2 = peek(controlSize, objectAddress + controlOffset + reloc); + + PxU64 controlMask = 0; + if(ed.entry.mFlags & PxMetaDataFlag::eCONTROL_MASK) + { + controlMask = PxU64(ed.entry.mFlags & (PxMetaDataFlag::eCONTROL_MASK_RANGE << 16)); + controlMask = controlMask >> 16; + } + + if(decodeControl(controlValue2, ed, controlMask)) + { + // PT: safe to cast to int here since we're reading a count + // int count = peek(countSize, objectAddress + countOffset); // ### + int count = int(peek(countSize, objectAddress + countOffset + reloc, ed.entry.mFlags)); // ### + + if(ed.entry.mAlignment) + { + Address = alignStream(Address, ed.entry.mAlignment); + assert(Address<=lastAddress); + } + + if(ed.entry.mFlags & PxMetaDataFlag::ePTR) + { + Address = convertExtraData_Ptr(Address, lastAddress, ed.entry, count, ptrSize_Src, ptrSize_Dst); + } + else + { + MetaClass* mc = getMetaClass(ed.entry.mType, META_DATA_SRC); + assert(mc); + + while(count--) + { + convertClass(Address, mc, 0); + Address += mc->mSize; + assert(Address<=lastAddress); + } + } + } + + } + else if(ed.entry.mFlags & PxMetaDataFlag::eALIGNMENT) + { + if(ed.entry.mAlignment) + { + displayMessage(PxErrorCode::eDEBUG_INFO, " align to %d bytes\n", ed.entry.mAlignment); + displayMessage(PxErrorCode::eDEBUG_INFO, "---------------------------------------------\n"); + + Address = alignStream(Address, ed.entry.mAlignment); + assert(Address<=lastAddress); + } + } + else if(ed.entry.mFlags & PxMetaDataFlag::eEXTRA_NAME) + { + if(ed.entry.mAlignment) + { + Address = alignStream(Address, ed.entry.mAlignment); + assert(Address<=lastAddress); + } + + //get string count + MetaClass* mc = getMetaClass("PxU32", META_DATA_SRC); + assert(mc); + //safe to cast to int here since we're reading a count. + const int count = int(peek(mc->mSize, Address, 0)); + + displayMessage(PxErrorCode::eDEBUG_INFO, " convert %d bytes string\n", count); + + convertClass(Address, mc, 0); + Address += mc->mSize; + + mc = getMetaClass(ed.entry.mType, META_DATA_SRC); + assert(mc); + + for(int c=0;c<count;c++) + { + convertClass(Address, mc, 0); + Address += mc->mSize; + assert(Address<=lastAddress); + } + } + else + { + Address = convertExtraData_Array(Address, lastAddress, objectAddress, ed); + } + } + } + PX_DELETE_ARRAY(objects); + assert(nbConvexes==mConvexFlags.size()); + } + + assert(Address==lastAddress); + + return true; +} + +bool Sn::ConvX::convert(const void* buffer, int fileSize) +{ + // Test initial alignment + if(size_t(buffer) & (ALIGN_DEFAULT-1)) + { + assert(0); + return false; + } + + const int header = read32(buffer); fileSize -= 4; (void)header; + + if (header != PX_MAKE_FOURCC('S','E','B','D')) + { + displayMessage(physx::PxErrorCode::eINVALID_PARAMETER, + "PxBinaryConverter: Buffer contains data with bad header indicating invalid serialized data."); + return false; + } + + const int version = read32(buffer); fileSize -= 4; (void)version; + + const int binaryVersion = read32(buffer); fileSize -= 4; + + if (!checkCompatibility(PxU32(version), PxU32(binaryVersion))) + { + char buf[512]; + getCompatibilityVersionsStr(buf, 512); + + displayMessage(physx::PxErrorCode::eINVALID_PARAMETER, + "PxBinaryConverter: Buffer contains data version (%x-%d) is incompatible with this PhysX sdk.\n These versions would be compatible: %s", + version, binaryVersion, buf); + return false; + } + const int buildNumber = read32(buffer); fileSize -= 4; (void)buildNumber; + + //read src platform tag and write dst platform tag according dst meta data + const int srcPlatformTag = *reinterpret_cast<const int*>(buffer); + buffer = reinterpret_cast<const void*>(size_t(buffer) + 4); + fileSize -= 4; + const int dstPlatformTag = mMetaData_Dst->getPlatformTag(); + output(dstPlatformTag); + + if (srcPlatformTag != mMetaData_Src->getPlatformTag()) + { + displayMessage(physx::PxErrorCode::eINVALID_PARAMETER, + "PxBinaryConverter: Mismatch of platform tags of binary data and metadata:\n Binary Data: %s\n MetaData: %s\n", + getBinaryPlatformName(PxU32(srcPlatformTag)), + getBinaryPlatformName(PxU32(mMetaData_Src->getPlatformTag()))); + return false; + } + + //read whether input data has marked padding, and set it for the output data (since 0xcd is written into pads on conversion) + const int srcMarkedPadding = *reinterpret_cast<const int*>(buffer); + buffer = reinterpret_cast<const void*>(size_t(buffer) + 4); + fileSize -= 4; + mMarkedPadding = srcMarkedPadding != 0; + const int dstMarkedPadding = 1; + output(dstMarkedPadding); + + int nbObjectsInCollection; + + buffer = convertReferenceTables(buffer, fileSize, nbObjectsInCollection); + if(!buffer) + return false; + + bool ret = convertCollection(buffer, fileSize, nbObjectsInCollection); + mMarkedPadding = false; + return ret; +} + +// PT: code below added to support 64bit-to-32bit conversions +void Sn::ConvX::exportIntAsPtr(int value) +{ + const int ptrSize_Src = mSrcPtrSize; + const int ptrSize_Dst = mDstPtrSize; + + PxMetaDataEntry entry; + + const char* address = NULL; + const PxU32 value32 = PxU32(value); + const PxU64 value64 = PxU64(value)&0xffffffff; + + if(ptrSize_Src==4) + { + address = reinterpret_cast<const char*>(&value32); + } + else if(ptrSize_Src==8) + { + address = reinterpret_cast<const char*>(&value64); + } + else assert(0); + + convertExtraData_Ptr(address, address + ptrSize_Src, entry, 1, ptrSize_Src, ptrSize_Dst); +} + +void Sn::ConvX::exportInt(int value) +{ + output(value); +} + +void Sn::ConvX::exportInt64(PxU64 value) +{ + output(value); +} + +PointerRemap::PointerRemap() +{ +} + +PointerRemap::~PointerRemap() +{ +} + +bool PointerRemap::checkRefIsNotUsed(PxU32 ref) const +{ + const PxU32 size = mData.size(); + for(PxU32 i=0;i<size;i++) + { + if(mData[i].id==ref) + return false; + } + return true; +} + +void PointerRemap::setObjectRef(PxU64 object64, PxU32 ref) +{ + const PxU32 size = mData.size(); + for(PxU32 i=0;i<size;i++) + { + if(mData[i].object==object64) + { + mData[i].id = ref; + return; + } + } + InternalData data; + data.object = object64; + data.id = ref; + mData.pushBack(data); +} + +bool PointerRemap::getObjectRef(PxU64 object64, PxU32& ref) const +{ + const PxU32 size = mData.size(); + for(PxU32 i=0;i<size;i++) + { + if(mData[i].object==object64) + { + ref = mData[i].id; + return true; + } + } + return false; +} + +/** +Converting the PxBase object offsets in the manifest table is fairly complicated now. +It would be good to have an easy callback mechanism for custom things like this. +*/ +const void* Sn::ConvX::convertManifestTable(const void* buffer, int& fileSize) +{ + PxU32 padding = getPadding(size_t(buffer), ALIGN_DEFAULT); + buffer = alignStream(reinterpret_cast<const char*>(buffer)); + fileSize -= padding; + int nb = read32(buffer); + fileSize -= 4; + + MetaClass* mc_src = getMetaClass("Sn::ManifestEntry", META_DATA_SRC); + assert(mc_src); + + MetaClass* mc_dst = getMetaClass("Sn::ManifestEntry", META_DATA_DST); + assert(mc_dst); + + bool mdOk; + PxMetaDataEntry srcTypeField; + mdOk = mc_src->getFieldByName("type", srcTypeField); + PX_UNUSED(mdOk); + PX_ASSERT(mdOk); + + PxMetaDataEntry dstOffsetField; + mdOk = mc_dst->getFieldByName("offset", dstOffsetField); + PX_ASSERT(mdOk); + + const char* address = reinterpret_cast<const char*>(buffer); + PxU32 headerOffset = 0; + for(int i=0;i<nb;i++) + { + PxConcreteType::Enum classType = PxConcreteType::Enum(peek(srcTypeField.mSize, address + srcTypeField.mOffset)); + + //convert ManifestEntry but output to tmpStream + PxDefaultMemoryOutputStream tmpStream; + { + //backup output state + PxOutputStream* outStream = mOutStream; + PxU32 outputSize = PxU32(mOutputSize); + + mOutStream = &tmpStream; + mOutputSize = 0; + + convertClass(address, mc_src, 0); + PX_ASSERT(tmpStream.getSize() == PxU32(mc_dst->mSize)); + + //restore output state + mOutStream = outStream; + mOutputSize = int(outputSize); + } + + //output patched offset + PX_ASSERT(dstOffsetField.mOffset == 0); //assuming offset is the first data + output(int(headerOffset)); + + //output rest of ManifestEntry + PxU32 restSize = PxU32(mc_dst->mSize - dstOffsetField.mSize); + mOutStream->write(tmpStream.getData() + dstOffsetField.mSize, restSize); + mOutputSize += restSize; + + //increment source stream + address += mc_src->mSize; + fileSize -= mc_src->mSize; + assert(fileSize>=0); + + //update headerOffset using the type and dst meta data of the type + MetaClass* mc_classType_dst = getMetaClass(classType, META_DATA_DST); + if(!mc_classType_dst) + return NULL; + headerOffset += getPadding(size_t(mc_classType_dst->mSize), PX_SERIAL_ALIGN) + mc_classType_dst->mSize; + } + + output(int(headerOffset)); //endoffset + buffer = address + 4; + fileSize -= 4; + return buffer; +} + +const void* Sn::ConvX::convertImportReferences(const void* buffer, int& fileSize) +{ + PxU32 padding = getPadding(size_t(buffer), ALIGN_DEFAULT); + buffer = alignStream(reinterpret_cast<const char*>(buffer)); + fileSize -= padding; + int nb = read32(buffer); + fileSize -= 4; + + if(!nb) + return buffer; + + MetaClass* mc = getMetaClass("Sn::ImportReference", META_DATA_SRC); + assert(mc); + + const char* address = reinterpret_cast<const char*>(buffer); + for(int i=0;i<nb;i++) + { + convertClass(address, mc, 0); + address += mc->mSize; + fileSize -= mc->mSize; + assert(fileSize>=0); + } + return address; +} + +const void* Sn::ConvX::convertExportReferences(const void* buffer, int& fileSize) +{ + PxU32 padding = getPadding(size_t(buffer), ALIGN_DEFAULT); + buffer = alignStream(reinterpret_cast<const char*>(buffer)); + fileSize -= padding; + int nb = read32(buffer); + fileSize -= 4; + + if(!nb) + return buffer; + + MetaClass* mc = getMetaClass("Sn::ExportReference", META_DATA_SRC); + assert(mc); + + const char* address = reinterpret_cast<const char*>(buffer); + for(int i=0;i<nb;i++) + { + convertClass(address, mc, 0); + address += mc->mSize; + fileSize -= mc->mSize; + assert(fileSize>=0); + } + return address; +} + +const void* Sn::ConvX::convertInternalReferences(const void* buffer, int& fileSize) +{ + PxU32 padding = getPadding(size_t(buffer), ALIGN_DEFAULT); + buffer = alignStream(reinterpret_cast<const char*>(buffer)); + fileSize -= padding; + + //pointer references + int nbPtrReferences = read32(buffer); + fileSize -= 4; + if(nbPtrReferences) + { + const char* address = reinterpret_cast<const char*>(buffer); + MetaClass* mc = getMetaClass("Sn::InternalReferencePtr", META_DATA_SRC); + assert(mc); + for(int i=0;i<nbPtrReferences;i++) + { + convertClass(address, mc, 0); + address += mc->mSize; + fileSize -= mc->mSize; + assert(fileSize>=0); + } + buffer = address; + } + + //index references + int nbIdxReferences = read32(buffer); + fileSize -= 4; + if (nbIdxReferences) + { + const char* address = reinterpret_cast<const char*>(buffer); + MetaClass* mc = getMetaClass("Sn::InternalReferenceIdx", META_DATA_SRC); + assert(mc); + for(int i=0;i<nbIdxReferences;i++) + { + convertClass(address, mc, 0); + address += mc->mSize; + fileSize -= mc->mSize; + assert(fileSize>=0); + } + buffer = address; + } + return buffer; +} + + +const void* Sn::ConvX::convertReferenceTables(const void* buffer, int& fileSize, int& nbObjectsInCollection) +{ + // PT: the map should not be used while creating it, so use one indirection + mActiveRemap = NULL; + mRemap.mData.clear(); + mPointerRemapCounter = 0; + + PxU32 padding = getPadding(size_t(buffer), ALIGN_DEFAULT); + buffer = alignStream(reinterpret_cast<const char*>(buffer)); + fileSize -= padding; + + nbObjectsInCollection = read32(buffer); + if (nbObjectsInCollection == 0) + displayMessage(PxErrorCode::eDEBUG_INFO, "\n\nConverting empty collection!\n\n"); + fileSize -= 4; + + buffer = convertManifestTable(buffer, fileSize); + + if(!buffer) + return NULL; + + buffer = convertImportReferences(buffer, fileSize); + buffer = convertExportReferences(buffer, fileSize); + buffer = convertInternalReferences(buffer, fileSize); + + // PT: the map can now be used + mActiveRemap = &mRemap; + + return buffer; +} + +bool Sn::ConvX::checkPaddingBytes(const char* buffer, int byteCount) +{ + const unsigned char* src = reinterpret_cast<const unsigned char*>(buffer); + + int i = 0; + while ((i < byteCount) && (src[i] == 0xcd)) + i++; + return (i == byteCount); +} diff --git a/PhysX_3.4/Source/PhysXExtensions/src/serialization/Binary/SnConvX_Error.cpp b/PhysX_3.4/Source/PhysXExtensions/src/serialization/Binary/SnConvX_Error.cpp new file mode 100644 index 00000000..9debc679 --- /dev/null +++ b/PhysX_3.4/Source/PhysXExtensions/src/serialization/Binary/SnConvX_Error.cpp @@ -0,0 +1,92 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and related documentation and +// any modifications thereto. Any use, reproduction, disclosure, or +// distribution of this software and related documentation without an express +// license agreement from NVIDIA Corporation is strictly prohibited. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 NVIDIA Corporation. All rights reserved. + +#include "foundation/PxErrorCallback.h" +#include "SnConvX.h" +#include <stdarg.h> +#include "PsString.h" +#include "PsFoundation.h" + +#define MAX_DISPLAYED_ISSUES 10 + +using namespace physx; + +void Sn::ConvX::resetNbErrors() +{ + mNbErrors = 0; + mNbWarnings = 0; +} + +int Sn::ConvX::getNbErrors() const +{ + return mNbErrors; +} + +void Sn::ConvX::displayMessage(PxErrorCode::Enum code, const char* format, ...) +{ + if(silentMode()) + return; + + int sum = mNbWarnings + mNbErrors; + if(sum >= MAX_DISPLAYED_ISSUES) + return; + + bool display = false; + + if(code==PxErrorCode::eINTERNAL_ERROR || code==PxErrorCode::eINVALID_OPERATION || code==PxErrorCode::eINVALID_PARAMETER) + { + mNbErrors++; + display = true; + } + else if(code == PxErrorCode::eDEBUG_WARNING) + { + mNbWarnings++; + display = true; + } + + if(display || ((sum == 0) && verboseMode()) ) + { + va_list va; + va_start(va, format); + Ps::getFoundation().errorImpl(code, __FILE__, __LINE__, format, va); + va_end(va); + } + + if(display) + { + if( sum == 0) + { + Ps::getFoundation().error(PxErrorCode::eDEBUG_INFO, __FILE__, __LINE__, "Hit warnings or errors: skipping further verbose output.\n"); + } + else if(sum == MAX_DISPLAYED_ISSUES-1) + { + Ps::getFoundation().error(PxErrorCode::eDEBUG_INFO, __FILE__, __LINE__, "Exceeding 10 warnings or errors: skipping further output.\n"); + } + } + + return; +} diff --git a/PhysX_3.4/Source/PhysXExtensions/src/serialization/Binary/SnConvX_MetaData.cpp b/PhysX_3.4/Source/PhysXExtensions/src/serialization/Binary/SnConvX_MetaData.cpp new file mode 100644 index 00000000..4d2eda22 --- /dev/null +++ b/PhysX_3.4/Source/PhysXExtensions/src/serialization/Binary/SnConvX_MetaData.cpp @@ -0,0 +1,840 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and related documentation and +// any modifications thereto. Any use, reproduction, disclosure, or +// distribution of this software and related documentation without an express +// license agreement from NVIDIA Corporation is strictly prohibited. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 NVIDIA Corporation. All rights reserved. + +#include "foundation/PxIO.h" +#include "SnConvX.h" +#include "common/PxSerialFramework.h" +#include "serialization/SnSerialUtils.h" +#include <assert.h> + +using namespace physx; +using namespace physx::Sn; + +//#define REMOVE_EXPLICIT_PADDING + +static const char gVTablePtr[] = "v-table ptr"; +static const char gAutoPadding[] = "auto-generated padding"; +static const char gByte[] = "paddingByte"; + +/////////////////////////////////////////////////////////////////////////////// + +bool PxMetaDataEntry::isVTablePtr() const +{ + return mType==gVTablePtr; +} + +/////////////////////////////////////////////////////////////////////////////// + +bool MetaClass::getFieldByType(const char* type, PxMetaDataEntry& entry) const +{ + assert(type); + PxU32 nbFields = mFields.size(); + for(PxU32 i=0;i<nbFields;i++) + { + if(strcmp(mFields[i].mType, type)==0) + { + entry = mFields[i]; + return true; + } + } + return false; +} + +bool MetaClass::getFieldByName(const char* name, PxMetaDataEntry& entry) const +{ + assert(name); + PxU32 nbFields = mFields.size(); + for(PxU32 i=0;i<nbFields;i++) + { + if(strcmp(mFields[i].mName, name)==0) + { + entry = mFields[i]; + return true; + } + } + return false; +} + +void MetaClass::checkAndCompleteClass(const MetaData& owner, int& startOffset, int& nbBytes) +{ + if(startOffset!=-1) + { + owner.mConvX.displayMessage(PxErrorCode::eDEBUG_INFO, + "\n Adding %d padding bytes at offset %d in class %s.\n", nbBytes, startOffset, mClassName); + + // Leap of faith: add padding bytes there + PxMetaDataEntry padding; + padding.mType = gByte; + padding.mName = gAutoPadding; + padding.mOffset = startOffset; + padding.mSize = nbBytes; + padding.mCount = nbBytes; + padding.mFlags = PxMetaDataFlag::ePADDING; + mFields.pushBack(padding); + + startOffset = -1; + } +} + +bool MetaClass::check(const MetaData& owner) +{ + owner.mConvX.displayMessage(PxErrorCode::eDEBUG_INFO, "Checking class: %s\n", mClassName); + + if(mCallback) + return true; // Skip atomic types + if(mMaster) + return true; // Skip typedefs + + bool* map = reinterpret_cast<bool*>(PX_ALLOC(sizeof(bool)*mSize, "bool")); + memset(map, 0, size_t(mSize)); + + const PxU32 nbFields = mFields.size(); + for(PxU32 i=0;i<nbFields;i++) + { + const PxMetaDataEntry& field = mFields[i]; + if(field.mFlags & PxMetaDataFlag::eEXTRA_DATA) + continue; +// if((field.mFlags & PxMetaDataFlag::eUNION) && !field.mSize) +// continue; // Union type + assert(field.mSize); + const int byteStart = field.mOffset; + const int byteEnd = field.mOffset + field.mSize; + assert(byteStart>=0 && byteStart<mSize); + assert(byteEnd>=0 && byteEnd<=mSize); + + int startOffset = -1; + int nbBytes = 0; + for(int j=byteStart;j<byteEnd;j++) + { + if(map[j]) + { + if(startOffset==-1) + { + startOffset = int(i); + nbBytes = 0; + } + nbBytes++; +// displayErrorMessage(" %s: found overlapping bytes!\n", mClassName); + } + else + { + if(startOffset!=-1) + { + owner.mConvX.displayMessage(PxErrorCode::eINTERNAL_ERROR, + "PxBinaryConverter: %s: %d overlapping bytes at offset %d!\n", mClassName, nbBytes, startOffset); + startOffset = -1; + PX_ALWAYS_ASSERT_MESSAGE("Overlapping bytes!"); + } + } + map[j] = true; + } + if(startOffset!=-1) + { + owner.mConvX.displayMessage(PxErrorCode::eINTERNAL_ERROR, + "PxBinaryConverter: %s: %d overlapping bytes at offset %d!\n", mClassName, nbBytes, startOffset); + startOffset = -1; + PX_ALWAYS_ASSERT_MESSAGE("Overlapping bytes!"); + } + } + + { + int startOffset = -1; + int nbBytes = 0; + for(int i=0;i<mSize;i++) + { + if(!map[i]) + { + if(startOffset==-1) + { + startOffset = i; + nbBytes = 0; + } + nbBytes++; + } + else + { + checkAndCompleteClass(owner, startOffset, nbBytes); + } + } + checkAndCompleteClass(owner, startOffset, nbBytes); + } + PX_FREE(map); + + + // + for(PxU32 i=0;i<nbFields;i++) + { + const PxMetaDataEntry& current = mFields[i]; + if(current.mFlags & PxMetaDataFlag::ePTR) + continue; + + MetaClass* fieldMetaClass = owner.mConvX.getMetaClass(current.mType, owner.getType()); + if(!fieldMetaClass) + { + owner.mConvX.displayMessage(PxErrorCode::eINTERNAL_ERROR, + "PxBinaryConverter: Missing meta-data for: %s\n", current.mType); + return false; + } + else + { + if(current.mFlags & PxMetaDataFlag::eEXTRA_DATA) + { + owner.mConvX.displayMessage(PxErrorCode::eDEBUG_INFO, "Extra data: %s\n", current.mType); + } + else + { + assert(fieldMetaClass->mSize*current.mCount==current.mSize); + } + } + } + return true; +} + +/////////////////////////////////////////////////////////////////////////////// + +MetaData::MetaData(ConvX& convx) : + mConvX (convx), + mType (META_DATA_NONE), + mNbEntries (0), + mEntries (NULL), + mStringTable (NULL), + mVersion (0), + mBuildNumber (0), + mSizeOfPtr (0), + mPlatformTag (0), + mGaussMapLimit (0), + mFlip (false) +{ +} + +MetaData::~MetaData() +{ + PxU32 nbMetaClasses = mMetaClasses.size(); + for(PxU32 i=0;i<nbMetaClasses;i++) + { + MetaClass* current = mMetaClasses[i]; + PX_DELETE(current); + } + + PX_FREE(mStringTable); + PX_DELETE_ARRAY(mEntries); +} + +MetaClass* MetaData::getMetaClass(const char* name) const +{ + PxU32 nbMetaClasses = mMetaClasses.size(); + for(PxU32 i=0;i<nbMetaClasses;i++) + { + MetaClass* current = mMetaClasses[i]; + if(strcmp(current->mClassName, name)==0) + { + while(current->mMaster) + current = current->mMaster; + return current; + } + } + return NULL; +} + +MetaClass* MetaData::getMetaClass(PxConcreteType::Enum concreteType) const +{ + for(PxU32 i=0; i< mConcreteTypeTable.size(); i++) + { + if(mConcreteTypeTable[i].first == concreteType) + { + const char* className = offsetToText(reinterpret_cast<const char*>(size_t(mConcreteTypeTable[i].second))); + return getMetaClass(className); + } + } + return NULL; +} + +MetaClass* MetaData::addNewClass(const char* name, int size, MetaClass* master, ConvertCallback callback) +{ + // PT: if you reach this assert, you used PX_DEF_BIN_METADATA_TYPEDEF twice on the same type + assert(!getMetaClass(name)); + MetaClass* mc = PX_NEW(MetaClass); + mc->mCallback = callback; + mc->mMaster = master; + mc->mClassName = name; + mc->mSize = size; + mc->mDepth = 0; + mc->mProcessed = false; +// mc->mNbEntries = -1; + + mMetaClasses.pushBack(mc); + + return mc; +} + +bool MetaData::load(PxInputStream& inputStream, MetaDataType type) +{ + assert(type!=META_DATA_NONE); + + mConvX.displayMessage(PxErrorCode::eDEBUG_INFO, "Loading %s meta-data...\n", type==META_DATA_SRC ? "source" : "target"); + + mType = type; + + mFlip = false; + { + int header; + inputStream.read(&header, 4); + if(header==PX_MAKE_FOURCC('M','E','T','A')) + { + mFlip = false; + } + else if(header==PX_MAKE_FOURCC('A','T','E','M')) + { + mFlip = true; + } + else + { + mConvX.displayMessage(PxErrorCode::eINVALID_PARAMETER, "PxBinaryConverter: invalid meta-data file!\n"); + return false; + } + + if (type == META_DATA_SRC && mFlip) + { + mConvX.displayMessage(PxErrorCode::eINVALID_PARAMETER, + "PxBinaryConverter: source meta data needs to match endianness with current system!"); + return false; + } + + inputStream.read(&mVersion, 4); + inputStream.read(&mBinaryVersion, 4); + if(mFlip) + { + flip(mVersion); + flip(mBinaryVersion); + } + + if (!checkCompatibility(PxU32(mVersion), PxU32(mBinaryVersion))) + { + char buffer[512]; + getCompatibilityVersionsStr(buffer, 512); + + mConvX.displayMessage(PxErrorCode::eINVALID_PARAMETER, + "PxBinaryConverter: data version (%x-%d) is incompatible with this PhysX sdk.\n These versions would be compatible: %s", + mVersion, mBinaryVersion, buffer); + + return false; + } + inputStream.read(&mBuildNumber, 4); + if(mFlip) + flip(mBuildNumber); + + + inputStream.read(&mSizeOfPtr, 4); + if(mFlip) + flip(mSizeOfPtr); + + inputStream.read(&mPlatformTag, 4); + if(mFlip) + flip(mPlatformTag); + + if (!Sn::isBinaryPlatformTagValid(PxU32(mPlatformTag))) + { + mConvX.displayMessage(PxErrorCode::eINVALID_PARAMETER, "PxBinaryConverter: Unknown meta data platform tag"); + return false; + } + + inputStream.read(&mGaussMapLimit, 4); + if(mFlip) + flip(mGaussMapLimit); + + inputStream.read(&mNbEntries, 4); + if(mFlip) + flip(mNbEntries); + + mEntries = PX_NEW(PxMetaDataEntry)[PxU32(mNbEntries)]; + if(mSizeOfPtr==8) + { + for(int i=0;i<mNbEntries;i++) + { + MetaDataEntry64 tmp; + inputStream.read(&tmp, sizeof(MetaDataEntry64)); + if (mFlip) // important to flip them first, else the cast below might destroy information + { + flip(tmp.mType); + flip(tmp.mName); + } + // We can safely cast to 32bits here since we transformed the pointers to offsets in the string table on export + mEntries[i].mType = reinterpret_cast<const char*>(size_t(tmp.mType)); + mEntries[i].mName = reinterpret_cast<const char*>(size_t(tmp.mName)); + mEntries[i].mOffset = tmp.mOffset; + mEntries[i].mSize = tmp.mSize; + mEntries[i].mCount = tmp.mCount; + mEntries[i].mOffsetSize = tmp.mOffsetSize; + mEntries[i].mFlags = tmp.mFlags; + mEntries[i].mAlignment = tmp.mAlignment; + } + } + else + { + assert(mSizeOfPtr==4); +// inputStream.read(mEntries, mNbEntries*sizeof(PxMetaDataEntry)); + for(int i=0;i<mNbEntries;i++) + { + MetaDataEntry32 tmp; + inputStream.read(&tmp, sizeof(MetaDataEntry32)); + if (mFlip) + { + flip(tmp.mType); + flip(tmp.mName); + } + mEntries[i].mType = reinterpret_cast<const char*>(size_t(tmp.mType)); + mEntries[i].mName = reinterpret_cast<const char*>(size_t(tmp.mName)); + mEntries[i].mOffset = tmp.mOffset; + mEntries[i].mSize = tmp.mSize; + mEntries[i].mCount = tmp.mCount; + mEntries[i].mOffsetSize = tmp.mOffsetSize; + mEntries[i].mFlags = tmp.mFlags; + mEntries[i].mAlignment = tmp.mAlignment; + } + } + + if(mFlip) + { + for(int i=0;i<mNbEntries;i++) + { + // mEntries[i].mType and mEntries[i].mName have been flipped already because they need special treatment + // on 64bit to 32bit platform conversions + flip(mEntries[i].mOffset); + flip(mEntries[i].mSize); + flip(mEntries[i].mCount); + flip(mEntries[i].mOffsetSize); + flip(mEntries[i].mFlags); + flip(mEntries[i].mAlignment); + } + } + + int nbConcreteType; + inputStream.read(&nbConcreteType, 4); + if(mFlip) + flip(nbConcreteType); + + for(int i=0; i<nbConcreteType; i++) + { + PxU16 concreteType; + PxU32 nameOffset; + inputStream.read(&concreteType, 2); + inputStream.read(&nameOffset, 4); + if(mFlip) + { + flip(concreteType); + flip(nameOffset); + } + + mConcreteTypeTable.pushBack( Ps::Pair<PxConcreteType::Enum, PxU32>(PxConcreteType::Enum(concreteType), nameOffset) ); + } + + int tableSize; + inputStream.read(&tableSize, 4); + if(mFlip) + flip(tableSize); + + mStringTable = reinterpret_cast<char*>(PX_ALLOC(sizeof(char)*tableSize, "MetaData StringTable")); + inputStream.read(mStringTable, PxU32(tableSize)); + } + + // Register atomic types + { + addNewClass("bool", 1, NULL, &ConvX::convert8); + addNewClass("char", 1, NULL, &ConvX::convert8); + addNewClass("short", 2, NULL, &ConvX::convert16); + addNewClass("int", 4, NULL, &ConvX::convert32); + addNewClass("PxU64", 8, NULL, &ConvX::convert64); + addNewClass("float", 4, NULL, &ConvX::convertFloat); + + addNewClass("paddingByte", 1, NULL, &ConvX::convertPad8); + } + + { + MetaClass* currentClass = NULL; + for(int i=0;i<mNbEntries;i++) + { + mEntries[i].mType = offsetToText(mEntries[i].mType); + mEntries[i].mName = offsetToText(mEntries[i].mName); + + if(mEntries[i].mFlags & PxMetaDataFlag::eTYPEDEF) + { + mConvX.displayMessage(PxErrorCode::eDEBUG_INFO, "Found typedef: %s => %s\n", mEntries[i].mName, mEntries[i].mType); + MetaClass* mc = getMetaClass(mEntries[i].mName); + if(mc) + addNewClass(mEntries[i].mType, mc->mSize, mc, mc->mCallback); + else + mConvX.displayMessage(PxErrorCode::eINTERNAL_ERROR, + "PxBinaryConverter: Invalid typedef - Missing metadata for: %s, please check the source metadata.\n" + , mEntries[i].mName); + } + else if(mEntries[i].mFlags & PxMetaDataFlag::eCLASS) + { + if(!mEntries[i].mName) + { + mConvX.displayMessage(PxErrorCode::eDEBUG_INFO, "Found class: %s\n", mEntries[i].mType); + currentClass = addNewClass(mEntries[i].mType, mEntries[i].mSize); + + if(mEntries[i].mFlags & PxMetaDataFlag::eVIRTUAL) + { + PxMetaDataEntry vtable; + vtable.mType = gVTablePtr; + vtable.mName = gVTablePtr; + vtable.mOffset = 0; + vtable.mSize = mSizeOfPtr; + vtable.mCount = 1; + vtable.mFlags = PxMetaDataFlag::ePTR; + currentClass->mFields.pushBack(vtable); + } + } + else + { + assert(currentClass); + mConvX.displayMessage(PxErrorCode::eDEBUG_INFO, " - inherits from: %s\n", mEntries[i].mName); + currentClass->mBaseClasses.pushBack(mEntries[i]); + } + } + else + { + const int isUnion = mEntries[i].mFlags & PxMetaDataFlag::eUNION; + + if(isUnion && !mEntries[i].mSize) + { + mConvX.registerUnionType(mEntries[i].mType, mEntries[i].mName, mEntries[i].mOffset); + } + else + { + if(isUnion) + { + mConvX.registerUnion(mEntries[i].mType); + } + + const int isPadding = mEntries[i].mFlags & PxMetaDataFlag::ePADDING; + + assert(currentClass); +#ifdef REMOVE_EXPLICIT_PADDING + if(!isPadding) +#endif + currentClass->mFields.pushBack(mEntries[i]); + + if(isPadding) + mConvX.displayMessage(PxErrorCode::eDEBUG_INFO, + " - contains padding: %s - %s\n", mEntries[i].mType, mEntries[i].mName); + else if(mEntries[i].mFlags & PxMetaDataFlag::eEXTRA_DATA) + mConvX.displayMessage(PxErrorCode::eDEBUG_INFO, + " - contains extra data: %s%s\n", mEntries[i].mType, mEntries[i].mFlags & PxMetaDataFlag::ePTR ? "*" : ""); + else + mConvX.displayMessage(PxErrorCode::eDEBUG_INFO, + " - contains field: %s%s\n", mEntries[i].mType, mEntries[i].mFlags & PxMetaDataFlag::ePTR ? "*" : ""); + + } + } + } + } + + // Sort classes by depth + struct Local + { + static bool _computeDepth(const MetaData& md, MetaClass* current, int currentDepth, int& maxDepth) + { + if(currentDepth>maxDepth) + maxDepth = currentDepth; + + PxU32 nbBases = current->mBaseClasses.size(); + for(PxU32 i=0;i<nbBases;i++) + { + const PxMetaDataEntry& baseClassEntry = current->mBaseClasses[i]; + MetaClass* baseClass = md.getMetaClass(baseClassEntry.mName); + if(!baseClass) + { + md.mConvX.displayMessage(PxErrorCode::eINTERNAL_ERROR, + "PxBinaryConverter: Can't find class %s metadata, please check the source metadata.\n", baseClassEntry.mName); + return false; + } + if (!_computeDepth(md, baseClass, currentDepth+1, maxDepth)) + return false; + } + return true; + } + + static int compareClasses(const void* c0, const void* c1) + { + MetaClass** mc0 = reinterpret_cast<MetaClass**>(const_cast<void*>(c0)); + MetaClass** mc1 = reinterpret_cast<MetaClass**>(const_cast<void*>(c1)); +// return (*mc0)->mSize - (*mc1)->mSize; + return (*mc0)->mDepth - (*mc1)->mDepth; + } + + static int compareEntries(const void* c0, const void* c1) + { + PxMetaDataEntry* mc0 = reinterpret_cast<PxMetaDataEntry*>(const_cast<void*>(c0)); + PxMetaDataEntry* mc1 = reinterpret_cast<PxMetaDataEntry*>(const_cast<void*>(c1)); + //mOffset is used to access control information for extra data, and not for offsets of the data itself. + assert(!(mc0->mFlags & PxMetaDataFlag::eEXTRA_DATA)); + assert(!(mc1->mFlags & PxMetaDataFlag::eEXTRA_DATA)); + return mc0->mOffset - mc1->mOffset; + } + }; + { + // Compute depths + const PxU32 nbMetaClasses = mMetaClasses.size(); + for(PxU32 i=0;i<nbMetaClasses;i++) + { + MetaClass* current = mMetaClasses[i]; + int maxDepth = 0; + if(!Local::_computeDepth(*this, current, 0, maxDepth)) + return false; + current->mDepth = maxDepth; + } + + // Sort by depth + MetaClass** metaClasses = &mMetaClasses[0]; + qsort(metaClasses, size_t(nbMetaClasses), sizeof(MetaClass*), Local::compareClasses); + } + + // Replicate fields from base classes + { + PxU32 nbMetaClasses = mMetaClasses.size(); + for(PxU32 k=0;k<nbMetaClasses;k++) + { + MetaClass* current = mMetaClasses[k]; + PxU32 nbBases = current->mBaseClasses.size(); + + // merge entries of base classes and current class in the right order + // this is needed for extra data ordering, which is not covered by the mOffset sort + // in the next stage below + PsArray<PxMetaDataEntry> mergedEntries; + + for(PxU32 i=0;i<nbBases;i++) + { + const PxMetaDataEntry& baseClassEntry = current->mBaseClasses[i]; + MetaClass* baseClass = getMetaClass(baseClassEntry.mName); + assert(baseClass); + assert(baseClass->mBaseClasses.size()==0 || baseClass->mProcessed); + + PxU32 nbBaseFields = baseClass->mFields.size(); + for(PxU32 j=0;j<nbBaseFields;j++) + { + PxMetaDataEntry f = baseClass->mFields[j]; + // Don't merge primary v-tables to avoid redundant v-table entries. + // It means the base v-table won't be inherited & needs to be explicitly defined in the metadata. Seems reasonable. + // Could be done better though. + + if(f.mType==gVTablePtr && !f.mOffset && !baseClassEntry.mOffset) + continue; + + f.mOffset += baseClassEntry.mOffset; + mergedEntries.pushBack(f); + } + current->mProcessed = true; + } + + //append current fields to base class fields + for (PxU32 i = 0; i < current->mFields.size(); i++) + { + mergedEntries.pushBack(current->mFields[i]); + } + current->mFields.clear(); + current->mFields.assign(mergedEntries.begin(), mergedEntries.end()); + } + } + + // Check classes + { + PxU32 nbMetaClasses = mMetaClasses.size(); + for(PxU32 i=0;i<nbMetaClasses;i++) + { + MetaClass* current = mMetaClasses[i]; + if(!current->check(*this)) + return false; + } + } + + // Sort meta-data by offset + { + PxU32 nbMetaClasses = mMetaClasses.size(); + for(PxU32 i=0;i<nbMetaClasses;i++) + { + MetaClass* current = mMetaClasses[i]; + PxU32 nbFields = current->mFields.size(); + if(nbFields<2) + continue; + PxMetaDataEntry* entries = ¤t->mFields[0]; + + PxMetaDataEntry* newEntries = PX_NEW(PxMetaDataEntry)[nbFields]; + PxU32 nb = 0; + for(PxU32 j=0;j<nbFields;j++) + if(!(entries[j].mFlags & PxMetaDataFlag::eEXTRA_DATA)) + newEntries[nb++] = entries[j]; + PxU32 nbToSort = nb; + for(PxU32 j=0;j<nbFields;j++) + if(entries[j].mFlags & PxMetaDataFlag::eEXTRA_DATA) + newEntries[nb++] = entries[j]; + assert(nb==nbFields); + memcpy(entries, newEntries, nb*sizeof(PxMetaDataEntry)); + PX_DELETE_ARRAY(newEntries); + qsort(entries, size_t(nbToSort), sizeof(PxMetaDataEntry), Local::compareEntries); + } + } + return true; +} + +/////////////////////////////////////////////////////////////////////////////// + +void ConvX::releaseMetaData() +{ + DELETESINGLE(mMetaData_Dst); + DELETESINGLE(mMetaData_Src); +} + +const MetaData* ConvX::loadMetaData(PxInputStream& inputStream, MetaDataType type) +{ + if (type != META_DATA_SRC && type != META_DATA_DST) + { + displayMessage(PxErrorCode::eINTERNAL_ERROR, + "PxBinaryConverter: Wrong meta data type, please check the source metadata.\n"); + return NULL; + } + + PX_ASSERT(type == META_DATA_SRC || type == META_DATA_DST); + + MetaData*& metaDataPtr = (type == META_DATA_SRC) ? mMetaData_Src : mMetaData_Dst; + metaDataPtr = PX_NEW(MetaData)(*this); + if(!(metaDataPtr)->load(inputStream, type)) + DELETESINGLE(metaDataPtr); + return metaDataPtr; +} + +const MetaData* ConvX::getBinaryMetaData(MetaDataType type) +{ + if(type==META_DATA_SRC) + return mMetaData_Src; + if(type==META_DATA_DST) + return mMetaData_Dst; + PX_ASSERT(0); + return NULL; +} + +int ConvX::getNbMetaClasses(MetaDataType type) +{ + if(type==META_DATA_SRC) + return mMetaData_Src->getNbMetaClasses(); + if(type==META_DATA_DST) + return mMetaData_Dst->getNbMetaClasses(); + PX_ASSERT(0); + return 0; +} + +MetaClass* ConvX::getMetaClass(unsigned int i, MetaDataType type) const +{ + if(type==META_DATA_SRC) + return mMetaData_Src->getMetaClass(i); + if(type==META_DATA_DST) + return mMetaData_Dst->getMetaClass(i); + PX_ASSERT(0); + return NULL; +} + +MetaClass* ConvX::getMetaClass(const char* name, MetaDataType type) const +{ + if(type==META_DATA_SRC) + return mMetaData_Src->getMetaClass(name); + if(type==META_DATA_DST) + return mMetaData_Dst->getMetaClass(name); + PX_ASSERT(0); + return NULL; +} + +MetaClass* ConvX::getMetaClass(PxConcreteType::Enum concreteType, MetaDataType type) +{ + MetaClass* metaClass = NULL; + if(type==META_DATA_SRC) + metaClass = mMetaData_Src->getMetaClass(concreteType); + if(type==META_DATA_DST) + metaClass = mMetaData_Dst->getMetaClass(concreteType); + + if(!metaClass) + { + displayMessage(PxErrorCode::eINTERNAL_ERROR, + "PxBinaryConverter: Missing concreteType %d metadata! serialized a class without dumping metadata. Please check the metadata.", + concreteType); + return NULL; + } + + return metaClass; +} + +/////////////////////////////////////////////////////////////////////////////// + +// Peek & poke, yes sir. +PxU64 physx::Sn::peek(int size, const char* buffer, int flags) +{ + const int maskMSB = flags & PxMetaDataFlag::eCOUNT_MASK_MSB; + const int skipIfOne = flags & PxMetaDataFlag::eCOUNT_SKIP_IF_ONE; + switch(size) + { + case 1: + { + unsigned char value = *(reinterpret_cast<const unsigned char*>(buffer)); + if(maskMSB) + value &= 0x7f; + if(skipIfOne && value==1) + return 0; + return PxU64(value); + } + case 2: + { + unsigned short value = *(reinterpret_cast<const unsigned short*>(buffer)); + if(maskMSB) + value &= 0x7fff; + if(skipIfOne && value==1) + return 0; + return PxU64(value); + } + case 4: + { + unsigned int value = *(reinterpret_cast<const unsigned int*>(buffer)); + if(maskMSB) + value &= 0x7fffffff; + if(skipIfOne && value==1) + return 0; + return PxU64(value); + } + case 8: + { + PxU64 value = *(reinterpret_cast<const PxU64*>(buffer)); + if(maskMSB) + value &= (PxU64(-1))>>1; + if(skipIfOne && value==1) + return 0; + return value; + } + }; + PX_ASSERT(0); + return PxU64(-1); +} + + diff --git a/PhysX_3.4/Source/PhysXExtensions/src/serialization/Binary/SnConvX_MetaData.h b/PhysX_3.4/Source/PhysXExtensions/src/serialization/Binary/SnConvX_MetaData.h new file mode 100644 index 00000000..29597b62 --- /dev/null +++ b/PhysX_3.4/Source/PhysXExtensions/src/serialization/Binary/SnConvX_MetaData.h @@ -0,0 +1,186 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and related documentation and +// any modifications thereto. Any use, reproduction, disclosure, or +// distribution of this software and related documentation without an express +// license agreement from NVIDIA Corporation is strictly prohibited. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 NVIDIA Corporation. All rights reserved. + +#ifndef PX_CONVX_METADATA_H +#define PX_CONVX_METADATA_H + +#include "SnConvX_Output.h" +#include "PxMetaDataFlags.h" + +namespace physx { namespace Sn { + +#if PX_VC +#pragma warning (push) +#pragma warning (disable : 4371) //layout of class may have changed from a previous version of the compiler due to better packing of member +#endif + + + // PT: beware, must match corresponding structure in PxMetaData.h + struct PxMetaDataEntry : public shdfnd::UserAllocated + { + PxMetaDataEntry() + { + memset(this, 0, sizeof(*this)); + } + bool isVTablePtr() const; + + const char* mType; //!< Field type (bool, byte, quaternion, etc) + const char* mName; //!< Field name (appears exactly as in the source file) + int mOffset; //!< Offset from the start of the class (ie from "this", field is located at "this"+Offset) + int mSize; //!< sizeof(Type) + int mCount; //!< Number of items of type Type (0 for dynamic sizes) + int mOffsetSize; //!< Offset of dynamic size param, for dynamic arrays + int mFlags; //!< Field parameters + int mAlignment; //!< Explicit alignment added for DE1340 + }; + + struct MetaDataEntry32 + { + PxI32 mType; //!< Field type (bool, byte, quaternion, etc) + PxI32 mName; //!< Field name (appears exactly as in the source file) + int mOffset; //!< Offset from the start of the class (ie from "this", field is located at "this"+Offset) + int mSize; //!< sizeof(Type) + int mCount; //!< Number of items of type Type (0 for dynamic sizes) + int mOffsetSize; //!< Offset of dynamic size param, for dynamic arrays + int mFlags; //!< Field parameters + int mAlignment; //!< Explicit alignment added for DE1340 + }; + + struct MetaDataEntry64 + { + PxI64 mType; //!< Field type (bool, byte, quaternion, etc) + PxI64 mName; //!< Field name (appears exactly as in the source file) + int mOffset; //!< Offset from the start of the class (ie from "this", field is located at "this"+Offset) + int mSize; //!< sizeof(Type) + int mCount; //!< Number of items of type Type (0 for dynamic sizes) + int mOffsetSize; //!< Offset of dynamic size param, for dynamic arrays + int mFlags; //!< Field parameters + int mAlignment; //!< Explicit alignment added for DE1340 + }; + + struct ExtraDataEntry + { + PxMetaDataEntry entry; + int offset; + }; + + struct ExtraDataEntry2 : ExtraDataEntry + { + ConvertCallback cb; + }; + + class MetaData; + + struct MetaClass : public shdfnd::UserAllocated + { + bool getFieldByType(const char* type, PxMetaDataEntry& entry) const; + bool getFieldByName(const char* name, PxMetaDataEntry& entry) const; + bool check(const MetaData& owner); + + ConvertCallback mCallback; + MetaClass* mMaster; + const char* mClassName; + int mSize; + int mDepth; + PsArray<PxMetaDataEntry> mBaseClasses; + PsArray<PxMetaDataEntry> mFields; + bool mProcessed; + +// int mNbEntries; +// ExtraDataEntry2 mEntries[256]; + + private: + void checkAndCompleteClass(const MetaData& owner, int& startOffset, int& nbBytes); + }; + + enum MetaDataType + { + META_DATA_NONE, + META_DATA_SRC, + META_DATA_DST + }; + + class ConvX; + class MetaData : public shdfnd::UserAllocated + { + public: + MetaData(Sn::ConvX&); + ~MetaData(); + + bool load(PxInputStream& inputStream, MetaDataType type); + + inline_ MetaDataType getType() const { return mType; } + inline_ int getVersion() const { return mVersion; } + inline_ int getBuildNumber() const { return mBuildNumber; } + inline_ int getPtrSize() const { return mSizeOfPtr; } + inline_ int getPlatformTag() const { return mPlatformTag; } + inline_ int getGaussMapLimit() const { return mGaussMapLimit; } + inline_ int getNbMetaClasses() const { return int(mMetaClasses.size()); } + inline_ MetaClass* getMetaClass(unsigned int i) const { return mMetaClasses[i]; } + inline_ bool getFlip() const { return mFlip; } + + MetaClass* getMetaClass(const char* name) const; + MetaClass* getMetaClass(PxConcreteType::Enum concreteType) const; + MetaClass* addNewClass(const char* name, int size, MetaClass* master=NULL, ConvertCallback callback=NULL); + private: + MetaData& operator=(const MetaData&); + Sn::ConvX& mConvX; + MetaDataType mType; + int mNbEntries; + PxMetaDataEntry* mEntries; + char* mStringTable; + PsArray<MetaClass*> mMetaClasses; + int mVersion; + int mBinaryVersion; + int mBuildNumber; + int mSizeOfPtr; + int mPlatformTag; + int mGaussMapLimit; + bool mFlip; + + PsArray< Ps::Pair<PxConcreteType::Enum, PxU32> > mConcreteTypeTable; + + inline_ const char* offsetToText(const char* text) const + { + const size_t offset = size_t(text); + const PxU32 offset32 = PxU32(offset); +// if(offset==-1) + if(offset32==0xffffffff) + return NULL; + return mStringTable + offset32; + } + friend struct MetaClass; + }; + + PxU64 peek(int size, const char* buffer, int flags=0); + +#if PX_VC +#pragma warning (pop) +#endif +} } + +#endif diff --git a/PhysX_3.4/Source/PhysXExtensions/src/serialization/Binary/SnConvX_Output.cpp b/PhysX_3.4/Source/PhysXExtensions/src/serialization/Binary/SnConvX_Output.cpp new file mode 100644 index 00000000..9eaa601c --- /dev/null +++ b/PhysX_3.4/Source/PhysXExtensions/src/serialization/Binary/SnConvX_Output.cpp @@ -0,0 +1,451 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and related documentation and +// any modifications thereto. Any use, reproduction, disclosure, or +// distribution of this software and related documentation without an express +// license agreement from NVIDIA Corporation is strictly prohibited. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 NVIDIA Corporation. All rights reserved. + +#include "foundation/PxIO.h" +#include "foundation/PxErrorCallback.h" +#include "SnConvX.h" + +#if PX_VC +#pragma warning(disable:4389) // signed/unsigned mismatch +#endif + +using namespace physx; + +void Sn::ConvX::setNullPtr(bool flag) +{ + mNullPtr = flag; +} + +void Sn::ConvX::setNoOutput(bool flag) +{ + mNoOutput = flag; +} + +bool Sn::ConvX::initOutput(PxOutputStream& targetStream) +{ + mOutStream = &targetStream; + + mOutputSize = 0; + mNullPtr = false; + mNoOutput = false; + + const MetaData* srcMetaData = getBinaryMetaData(META_DATA_SRC); + PX_ASSERT(srcMetaData); + const MetaData* dstMetaData = getBinaryMetaData(META_DATA_DST); + PX_ASSERT(dstMetaData); + + mSrcPtrSize = srcMetaData->getPtrSize(); + mDstPtrSize = dstMetaData->getPtrSize(); + + PX_ASSERT(!srcMetaData->getFlip()); + mMustFlip = dstMetaData->getFlip(); + return true; +} + +void Sn::ConvX::closeOutput() +{ + mOutStream = NULL; +} + +int Sn::ConvX::getCurrentOutputSize() +{ + return mOutputSize; +} + +void Sn::ConvX::output(short value) +{ + if(mNoOutput) + return; + + if(mMustFlip) + flip(value); + + PX_ASSERT(mOutStream); + const size_t size = mOutStream->write(&value, 2); + PX_ASSERT(size==2); + mOutputSize += int(size); +} + +void Sn::ConvX::output(int value) +{ + if(mNoOutput) + return; + + if(mMustFlip) + flip(value); + + PX_ASSERT(mOutStream); + const size_t size = mOutStream->write(&value, 4); + PX_ASSERT(size==4); + mOutputSize += int(size); +} + +//ntohll is a macro on apple yosemite +static PxU64 ntohll_internal(const PxU64 value) +{ + union + { + PxU64 ull; + PxU8 c[8]; + } x; + + x.ull = value; + + PxU8 c = 0; + c = x.c[0]; x.c[0] = x.c[7]; x.c[7] = c; + c = x.c[1]; x.c[1] = x.c[6]; x.c[6] = c; + c = x.c[2]; x.c[2] = x.c[5]; x.c[5] = c; + c = x.c[3]; x.c[3] = x.c[4]; x.c[4] = c; + + return x.ull; +} + +void Sn::ConvX::output(PxU64 value) +{ + if(mNoOutput) + return; + + if(mMustFlip) +// flip(value); + value = ntohll_internal(value); + + PX_ASSERT(mOutStream); + const size_t size = mOutStream->write(&value, 8); + PX_ASSERT(size==8); + mOutputSize += int(size); +} + +void Sn::ConvX::output(const char* buffer, int nbBytes) +{ + if(mNoOutput) + return; + + if(!nbBytes) + return; + + PX_ASSERT(mOutStream); + const PxU32 size = mOutStream->write(buffer, PxU32(nbBytes)); + PX_ASSERT(size== PxU32(nbBytes)); + mOutputSize += int(size); +} + +void Sn::ConvX::convert8(const char* src, const PxMetaDataEntry& entry, const PxMetaDataEntry& dstEntry) +{ + (void)dstEntry; + if(mNoOutput) + return; + + PX_ASSERT(entry.mSize==1*entry.mCount); + PX_ASSERT(mOutStream); + PX_ASSERT(entry.mSize==dstEntry.mSize); + + const PxU32 size = mOutStream->write(src, PxU32(entry.mSize)); + PX_ASSERT(size== PxU32(entry.mSize)); + mOutputSize += int(size); +} + +// This is called to convert auto-generated "padding bytes" (or so we think). +// We use a special converter to check the input bytes and issue warnings when it doesn't look like padding +void Sn::ConvX::convertPad8(const char* src, const PxMetaDataEntry& entry, const PxMetaDataEntry& dstEntry) +{ + (void)dstEntry; + (void)src; + if(mNoOutput) + return; + + PX_ASSERT(entry.mSize); + PX_ASSERT(entry.mSize==1*entry.mCount); + PX_ASSERT(mOutStream); + PX_ASSERT(entry.mSize==dstEntry.mSize); + + // PT: we don't output the source data on purpose, to catch missing meta-data + // sschirm: changed that to 0xcd, so we can mark the output as "having marked pads" + const unsigned char b = 0xcd; + for(int i=0;i<entry.mSize;i++) + { + const size_t size = mOutStream->write(&b, 1); + (void)size; + } + mOutputSize += entry.mSize; +} + +void Sn::ConvX::convert16(const char* src, const PxMetaDataEntry& entry, const PxMetaDataEntry& dstEntry) +{ + (void)dstEntry; + if(mNoOutput) + return; + + PX_ASSERT(entry.mSize==int(sizeof(short)*entry.mCount)); + PX_ASSERT(mOutStream); + PX_ASSERT(entry.mSize==dstEntry.mSize); + + const short* data = reinterpret_cast<const short*>(src); + for(int i=0;i<entry.mCount;i++) + { + short value = *data++; + if(mMustFlip) + flip(value); + + const size_t size = mOutStream->write(&value, sizeof(short)); + PX_ASSERT(size==sizeof(short)); + mOutputSize += int(size); + } +} + +void Sn::ConvX::convert32(const char* src, const PxMetaDataEntry& entry, const PxMetaDataEntry& dstEntry) +{ + (void)dstEntry; + if(mNoOutput) + return; + + PX_ASSERT(entry.mSize==int(sizeof(int)*entry.mCount)); + PX_ASSERT(mOutStream); + PX_ASSERT(entry.mSize==dstEntry.mSize); + + const int* data = reinterpret_cast<const int*>(src); + for(int i=0;i<entry.mCount;i++) + { + int value = *data++; + if(mMustFlip) + flip(value); + + const size_t size = mOutStream->write(&value, sizeof(int)); + PX_ASSERT(size==sizeof(int)); + mOutputSize += int(size); + } +} + +void Sn::ConvX::convert64(const char* src, const PxMetaDataEntry& entry, const PxMetaDataEntry& dstEntry) +{ + (void)dstEntry; + if(mNoOutput) + return; + + PX_ASSERT(entry.mSize==int(sizeof(PxU64)*entry.mCount)); + PX_ASSERT(mOutStream); + PX_ASSERT(entry.mSize==dstEntry.mSize); + + const PxU64* data = reinterpret_cast<const PxU64*>(src); + for(int i=0;i<entry.mCount;i++) + { + PxU64 value = *data++; + if(mMustFlip) + value = ntohll_internal(value); + + const size_t size = mOutStream->write(&value, sizeof(PxU64)); + PX_ASSERT(size==sizeof(PxU64)); + mOutputSize += int(size); + } +} + +void Sn::ConvX::convertFloat(const char* src, const PxMetaDataEntry& entry, const PxMetaDataEntry& dstEntry) +{ + (void)dstEntry; + if(mNoOutput) + return; + + PX_ASSERT(entry.mSize==int(sizeof(float)*entry.mCount)); + PX_ASSERT(mOutStream); + PX_ASSERT(entry.mSize==dstEntry.mSize); + + const float* data = reinterpret_cast<const float*>(src); + for(int i=0;i<entry.mCount;i++) + { + float value = *data++; + if(mMustFlip) + flip(value); + + const size_t size = mOutStream->write(&value, sizeof(float)); + PX_ASSERT(size==sizeof(float)); + mOutputSize += int(size); + } +} + +void Sn::ConvX::convertPtr(const char* src, const PxMetaDataEntry& entry, const PxMetaDataEntry& dstEntry) +{ + (void)dstEntry; + if(mNoOutput) + return; + + PX_ASSERT(entry.mSize==mSrcPtrSize*entry.mCount); + PX_ASSERT(mOutStream); + + char buffer[16]; + for(int i=0;i<entry.mCount;i++) + { + PxU64 testValue=0; + // Src pointer can be 4 or 8 bytes so we can't use "void*" here + if(mSrcPtrSize==4) + { + PX_ASSERT(sizeof(PxU32)==4); + const PxU32* data = reinterpret_cast<const PxU32*>(src); + PxU32 value = *data++; + src = reinterpret_cast<const char*>(data); + + if(mActiveRemap) + { + PxU32 ref; + if(mActiveRemap->getObjectRef(value, ref)) + { + value = ref; + } + else if(value) + { + // value = 0; + //We use the pointer of mName for its length + // PT: on serialization mName is transformed to an index by the name manager, so we should not modify its value. + if(!entry.mName || strcmp(entry.mName, "mName")) + value=0x12345678; + } + } + else + { + //we should only get here during convertReferenceTables to build up the pointer map + PxU32 ref; + if (mRemap.getObjectRef(value, ref)) + { + value = ref; + } + else if(value) + { + const PxU32 remappedRef = 0x80000000 | (mPointerRemapCounter++ +1); + mRemap.setObjectRef(value, remappedRef); + value = remappedRef; + } + } + + if(mMustFlip) + flip(value); + + if(mNullPtr) + value = 0; + + *reinterpret_cast<PxU32*>(buffer) = value; + } + else + { + PX_ASSERT(mSrcPtrSize==8); + PX_ASSERT(sizeof(PxU64)==8); + const PxU64* data = reinterpret_cast<const PxU64*>(src); + PxU64 value = *data++; + src = reinterpret_cast<const char*>(data); + + if(mActiveRemap) + { + PxU32 ref; + if(mActiveRemap->getObjectRef(value, ref)) + { + value = ref; + } + else if(value) + { + // value = 0; + //We use the pointer of mName for its length + // PT: on serialization mName is transformed to an index by the name manager, so we should not modify its value. + if(!entry.mName || strcmp(entry.mName, "mName")) + value=0x12345678; + } + } + else + { + //we should only get here during convertReferenceTables to build up the pointer map + PxU32 ref; + if (mRemap.getObjectRef(value, ref)) + { + value = ref; + } + else if(value) + { + const PxU32 remappedRef = 0x80000000 | (mPointerRemapCounter++ +1); + mRemap.setObjectRef(value, remappedRef); + value = remappedRef; + } + } + +// PX_ASSERT(!mMustFlip); +// if(mMustFlip) +// flip(value); + + if(mNullPtr) + value = 0; + + testValue = value; + + *reinterpret_cast<PxU64*>(buffer) = value; + } + + if(mSrcPtrSize==mDstPtrSize) + { + const size_t size = mOutStream->write(buffer, PxU32(mSrcPtrSize)); + PX_ASSERT(size==PxU32(mSrcPtrSize)); + mOutputSize += int(size); + } + else + { + if(mDstPtrSize>mSrcPtrSize) + { + // 32bit to 64bit + PX_ASSERT(mDstPtrSize==8); + PX_ASSERT(mSrcPtrSize==4); + + // We need to output the lower 32bits first for PC. Might be different on a 64bit console.... + + // Output src ptr for the lower 32bits + const size_t size = mOutStream->write(buffer, PxU32(mSrcPtrSize)); + PX_ASSERT(size==PxU32(mSrcPtrSize)); + mOutputSize += int(size); + + // Output zeros for the higher 32bits + const int zero = 0; + const size_t size0 = mOutStream->write(&zero, 4); + PX_ASSERT(size0==4); + mOutputSize += int(size0); + } + else + { + // 64bit to 32bit + PX_ASSERT(mSrcPtrSize==8); + PX_ASSERT(mDstPtrSize==4); + + // Not sure how we can safely convert 64bit ptrs to 32bit... just drop the high 32 bits?!? + + PxU32 ptr32 = *reinterpret_cast<PxU32*>(buffer); + (void)ptr32; + PxU32 ptr32b = PxU32(testValue); + (void)ptr32b; + + if(mMustFlip) + flip(ptr32b); + + // Output src ptr for the lower 32bits + const size_t size = mOutStream->write(&ptr32b, 4); + PX_ASSERT(size==4); + mOutputSize += int(size); + } + } + } +} diff --git a/PhysX_3.4/Source/PhysXExtensions/src/serialization/Binary/SnConvX_Output.h b/PhysX_3.4/Source/PhysXExtensions/src/serialization/Binary/SnConvX_Output.h new file mode 100644 index 00000000..6eaf7b99 --- /dev/null +++ b/PhysX_3.4/Source/PhysXExtensions/src/serialization/Binary/SnConvX_Output.h @@ -0,0 +1,112 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and related documentation and +// any modifications thereto. Any use, reproduction, disclosure, or +// distribution of this software and related documentation without an express +// license agreement from NVIDIA Corporation is strictly prohibited. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 NVIDIA Corporation. All rights reserved. + +#ifndef PX_CONVX_OUTPUT_H +#define PX_CONVX_OUTPUT_H + +#include "foundation/PxSimpleTypes.h" + +namespace physx { namespace Sn { + + struct PxMetaDataEntry; + class ConvX; + + typedef void (Sn::ConvX::*ConvertCallback) (const char* src, const PxMetaDataEntry& entry, const PxMetaDataEntry& dstEntry); + + inline_ void flip(PxI16& v) + { + PxI8* b = reinterpret_cast<PxI8*>(&v); + PxI8 temp = b[0]; + b[0] = b[1]; + b[1] = temp; + } + + inline_ void flip(PxU16& v) + { + flip(reinterpret_cast<PxI16&>(v)); + } + + inline_ void flip32(PxI8* b) + { + PxI8 temp = b[0]; + b[0] = b[3]; + b[3] = temp; + temp = b[1]; + b[1] = b[2]; + b[2] = temp; + } + + inline_ void flip(PxI32& v) + { + PxI8* b = reinterpret_cast<PxI8*>(&v); + flip32(b); + } + + inline_ void flip(PxU32& v) + { + PxI8* b = reinterpret_cast<PxI8*>(&v); + flip32(b); + } + + inline_ void flip(PxI64& v) + { + PxI8* b = reinterpret_cast<PxI8*>(&v); + + PxI8 temp = b[0]; + b[0] = b[7]; + b[7] = temp; + temp = b[1]; + b[1] = b[6]; + b[6] = temp; + temp = b[2]; + b[2] = b[5]; + b[5] = temp; + temp = b[3]; + b[3] = b[4]; + b[4] = temp; + } + + inline_ void flip(PxF32& v) + { + PxI8* b = reinterpret_cast<PxI8*>(&v); + flip32(b); + } + + inline_ void flip(void*& v) + { + PxI8* b = reinterpret_cast<PxI8*>(&v); + flip32(b); + } + + inline_ void flip(const PxI8*& v) + { + PxI8* b = const_cast<PxI8*>(v); + flip32(b); + } +} } + +#endif diff --git a/PhysX_3.4/Source/PhysXExtensions/src/serialization/Binary/SnConvX_Union.cpp b/PhysX_3.4/Source/PhysXExtensions/src/serialization/Binary/SnConvX_Union.cpp new file mode 100644 index 00000000..ddff8df1 --- /dev/null +++ b/PhysX_3.4/Source/PhysXExtensions/src/serialization/Binary/SnConvX_Union.cpp @@ -0,0 +1,90 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and related documentation and +// any modifications thereto. Any use, reproduction, disclosure, or +// distribution of this software and related documentation without an express +// license agreement from NVIDIA Corporation is strictly prohibited. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 NVIDIA Corporation. All rights reserved. + +#include "SnConvX.h" +#include <assert.h> + +using namespace physx; + +void Sn::ConvX::resetUnions() +{ + mUnions.clear(); +} + +bool Sn::ConvX::registerUnion(const char* name) +{ + displayMessage(PxErrorCode::eDEBUG_INFO, "Registering union: %s\n", name); + + Sn::Union u; + u.mName = name; + + mUnions.pushBack(u); + return true; +} + +bool Sn::ConvX::registerUnionType(const char* unionName, const char* typeName, int typeValue) +{ + const PxU32 nb = mUnions.size(); + for(PxU32 i=0;i<nb;i++) + { + if(strcmp(mUnions[i].mName, unionName)==0) + { + UnionType t; + t.mTypeName = typeName; + t.mTypeValue = typeValue; + mUnions[i].mTypes.pushBack(t); + displayMessage(PxErrorCode::eDEBUG_INFO, "Registering union type: %s | %s | %d\n", unionName, typeName, typeValue); + return true; + } + } + + displayMessage(PxErrorCode::eINTERNAL_ERROR, "PxBinaryConverter: union not found: %s, please check the source metadata.\n", unionName); + return false; +} + +const char* Sn::ConvX::getTypeName(const char* unionName, int typeValue) +{ + const PxU32 nb = mUnions.size(); + for(PxU32 i=0;i<nb;i++) + { + if(strcmp(mUnions[i].mName, unionName)==0) + { + const PxU32 nbTypes = mUnions[i].mTypes.size(); + for(PxU32 j=0;j<nbTypes;j++) + { + const UnionType& t = mUnions[i].mTypes[j]; + if(t.mTypeValue==typeValue) + return t.mTypeName; + } + break; + } + } + displayMessage(PxErrorCode::eINTERNAL_ERROR, + "PxBinaryConverter: union type not found: %s, type %d, please check the source metadata.\n", unionName, typeValue); + assert(0); + return NULL; +} diff --git a/PhysX_3.4/Source/PhysXExtensions/src/serialization/Binary/SnConvX_Union.h b/PhysX_3.4/Source/PhysXExtensions/src/serialization/Binary/SnConvX_Union.h new file mode 100644 index 00000000..6c94a12c --- /dev/null +++ b/PhysX_3.4/Source/PhysXExtensions/src/serialization/Binary/SnConvX_Union.h @@ -0,0 +1,45 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and related documentation and +// any modifications thereto. Any use, reproduction, disclosure, or +// distribution of this software and related documentation without an express +// license agreement from NVIDIA Corporation is strictly prohibited. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 NVIDIA Corporation. All rights reserved. + +#ifndef PX_UNION_H +#define PX_UNION_H + +namespace physx { namespace Sn { + struct UnionType + { + const char* mTypeName; + int mTypeValue; + }; + + struct Union + { + const char* mName; + PsArray<UnionType> mTypes; + }; +} } + +#endif diff --git a/PhysX_3.4/Source/PhysXExtensions/src/serialization/Binary/SnSerializationContext.cpp b/PhysX_3.4/Source/PhysXExtensions/src/serialization/Binary/SnSerializationContext.cpp new file mode 100644 index 00000000..ef46d552 --- /dev/null +++ b/PhysX_3.4/Source/PhysXExtensions/src/serialization/Binary/SnSerializationContext.cpp @@ -0,0 +1,94 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and related documentation and +// any modifications thereto. Any use, reproduction, disclosure, or +// distribution of this software and related documentation without an express +// license agreement from NVIDIA Corporation is strictly prohibited. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + +#include "PxBase.h" +#include "SnSerializationContext.h" +#include "PsFoundation.h" + +using namespace physx; +using namespace Sn; + +PxBase* DeserializationContext::resolveReference(PxU32 kind, size_t reference) const +{ + const InternalRefMap::Entry* entry0 = mInternalReferencesMap.find(InternalRefKey(reference, kind)); + PX_ASSERT(entry0); + SerialObjectIndex objIndex = entry0->second; + bool isExternal; + PxU32 index = objIndex.getIndex(isExternal); + PxBase* base = NULL; + if (isExternal) + { + const ImportReference& entry = mImportReferences[index]; + base = mExternalRefs->find(entry.id); + } + else + { + const ManifestEntry& entry = mManifestTable[index]; + base = reinterpret_cast<PxBase*>(mObjectDataAddress + entry.offset); + } + PX_ASSERT(base); + return base; +} + +void SerializationContext::registerReference(PxBase& serializable, PxU32 kind, size_t reference) +{ +#if PX_CHECKED + if ((kind & PX_SERIAL_REF_KIND_PTR_TYPE_BIT) == 0 && reference > 0xffffffff) + { + Ps::getFoundation().error(PxErrorCode::eINVALID_PARAMETER, __FILE__, __LINE__, "PxSerializationContext::registerReference: only 32 bit indices supported."); + return; + } +#endif + + bool isExternal = mExternalRefs && mExternalRefs->contains(serializable); + PxU32 index; + if (isExternal) + { + PxSerialObjectId id = mExternalRefs->getId(serializable); + PX_ASSERT(id != PX_SERIAL_OBJECT_ID_INVALID); + if (const Ps::HashMap<PxSerialObjectId, PxU32>::Entry* entry = mImportReferencesMap.find(id)) + { + index = entry->second; + } + else + { + index = mImportReferences.size(); + mImportReferencesMap.insert(id, index); + mImportReferences.pushBack(ImportReference(id, serializable.getConcreteType())); + } + } + else + { + PX_ASSERT(mCollection.contains(serializable)); + index = mObjToCollectionIndexMap[&serializable]; + } + + InternalRefMap& targetMap = (kind & PX_SERIAL_REF_KIND_PTR_TYPE_BIT) ? mInternalReferencesPtrMap : mInternalReferencesIdxMap; + targetMap[InternalRefKey(reference, kind)] = SerialObjectIndex(index, isExternal); +} diff --git a/PhysX_3.4/Source/PhysXExtensions/src/serialization/Binary/SnSerializationContext.h b/PhysX_3.4/Source/PhysXExtensions/src/serialization/Binary/SnSerializationContext.h new file mode 100644 index 00000000..6bfa05e1 --- /dev/null +++ b/PhysX_3.4/Source/PhysXExtensions/src/serialization/Binary/SnSerializationContext.h @@ -0,0 +1,303 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and related documentation and +// any modifications thereto. Any use, reproduction, disclosure, or +// distribution of this software and related documentation without an express +// license agreement from NVIDIA Corporation is strictly prohibited. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + + +#ifndef PX_PHYSICS_SN_SERIALIZATION_CONTEXT +#define PX_PHYSICS_SN_SERIALIZATION_CONTEXT + +#include "foundation/PxAssert.h" +#include "foundation/PxMemory.h" +#include "CmPhysXCommon.h" +#include "PsHash.h" +#include "PsUserAllocated.h" +#include "PxSerialFramework.h" +#include "CmCollection.h" +#include "CmUtils.h" +#include "PxDefaultStreams.h" +#include "PsFoundation.h" +#include "SnConvX_Align.h" + +namespace physx +{ + namespace Sn + { + + struct ManifestEntry + { + //= ATTENTION! ===================================================================================== + // Changing the data layout of this class breaks the binary serialization format. See comments for + // PX_BINARY_SERIAL_VERSION. If a modification is required, please adjust the getBinaryMetaData + // function. If the modification is made on a custom branch, please change PX_BINARY_SERIAL_VERSION + // accordingly. + //================================================================================================== + + PX_FORCE_INLINE ManifestEntry(PxU32 _offset, PxType _type) + { + Cm::markSerializedMem(this, sizeof(ManifestEntry)); + offset = _offset; + type = _type; + } + PX_FORCE_INLINE ManifestEntry() { Cm::markSerializedMem(this, sizeof(ManifestEntry)); } + PX_FORCE_INLINE void operator =(const ManifestEntry& m) + { + PxMemCopy(this, &m, sizeof(ManifestEntry)); + } + + PxU32 offset; + PxType type; + }; + + struct ImportReference + { + //= ATTENTION! ===================================================================================== + // Changing the data layout of this class breaks the binary serialization format. See comments for + // PX_BINARY_SERIAL_VERSION. If a modification is required, please adjust the getBinaryMetaData + // function. If the modification is made on a custom branch, please change PX_BINARY_SERIAL_VERSION + // accordingly. + //================================================================================================== + + PX_FORCE_INLINE ImportReference(PxSerialObjectId _id, PxType _type) + { + Cm::markSerializedMem(this, sizeof(ImportReference)); + id = _id; + type = _type; + } + PX_FORCE_INLINE ImportReference() { Cm::markSerializedMem(this, sizeof(ImportReference)); } + PX_FORCE_INLINE void operator =(const ImportReference& m) + { + PxMemCopy(this, &m, sizeof(ImportReference)); + } + PxSerialObjectId id; + PxType type; + }; + +#define SERIAL_OBJECT_INDEX_TYPE_BIT (1u<<31) + struct SerialObjectIndex + { + //= ATTENTION! ===================================================================================== + // Changing the data layout of this class breaks the binary serialization format. See comments for + // PX_BINARY_SERIAL_VERSION. If a modification is required, please adjust the getBinaryMetaData + // function. If the modification is made on a custom branch, please change PX_BINARY_SERIAL_VERSION + // accordingly. + //================================================================================================== + + PX_FORCE_INLINE SerialObjectIndex(PxU32 index, bool external) { setIndex(index, external); } + PX_FORCE_INLINE SerialObjectIndex(const SerialObjectIndex& objIndex) : mObjIndex(objIndex.mObjIndex) {} + PX_FORCE_INLINE SerialObjectIndex() : mObjIndex(PX_INVALID_U32) {} + + PX_FORCE_INLINE void setIndex(PxU32 index, bool external) + { + PX_ASSERT((index & SERIAL_OBJECT_INDEX_TYPE_BIT) == 0); + mObjIndex = index | (external ? SERIAL_OBJECT_INDEX_TYPE_BIT : 0); + } + + PX_FORCE_INLINE PxU32 getIndex(bool& isExternal) + { + PX_ASSERT(mObjIndex != PX_INVALID_U32); + isExternal = (mObjIndex & SERIAL_OBJECT_INDEX_TYPE_BIT) > 0; + return mObjIndex & ~SERIAL_OBJECT_INDEX_TYPE_BIT; + } + + private: + PxU32 mObjIndex; + }; + + struct ExportReference + { + //= ATTENTION! ===================================================================================== + // Changing the data layout of this class breaks the binary serialization format. See comments for + // PX_BINARY_SERIAL_VERSION. If a modification is required, please adjust the getBinaryMetaData + // function. If the modification is made on a custom branch, please change PX_BINARY_SERIAL_VERSION + // accordingly. + //================================================================================================== + + PX_FORCE_INLINE ExportReference(PxSerialObjectId _id, SerialObjectIndex _objIndex) + { + Cm::markSerializedMem(this, sizeof(ExportReference)); + id = _id; + objIndex = _objIndex; + } + PX_FORCE_INLINE ExportReference() { Cm::markSerializedMem(this, sizeof(ExportReference)); } + PX_FORCE_INLINE void operator =(const ExportReference& m) + { + PxMemCopy(this, &m, sizeof(ExportReference)); + } + PxSerialObjectId id; + SerialObjectIndex objIndex; + }; + + template<class ReferenceType> + struct InternalReference + { + //= ATTENTION! ===================================================================================== + // Changing the data layout of this class breaks the binary serialization format. See comments for + // PX_BINARY_SERIAL_VERSION. If a modification is required, please adjust the getBinaryMetaData + // function. If the modification is made on a custom branch, please change PX_BINARY_SERIAL_VERSION + // accordingly. + //================================================================================================== + + PX_FORCE_INLINE InternalReference(ReferenceType _reference, PxU32 _kind, SerialObjectIndex _objIndex) + { + Cm::markSerializedMem(this, sizeof(InternalReference)); + reference = _reference; + kind = _kind; + objIndex = _objIndex; + } + PX_FORCE_INLINE InternalReference() { Cm::markSerializedMem(this, sizeof(InternalReference)); } + PX_FORCE_INLINE void operator =(const InternalReference& m) + { + PxMemCopy(this, &m, sizeof(InternalReference)); + } + ReferenceType reference; + PxU32 kind; + SerialObjectIndex objIndex; + }; + + typedef InternalReference<size_t> InternalReferencePtr; + typedef InternalReference<PxU32> InternalReferenceIdx; + + typedef shdfnd::Pair<size_t, PxU32> InternalRefKey; + typedef Cm::CollectionHashMap<InternalRefKey, SerialObjectIndex> InternalRefMap; + + class DeserializationContext : public PxDeserializationContext, public Ps::UserAllocated + { + PX_NOCOPY(DeserializationContext) + + public: + DeserializationContext(const ManifestEntry* manifestTable, + const ImportReference* importReferences, + PxU8* objectDataAddress, + const InternalRefMap& internalReferencesMap, + const Cm::Collection* externalRefs, + PxU8* extraData, + PxU32 physxVersion) + : mManifestTable(manifestTable) + , mImportReferences(importReferences) + , mObjectDataAddress(objectDataAddress) + , mInternalReferencesMap(internalReferencesMap) + , mExternalRefs(externalRefs) + , mPhysXVersion(physxVersion) + { + mExtraDataAddress = extraData; + } + + virtual PxBase* resolveReference(PxU32 kind, size_t reference) const; + + PxU32 getPhysXVersion() const { return mPhysXVersion; } + private: + //various pointers to deserialized data + const ManifestEntry* mManifestTable; + const ImportReference* mImportReferences; + PxU8* mObjectDataAddress; + + //internal references map for resolving references. + const InternalRefMap& mInternalReferencesMap; + + //external collection for resolving import references. + const Cm::Collection* mExternalRefs; + const PxU32 mPhysXVersion; + }; + + class SerializationContext : public PxSerializationContext, public Ps::UserAllocated + { + PX_NOCOPY(SerializationContext) + public: + SerializationContext(const Cm::Collection& collection, const Cm::Collection* externalRefs) + : mCollection(collection) + , mExternalRefs(externalRefs) + { + // fill object to collection index map (same ordering as manifest) + for (PxU32 i=0;i<mCollection.internalGetNbObjects();i++) + { + mObjToCollectionIndexMap[mCollection.internalGetObject(i)] = i; + } + } + + virtual void writeData(const void* buffer, PxU32 size) { mMemStream.write(buffer, size); } + virtual PxU32 getTotalStoredSize() { return mMemStream.getSize(); } + virtual void alignData(PxU32 alignment = PX_SERIAL_ALIGN) + { + if(!alignment) + return; + + PxI32 bytesToPad = PxI32(getPadding(mMemStream.getSize(), alignment)); + static const PxI32 BUFSIZE = 64; + char buf[BUFSIZE]; + PxMemSet(buf, 0, bytesToPad < BUFSIZE ? PxU32(bytesToPad) : PxU32(BUFSIZE)); + while(bytesToPad > 0) + { + mMemStream.write(buf, bytesToPad < BUFSIZE ? PxU32(bytesToPad) : PxU32(BUFSIZE)); + bytesToPad -= BUFSIZE; + } + PX_ASSERT(!getPadding(getTotalStoredSize(), alignment)); + } + + virtual void writeName(const char*) + { + Ps::getFoundation().error(physx::PxErrorCode::eINVALID_OPERATION, __FILE__, __LINE__, + "Cannot export names during exportData."); + } + + const PxCollection& getCollection() const { return mCollection; } + + virtual void registerReference(PxBase& serializable, PxU32 kind, size_t reference); + + const Ps::Array<ImportReference>& getImportReferences() { return mImportReferences; } + InternalRefMap& getInternalReferencesPtrMap() { return mInternalReferencesPtrMap; } + InternalRefMap& getInternalReferencesIdxMap() { return mInternalReferencesIdxMap; } + + PxU32 getSize() const { return mMemStream.getSize(); } + PxU8* getData() const { return mMemStream.getData(); } + + + + private: + //import reference map for unique registration of import references and corresponding buffer. + Ps::HashMap<PxSerialObjectId, PxU32> mImportReferencesMap; + Ps::Array<ImportReference> mImportReferences; + + //maps for unique registration of internal references + InternalRefMap mInternalReferencesPtrMap; + InternalRefMap mInternalReferencesIdxMap; + + //map for quick lookup of manifest index. + Ps::HashMap<const PxBase*, PxU32> mObjToCollectionIndexMap; + + //collection and externalRefs collection for assigning references. + const Cm::Collection& mCollection; + const Cm::Collection* mExternalRefs; + + PxDefaultMemoryOutputStream mMemStream; + + }; + + } // namespace Sn +} + +#endif |