aboutsummaryrefslogtreecommitdiff
path: root/PhysX_3.4/Source/PhysXExtensions/src/serialization/Binary/SnBinaryDeserialization.cpp
diff options
context:
space:
mode:
authorgit perforce import user <a@b>2016-10-25 12:29:14 -0600
committerSheikh Dawood Abdul Ajees <Sheikh Dawood Abdul Ajees>2016-10-25 18:56:37 -0500
commit3dfe2108cfab31ba3ee5527e217d0d8e99a51162 (patch)
treefa6485c169e50d7415a651bf838f5bcd0fd3bfbd /PhysX_3.4/Source/PhysXExtensions/src/serialization/Binary/SnBinaryDeserialization.cpp
downloadphysx-3.4-3dfe2108cfab31ba3ee5527e217d0d8e99a51162.tar.xz
physx-3.4-3dfe2108cfab31ba3ee5527e217d0d8e99a51162.zip
Initial commit:
PhysX 3.4.0 Update @ 21294896 APEX 1.4.0 Update @ 21275617 [CL 21300167]
Diffstat (limited to 'PhysX_3.4/Source/PhysXExtensions/src/serialization/Binary/SnBinaryDeserialization.cpp')
-rw-r--r--PhysX_3.4/Source/PhysXExtensions/src/serialization/Binary/SnBinaryDeserialization.cpp305
1 files changed, 305 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;
+}