diff options
| author | git perforce import user <a@b> | 2016-10-25 12:29:14 -0600 |
|---|---|---|
| committer | Sheikh Dawood Abdul Ajees <Sheikh Dawood Abdul Ajees> | 2016-10-25 18:56:37 -0500 |
| commit | 3dfe2108cfab31ba3ee5527e217d0d8e99a51162 (patch) | |
| tree | fa6485c169e50d7415a651bf838f5bcd0fd3bfbd /APEX_1.4/NvParameterized/src/PlatformOutputStream.cpp | |
| download | physx-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 'APEX_1.4/NvParameterized/src/PlatformOutputStream.cpp')
| -rw-r--r-- | APEX_1.4/NvParameterized/src/PlatformOutputStream.cpp | 560 |
1 files changed, 560 insertions, 0 deletions
diff --git a/APEX_1.4/NvParameterized/src/PlatformOutputStream.cpp b/APEX_1.4/NvParameterized/src/PlatformOutputStream.cpp new file mode 100644 index 00000000..74ae68e6 --- /dev/null +++ b/APEX_1.4/NvParameterized/src/PlatformOutputStream.cpp @@ -0,0 +1,560 @@ +// 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-2013 NVIDIA Corporation. All rights reserved. + +// WARNING: before doing any changes to this file +// check comments at the head of BinSerializer.cpp + +#include "PlatformOutputStream.h" +#include <stdint.h> + +using namespace NvParameterized; + +#ifndef WITHOUT_APEX_SERIALIZATION + +Reloc::Reloc(RelocType type_, uint32_t ptrPos_, const PlatformOutputStream &parent) + : type(type_), + ptrPos(ptrPos_), + traits(parent.mTraits) +{ + ptrData = reinterpret_cast<PlatformOutputStream *>(traits->alloc(sizeof(PlatformOutputStream))); + PX_PLACEMENT_NEW(ptrData, PlatformOutputStream)(parent.mTargetParams, parent.mTraits, parent.dict); +} + +Reloc::Reloc(const Reloc &cinfo): type(cinfo.type), ptrPos(cinfo.ptrPos), traits(cinfo.traits) +{ + Reloc &info = (Reloc &)cinfo; + + //Take ownership of stream to avoid slow recursive copies (especially when reallocating array elements) + ptrData = info.ptrData; + info.ptrData = 0; +} + +Reloc::~Reloc() +{ + if( ptrData ) + { + ptrData->~PlatformOutputStream(); + traits->free(ptrData); + } +} + +PlatformOutputStream::PlatformOutputStream(const PlatformABI &targetParams, Traits *traits, Dictionary &dict_) + : PlatformStream(targetParams, traits), + data(traits), + mRelocs(Traits::Allocator(traits)), + mStrings(Traits::Allocator(traits)), + mMerges(Traits::Allocator(traits)), + dict(dict_), + mTotalAlign(1) +{} + +PlatformOutputStream::PlatformOutputStream(const PlatformOutputStream &s) + : PlatformStream(s), + data(s.data), + mRelocs(Traits::Allocator(s.mTraits)), + mStrings(Traits::Allocator(s.mTraits)), + mMerges(Traits::Allocator(s.mTraits)), + dict(s.dict), + mTotalAlign(1) +{ + mRelocs.reserve(s.mRelocs.size()); + for(uint32_t i = 0; i < s.mRelocs.size(); ++i) + mRelocs.pushBack(s.mRelocs[i]); + + mStrings.reserve(s.mStrings.size()); + for(uint32_t i = 0; i < s.mStrings.size(); ++i) + mStrings.pushBack(s.mStrings[i]); + + mMerges.reserve(s.mMerges.size()); + for(uint32_t i = 0; i < s.mMerges.size(); ++i) + mMerges.pushBack(s.mMerges[i]); +} + +#ifndef NDEBUG +void PlatformOutputStream::dump() const +{ + PlatformStream::dump(); + + dumpBytes(data, size()); + + fflush(stdout); + for(uint32_t i = 0; i < mRelocs.size(); ++i) + { + printf("Relocation %d at %x:\n", (int)i, mRelocs[i].ptrPos); + mRelocs[i].ptrData->dump(); + } + + fflush(stdout); +} +#endif + +void PlatformOutputStream::storeU32At(uint32_t x, uint32_t i) +{ + if( mCurParams.endian != mTargetParams.endian ) + SwapBytes(reinterpret_cast<char *>(&x), 4U, TYPE_U32); + + *reinterpret_cast<uint32_t *>(&data[i]) = x; +} + +uint32_t PlatformOutputStream::storeString(const char *s) +{ + uint32_t off = storeSimple((uint8_t)*s); + while( *s++ ) + storeSimple((uint8_t)*s); + + return off; +} + +uint32_t PlatformOutputStream::storeBytes(const char *s, uint32_t n) +{ + if( !n ) + return size(); + + uint32_t off = storeSimple((uint8_t)s[0]); + for(uint32_t i = 1; i < n; ++i) + storeSimple((uint8_t)s[i]); + + return off; +} + +uint32_t PlatformOutputStream::beginStruct(uint32_t align_, uint32_t pad_) +{ + uint32_t off = size(); + mStack.pushBack(Agregate(Agregate::STRUCT, pad_)); + align(align_); // Align _after_ we push struct to avoid ignored align() when inside array + return off; +} + +uint32_t PlatformOutputStream::beginStruct(uint32_t align_) +{ + return beginStruct(align_, align_); +} + +uint32_t PlatformOutputStream::beginStruct(const Definition *pd) +{ + return beginStruct(getTargetAlignment(pd), getTargetPadding(pd)); +} + +void PlatformOutputStream::closeStruct() +{ + PX_ASSERT(mStack.size() > 0); + + //Tail padding + align(mStack.back().align);// Align _before_ we pop struct to avoid ignored align() when inside array + mStack.popBack(); +} + +uint32_t PlatformOutputStream::beginString() +{ + return beginStruct(physx::PxMax(mTargetParams.aligns.pointer, mTargetParams.aligns.Bool)); +} + +void PlatformOutputStream::closeString() +{ + closeStruct(); +} + +uint32_t PlatformOutputStream::beginArray(const Definition *pd) +{ + return beginArray(getTargetAlignment(pd)); +} + +uint32_t PlatformOutputStream::beginArray(uint32_t align_) +{ + align(align_); // Align _before_ we push array because otherwise align() would be ignored + uint32_t off = size(); + mStack.pushBack(Agregate(Agregate::ARRAY, align_)); + return off; +} + +void PlatformOutputStream::closeArray() +{ + // No tail padding when in array + mStack.popBack(); +} + +void PlatformOutputStream::skipBytes(uint32_t nbytes) +{ + data.skipBytes(nbytes); +} + +void PlatformOutputStream::align(uint32_t border) +{ + bool isAligned; + uint32_t newSize = getAlign(size(), border, isAligned); + + if( isAligned ) + mTotalAlign = physx::PxMax(mTotalAlign, border); + + data.skipBytes(newSize - size()); +} + +void PlatformOutputStream::mergeDict() +{ + for(uint32_t i = 0; i < dict.size(); ++i) + { + const char *s = dict.get(i); + uint32_t off = storeString(s); + dict.setOffset(s, off); + } +} + +uint32_t PlatformOutputStream::storeNullPtr() +{ + //Do not align on uint32_t or uint64_t boundary (already aligned at pointer boundary) + align(mTargetParams.aligns.pointer); + uint32_t off = size(); + if( 4 == mTargetParams.sizes.pointer ) + data.skipBytes(4); + else + { + PX_ASSERT( 8 == mTargetParams.sizes.pointer ); + data.skipBytes(8); + } + return off; +} + +Reloc &PlatformOutputStream::storePtr(RelocType type, uint32_t align) +{ + uint32_t off = storeNullPtr(); + mRelocs.pushBack(Reloc(type, off, *this)); + mRelocs.back().ptrData->setAlignment(align); + return mRelocs.back(); +} + +Reloc &PlatformOutputStream::storePtr(RelocType type, const Definition *pd) +{ + return storePtr(type, getTargetAlignment(pd)); +} + +void PlatformOutputStream::storeStringPtr(const char *s) +{ + uint32_t off = storeNullPtr(); + if( s ) + { + mStrings.pushBack(StringReloc(off, s)); + dict.put(s); + } +} + +uint32_t PlatformOutputStream::storeSimpleStructArray(Handle &handle) +{ + int32_t n; + handle.getArraySize(n); + + const NvParameterized::Definition *pdStruct = handle.parameterDefinition()->child(0); + int32_t nfields = pdStruct->numChildren(); + + uint32_t align_ = getTargetAlignment(pdStruct), + size_ = getTargetSize(pdStruct), + pad_ = getTargetPadding(pdStruct); + + align(align_); + uint32_t off = size(); + + data.reserve(size() + n * physx::PxMax(align_, size_)); + + char *p = data; + p += data.size(); + + for(int32_t i = 0; i < n; ++i) + { + beginStruct(align_, pad_); + handle.set(i); + + for(int32_t j = 0; j < nfields; ++j) + { + handle.set(j); + + const Definition *pdField = pdStruct->child(j); + + if( pdField->alignment() ) + align( pdField->alignment() ); + + if( pdField->hint("DONOTSERIALIZE") ) + { + //Simply skip bytes + align(getTargetAlignment(pdField)); + skipBytes(getTargetSize(pdField)); + } + else + { + //No need to align structs because of tail padding + switch( pdField->type() ) + { +# define NV_PARAMETERIZED_TYPES_NO_LEGACY_TYPES +# define NV_PARAMETERIZED_TYPES_ONLY_SIMPLE_TYPES +# define NV_PARAMETERIZED_TYPES_NO_STRING_TYPES +# define NV_PARAMETERIZED_TYPE(type_name, enum_name, c_type) \ + case TYPE_##enum_name: \ + { \ + c_type val; \ + handle.getParam##type_name(val); \ + storeSimple<c_type>(val); \ + break; \ + } +# include "nvparameterized/NvParameterized_types.h" + + case TYPE_MAT34: + { + float val[12]; + handle.getParamMat34Legacy(val); + storeSimple(val, 12); + break; + } + + NV_PARAMETRIZED_NO_MATH_DATATYPE_LABELS + default: + DEBUG_ASSERT( 0 && "Unexpected type" ); + return UINT32_MAX; + } + } + + handle.popIndex(); + } //j + + handle.popIndex(); + closeStruct(); + } //i + + return off; +} + +uint32_t PlatformOutputStream::storeObjHeader(const NvParameterized::Interface &obj, bool isIncluded) +{ + uint32_t align_ = NvMax3(mTargetParams.aligns.Bool, mTargetParams.aligns.i32, mTargetParams.aligns.pointer); + + uint32_t off = beginStruct(align_); + + uint32_t hdrOff = data.size(); + PX_ASSERT( hdrOff % sizeof(uint32_t) == 0 ); + + storeSimple(uint32_t(0)); //Data offset + + //className + storeStringPtr(obj.className()); + + //name + storeStringPtr(obj.name()); + + //isIncluded + storeSimple(isIncluded); + + //version + storeSimple<uint32_t>(obj.version()); + + //checksum size + uint32_t bits = (uint32_t)-1; + const uint32_t *checksum = obj.checksum(bits); + PX_ASSERT( bits % 32 == 0 ); //32 bits in uint32_t + uint32_t i32s = bits / 32; + storeSimple(i32s); + + //checksum pointer + Reloc &reloc = storePtr(RELOC_ABS_RAW, mTargetParams.aligns.i32); + for(uint32_t i = 0; i < i32s; ++i) + reloc.ptrData->storeSimple(checksum[i]); + + closeStruct(); + + //We force alignment to calculate dataOffset + //(when object is inserted no additional padding will be inserted) + + const Definition *pd = obj.rootParameterDefinition(); + uint32_t customAlign = pd ? getTargetAlignment(pd) : 1; + align(physx::PxMax(16U, customAlign)); //16 for safety + + storeU32At(data.size() - hdrOff, hdrOff); //Now we know object data offset + + return off; +} + +uint32_t PlatformOutputStream::beginObject(const NvParameterized::Interface &obj, bool /*isRoot*/, const Definition *pd) +{ + //NvParameterized objects is derived from NvParameters so we need to store its fields as well. + + //WARN: this implementation _heavily_ depends on implementation of NvParameters + + //Alignment of NvParameters + uint32_t parentAlign = physx::PxMax(mTargetParams.aligns.pointer, mTargetParams.aligns.Bool), + childAlign = pd ? getTargetAlignment(pd) : 1, + totalAlign = physx::PxMax(parentAlign, childAlign); + + uint32_t off = beginStruct(totalAlign); + + //NvParameters fields + for(uint32_t i = 0; i < 6; storeNullPtr(), ++i); //vtable and other fields + storeStringPtr(obj.name()); //mName + storeStringPtr(obj.className()); //mClassName + storeSimple(true); //mDoDeallocateSelf (all objects are responsible for memory deallocation) + storeSimple(false); //mDoDeallocateName + storeSimple(false); //mDoDeallocateClassName + + //Some general theory of alignment handling + //Imagine that we have class: + //class A: A1, A2, ... An + //{ + // T1 f1; + // T2 f2; + //}; + //Then all Ai/fi are aligned on natural boundary. Whether or not padding bytes for Ai are inserted + //and whether or not Ai+1 or fi may reuse those bytes depends on compiler; + //we store this info in PlatformABI's doReusePadding flag. + //doReusePadding == false means that padding bytes are always there. + //doReusePadding == true means that padding bytes are _not_ inserted for non-POD Ai but are inserted for POD Ai. + //(I have yet to see compiler that does not insert padding bytes for POD base class!). + + //Compilers may handle derived classes in two different ways. + //Say we have + // class B {int x; char y; }; + // class A: public B {char z; }; + //Then in pure C code this may look like either as + // struct A { struct { int x; char y; } b; char z; }; + //or as + // struct A { int x; char y; char z; }; + //(the latter is usual if B is not POD). + //Take care of that here (NvParameters is not POD!). + if( !mTargetParams.doReuseParentPadding ) + align(parentAlign); //Insert tail padding for NvParameters + + //ParametersStruct is aligned on natural boundary + align(childAlign); + + return off; +} + +uint32_t PlatformOutputStream::merge(const PlatformOutputStream &mergee) +{ + //All structs should be closed + PX_ASSERT( !mergee.mStack.size() ); + + align(mergee.alignment()); + + uint32_t base = data.size(); + + data.appendBytes(mergee.data, mergee.data.size()); + + //Update relocations + + mRelocs.reserve(mRelocs.size() + mergee.mRelocs.size()); + for(uint32_t i = 0; i < mergee.mRelocs.size(); ++i) + { + mRelocs.pushBack(mergee.mRelocs[i]); + mRelocs.back().ptrPos += base; + } + + mStrings.reserve(mStrings.size() + mergee.mStrings.size()); + for(uint32_t i = 0; i < mergee.mStrings.size(); ++i) + { + mStrings.pushBack(mergee.mStrings[i]); + mStrings.back().ptrPos += base; + } + + mMerges.reserve(mMerges.size() + mergee.mMerges.size()); + for(uint32_t i = 0; i < mergee.mMerges.size(); ++i) + { + mMerges.pushBack(mergee.mMerges[i]); + + mMerges.back().ptrPos += base; + if( !mergee.mMerges[i].isExtern ) + mMerges.back().targetPos += base; + } + + return base; +} + +void PlatformOutputStream::flatten() +{ + //It's very important that data for child objects is stored + //after current object to allow safe initialization + + //Generic pointers + for(uint32_t i = 0; i < mRelocs.size(); ++i) + { + Reloc &reloc = mRelocs[i]; + + //Recursively add data which is pointed-to + + align( reloc.ptrData->alignment() ); + + MergedReloc m = { reloc.ptrPos, data.size(), reloc.type, false }; + mMerges.pushBack(m); + + merge(*reloc.ptrData); //Internal pointers are recursively added here + } + + //String pointers + for(uint32_t i = 0; i < mStrings.size(); ++i) + { + //String pointers are external and absolute + MergedReloc m = { mStrings[i].ptrPos, dict.getOffset(mStrings[i].s), RELOC_ABS_RAW, true }; + mMerges.pushBack(m); + } + + mRelocs.clear(); + mStrings.clear(); +} + +uint32_t PlatformOutputStream::writeRelocs() +{ + uint32_t ptrOff = storeSimple<uint32_t>(mMerges.size()); //Offset of relocation table + + data.reserve(mMerges.size() * 2 * physx::PxMax(4U, mTargetParams.aligns.i32)); + + for(uint32_t i = 0; i < mMerges.size(); ++i) + { + char *ptr = &data[mMerges[i].ptrPos]; + if( 4 == mTargetParams.sizes.pointer ) + { + uint32_t *ptrAsInt = reinterpret_cast<uint32_t *>(ptr); + *ptrAsInt = mMerges[i].targetPos; + if( mTargetParams.endian != mCurParams.endian ) + SwapBytes(ptr, 4U, TYPE_U32); + } + else + { + PX_ASSERT(8 == mTargetParams.sizes.pointer); + + uint64_t *ptrAsInt = reinterpret_cast<uint64_t *>(ptr); + *ptrAsInt = mMerges[i].targetPos; + if( mTargetParams.endian != mCurParams.endian ) + SwapBytes(ptr, 8U, TYPE_U64); + } + + //BinaryReloc struct + beginStruct(mTargetParams.aligns.i32); + storeSimple<uint32_t>(static_cast<uint32_t>(mMerges[i].type)); + storeSimple<uint32_t>(mMerges[i].ptrPos); + closeStruct(); + } + + mMerges.clear(); + + return ptrOff; +} + +#endif |