1504 lines
48 KiB
C++
1504 lines
48 KiB
C++
//
|
|
// Redistribution and use in source and binary forms, with or without
|
|
// modification, are permitted provided that the following conditions
|
|
// are met:
|
|
// * Redistributions of source code must retain the above copyright
|
|
// notice, this list of conditions and the following disclaimer.
|
|
// * Redistributions in binary form must reproduce the above copyright
|
|
// notice, this list of conditions and the following disclaimer in the
|
|
// documentation and/or other materials provided with the distribution.
|
|
// * Neither the name of NVIDIA CORPORATION nor the names of its
|
|
// contributors may be used to endorse or promote products derived
|
|
// from this software without specific prior written permission.
|
|
//
|
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
|
|
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
|
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
|
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
|
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
|
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
|
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
|
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
//
|
|
// Copyright (c) 2008-2021 NVIDIA Corporation. All rights reserved.
|
|
|
|
#include "PxPvdObjectModelInternalTypes.h"
|
|
#include "PxPvdObjectModelMetaData.h"
|
|
#include "PxPvdInternalByteStreams.h"
|
|
#include "PxPvdMarshalling.h"
|
|
|
|
using namespace physx;
|
|
using namespace pvdsdk;
|
|
using namespace shdfnd;
|
|
|
|
namespace
|
|
{
|
|
|
|
struct PropDescImpl : public PropertyDescription, public UserAllocated
|
|
{
|
|
Array<NamedValue> mValueNames;
|
|
PropDescImpl(const PropertyDescription& inBase, StringTable& table)
|
|
: PropertyDescription(inBase), mValueNames("NamedValue")
|
|
{
|
|
mName = table.registerStr(mName);
|
|
}
|
|
PropDescImpl() : mValueNames("NamedValue")
|
|
{
|
|
}
|
|
|
|
template <typename TSerializer>
|
|
void serialize(TSerializer& serializer)
|
|
{
|
|
serializer.streamify(mOwnerClassName);
|
|
serializer.streamify(mOwnerClassId);
|
|
serializer.streamify(mSemantic);
|
|
serializer.streamify(mDatatype);
|
|
serializer.streamify(mDatatypeName);
|
|
serializer.streamify(mPropertyType);
|
|
serializer.streamify(mPropertyId);
|
|
serializer.streamify(m32BitOffset);
|
|
serializer.streamify(m64BitOffset);
|
|
serializer.streamify(mValueNames);
|
|
serializer.streamify(mName);
|
|
}
|
|
};
|
|
|
|
struct ClassDescImpl : public ClassDescription, public UserAllocated
|
|
{
|
|
Array<PropDescImpl*> mPropImps;
|
|
Array<PtrOffset> m32OffsetArray;
|
|
Array<PtrOffset> m64OffsetArray;
|
|
ClassDescImpl(const ClassDescription& inBase)
|
|
: ClassDescription(inBase)
|
|
, mPropImps("PropDescImpl*")
|
|
, m32OffsetArray("ClassDescImpl::m32OffsetArray")
|
|
, m64OffsetArray("ClassDescImpl::m64OffsetArray")
|
|
{
|
|
PVD_FOREACH(idx, get32BitSizeInfo().mPtrOffsets.size())
|
|
m32OffsetArray.pushBack(get32BitSizeInfo().mPtrOffsets[idx]);
|
|
PVD_FOREACH(idx, get64BitSizeInfo().mPtrOffsets.size())
|
|
m64OffsetArray.pushBack(get64BitSizeInfo().mPtrOffsets[idx]);
|
|
}
|
|
ClassDescImpl()
|
|
: mPropImps("PropDescImpl*")
|
|
, m32OffsetArray("ClassDescImpl::m32OffsetArray")
|
|
, m64OffsetArray("ClassDescImpl::m64OffsetArray")
|
|
{
|
|
}
|
|
PropDescImpl* findProperty(String name)
|
|
{
|
|
PVD_FOREACH(idx, mPropImps.size())
|
|
{
|
|
if(safeStrEq(mPropImps[idx]->mName, name))
|
|
return mPropImps[idx];
|
|
}
|
|
return NULL;
|
|
}
|
|
void addProperty(PropDescImpl* prop)
|
|
{
|
|
mPropImps.pushBack(prop);
|
|
}
|
|
|
|
void addPtrOffset(PtrOffsetType::Enum type, uint32_t offset32, uint32_t offset64)
|
|
{
|
|
m32OffsetArray.pushBack(PtrOffset(type, offset32));
|
|
m64OffsetArray.pushBack(PtrOffset(type, offset64));
|
|
get32BitSizeInfo().mPtrOffsets = DataRef<PtrOffset>(m32OffsetArray.begin(), m32OffsetArray.end());
|
|
get64BitSizeInfo().mPtrOffsets = DataRef<PtrOffset>(m64OffsetArray.begin(), m64OffsetArray.end());
|
|
}
|
|
|
|
template <typename TSerializer>
|
|
void serialize(TSerializer& serializer)
|
|
{
|
|
serializer.streamify(mName);
|
|
serializer.streamify(mClassId);
|
|
serializer.streamify(mBaseClass);
|
|
serializer.streamify(mPackedUniformWidth);
|
|
serializer.streamify(mPackedClassType);
|
|
serializer.streamify(mLocked);
|
|
serializer.streamify(mRequiresDestruction);
|
|
serializer.streamify(get32BitSize());
|
|
serializer.streamify(get32BitSizeInfo().mDataByteSize);
|
|
serializer.streamify(get32BitSizeInfo().mAlignment);
|
|
serializer.streamify(get64BitSize());
|
|
serializer.streamify(get64BitSizeInfo().mDataByteSize);
|
|
serializer.streamify(get64BitSizeInfo().mAlignment);
|
|
serializer.streamifyLinks(mPropImps);
|
|
serializer.streamify(m32OffsetArray);
|
|
serializer.streamify(m64OffsetArray);
|
|
get32BitSizeInfo().mPtrOffsets = DataRef<PtrOffset>(m32OffsetArray.begin(), m32OffsetArray.end());
|
|
get64BitSizeInfo().mPtrOffsets = DataRef<PtrOffset>(m64OffsetArray.begin(), m64OffsetArray.end());
|
|
}
|
|
};
|
|
|
|
class StringTableImpl : public StringTable, public UserAllocated
|
|
{
|
|
HashMap<const char*, char*> mStrings;
|
|
uint32_t mNextStrHandle;
|
|
HashMap<uint32_t, char*> mHandleToStr;
|
|
HashMap<const char*, uint32_t> mStrToHandle;
|
|
|
|
public:
|
|
StringTableImpl()
|
|
: mStrings("StringTableImpl::mStrings")
|
|
, mNextStrHandle(1)
|
|
, mHandleToStr("StringTableImpl::mHandleToStr")
|
|
, mStrToHandle("StringTableImpl::mStrToHandle")
|
|
{
|
|
}
|
|
uint32_t nextHandleValue()
|
|
{
|
|
return mNextStrHandle++;
|
|
}
|
|
virtual ~StringTableImpl()
|
|
{
|
|
for(HashMap<const char*, char*>::Iterator iter = mStrings.getIterator(); !iter.done(); ++iter)
|
|
PX_FREE(iter->second);
|
|
mStrings.clear();
|
|
}
|
|
virtual uint32_t getNbStrs()
|
|
{
|
|
return mStrings.size();
|
|
}
|
|
virtual uint32_t getStrs(const char** outStrs, uint32_t bufLen, uint32_t startIdx = 0)
|
|
{
|
|
startIdx = PxMin(getNbStrs(), startIdx);
|
|
uint32_t numStrs(PxMin(getNbStrs() - startIdx, bufLen));
|
|
HashMap<const char*, char*>::Iterator iter(mStrings.getIterator());
|
|
for(uint32_t idx = 0; idx < startIdx; ++idx, ++iter)
|
|
;
|
|
for(uint32_t idx = 0; idx < numStrs && !iter.done(); ++idx, ++iter)
|
|
outStrs[idx] = iter->second;
|
|
return numStrs;
|
|
}
|
|
void addStringHandle(char* str, uint32_t hdl)
|
|
{
|
|
mHandleToStr.insert(hdl, str);
|
|
mStrToHandle.insert(str, hdl);
|
|
}
|
|
|
|
uint32_t addStringHandle(char* str)
|
|
{
|
|
uint32_t theNewHandle = nextHandleValue();
|
|
addStringHandle(str, theNewHandle);
|
|
return theNewHandle;
|
|
}
|
|
const char* doRegisterStr(const char* str, bool& outAdded)
|
|
{
|
|
PX_ASSERT(isMeaningful(str));
|
|
const HashMap<const char*, char*>::Entry* entry(mStrings.find(str));
|
|
if(entry == NULL)
|
|
{
|
|
outAdded = true;
|
|
char* retval(copyStr(str));
|
|
mStrings.insert(retval, retval);
|
|
return retval;
|
|
}
|
|
return entry->second;
|
|
}
|
|
virtual const char* registerStr(const char* str, bool& outAdded)
|
|
{
|
|
outAdded = false;
|
|
if(isMeaningful(str) == false)
|
|
return "";
|
|
const char* retval = doRegisterStr(str, outAdded);
|
|
if(outAdded)
|
|
addStringHandle(const_cast<char*>(retval));
|
|
return retval;
|
|
}
|
|
|
|
NamespacedName registerName(const NamespacedName& nm)
|
|
{
|
|
return NamespacedName(registerStr(nm.mNamespace), registerStr(nm.mName));
|
|
}
|
|
const char* registerStr(const char* str)
|
|
{
|
|
bool ignored;
|
|
return registerStr(str, ignored);
|
|
}
|
|
|
|
virtual StringHandle strToHandle(const char* str)
|
|
{
|
|
if(isMeaningful(str) == false)
|
|
return 0;
|
|
const HashMap<const char*, uint32_t>::Entry* entry(mStrToHandle.find(str));
|
|
if(entry)
|
|
return entry->second;
|
|
bool added = false;
|
|
const char* registeredStr = doRegisterStr(str, added);
|
|
uint32_t theNewHandle = addStringHandle(const_cast<char*>(registeredStr));
|
|
PX_ASSERT(mStrToHandle.find(str));
|
|
PX_ASSERT(added);
|
|
return theNewHandle;
|
|
}
|
|
|
|
virtual const char* handleToStr(uint32_t hdl)
|
|
{
|
|
if(hdl == 0)
|
|
return "";
|
|
const HashMap<uint32_t, char*>::Entry* entry(mHandleToStr.find(hdl));
|
|
if(entry)
|
|
return entry->second;
|
|
// unregistered handle...
|
|
return "";
|
|
}
|
|
|
|
void write(PvdOutputStream& stream)
|
|
{
|
|
uint32_t numStrs = static_cast<uint32_t>(mHandleToStr.size());
|
|
stream << numStrs;
|
|
stream << mNextStrHandle;
|
|
for(HashMap<uint32_t, char*>::Iterator iter = mHandleToStr.getIterator(); !iter.done(); ++iter)
|
|
{
|
|
stream << iter->first;
|
|
uint32_t len = static_cast<uint32_t>(strlen(iter->second) + 1);
|
|
stream << len;
|
|
stream.write(reinterpret_cast<uint8_t*>(iter->second), len);
|
|
}
|
|
}
|
|
|
|
template <typename TReader>
|
|
void read(TReader& stream)
|
|
{
|
|
mHandleToStr.clear();
|
|
mStrToHandle.clear();
|
|
uint32_t numStrs;
|
|
stream >> numStrs;
|
|
stream >> mNextStrHandle;
|
|
Array<uint8_t> readBuffer("StringTable::read::readBuffer");
|
|
uint32_t bufSize = 0;
|
|
for(uint32_t idx = 0; idx < numStrs; ++idx)
|
|
{
|
|
uint32_t handleValue;
|
|
uint32_t bufLen;
|
|
stream >> handleValue;
|
|
stream >> bufLen;
|
|
if(bufSize < bufLen)
|
|
readBuffer.resize(bufLen);
|
|
bufSize = PxMax(bufSize, bufLen);
|
|
stream.read(readBuffer.begin(), bufLen);
|
|
bool ignored;
|
|
const char* newStr = doRegisterStr(reinterpret_cast<const char*>(readBuffer.begin()), ignored);
|
|
addStringHandle(const_cast<char*>(newStr), handleValue);
|
|
}
|
|
}
|
|
|
|
virtual void release()
|
|
{
|
|
PVD_DELETE(this);
|
|
}
|
|
|
|
private:
|
|
StringTableImpl& operator=(const StringTableImpl&);
|
|
};
|
|
|
|
struct NamespacedNameHasher
|
|
{
|
|
uint32_t operator()(const NamespacedName& nm)
|
|
{
|
|
return Hash<const char*>()(nm.mNamespace) ^ Hash<const char*>()(nm.mName);
|
|
}
|
|
bool equal(const NamespacedName& lhs, const NamespacedName& rhs)
|
|
{
|
|
return safeStrEq(lhs.mNamespace, rhs.mNamespace) && safeStrEq(lhs.mName, rhs.mName);
|
|
}
|
|
};
|
|
|
|
struct ClassPropertyName
|
|
{
|
|
NamespacedName mName;
|
|
String mPropName;
|
|
ClassPropertyName(const NamespacedName& name = NamespacedName(), String propName = "")
|
|
: mName(name), mPropName(propName)
|
|
{
|
|
}
|
|
};
|
|
|
|
struct ClassPropertyNameHasher
|
|
{
|
|
uint32_t operator()(const ClassPropertyName& nm)
|
|
{
|
|
return NamespacedNameHasher()(nm.mName) ^ Hash<const char*>()(nm.mPropName);
|
|
}
|
|
bool equal(const ClassPropertyName& lhs, const ClassPropertyName& rhs)
|
|
{
|
|
return NamespacedNameHasher().equal(lhs.mName, rhs.mName) && safeStrEq(lhs.mPropName, rhs.mPropName);
|
|
}
|
|
};
|
|
|
|
struct PropertyMessageEntryImpl : public PropertyMessageEntry
|
|
{
|
|
PropertyMessageEntryImpl(const PropertyMessageEntry& data) : PropertyMessageEntry(data)
|
|
{
|
|
}
|
|
PropertyMessageEntryImpl()
|
|
{
|
|
}
|
|
template <typename TSerializerType>
|
|
void serialize(TSerializerType& serializer)
|
|
{
|
|
serializer.streamify(mDatatypeName);
|
|
serializer.streamify(mDatatypeId);
|
|
serializer.streamify(mMessageOffset);
|
|
serializer.streamify(mByteSize);
|
|
serializer.streamify(mDestByteSize);
|
|
serializer.streamify(mProperty);
|
|
}
|
|
};
|
|
|
|
struct PropertyMessageDescriptionImpl : public PropertyMessageDescription, public UserAllocated
|
|
{
|
|
Array<PropertyMessageEntryImpl> mEntryImpls;
|
|
Array<PropertyMessageEntry> mEntries;
|
|
Array<uint32_t> mStringOffsetArray;
|
|
PropertyMessageDescriptionImpl(const PropertyMessageDescription& data)
|
|
: PropertyMessageDescription(data)
|
|
, mEntryImpls("PropertyMessageDescriptionImpl::mEntryImpls")
|
|
, mEntries("PropertyMessageDescriptionImpl::mEntries")
|
|
, mStringOffsetArray("PropertyMessageDescriptionImpl::mStringOffsets")
|
|
{
|
|
}
|
|
PropertyMessageDescriptionImpl()
|
|
: mEntryImpls("PropertyMessageDescriptionImpl::mEntryImpls")
|
|
, mEntries("PropertyMessageDescriptionImpl::mEntries")
|
|
, mStringOffsetArray("PropertyMessageDescriptionImpl::mStringOffsets")
|
|
{
|
|
}
|
|
|
|
~PropertyMessageDescriptionImpl()
|
|
{
|
|
}
|
|
|
|
void addEntry(const PropertyMessageEntryImpl& entry)
|
|
{
|
|
mEntryImpls.pushBack(entry);
|
|
mEntries.pushBack(entry);
|
|
mProperties = DataRef<PropertyMessageEntry>(mEntries.begin(), mEntries.end());
|
|
}
|
|
|
|
template <typename TSerializerType>
|
|
void serialize(TSerializerType& serializer)
|
|
{
|
|
serializer.streamify(mClassName);
|
|
serializer.streamify(mClassId); // No other class has this id, it is DB-unique
|
|
serializer.streamify(mMessageName);
|
|
serializer.streamify(mMessageId);
|
|
serializer.streamify(mMessageByteSize);
|
|
serializer.streamify(mEntryImpls);
|
|
serializer.streamify(mStringOffsetArray);
|
|
if(mEntries.size() != mEntryImpls.size())
|
|
{
|
|
mEntries.clear();
|
|
uint32_t numEntries = static_cast<uint32_t>(mEntryImpls.size());
|
|
for(uint32_t idx = 0; idx < numEntries; ++idx)
|
|
mEntries.pushBack(mEntryImpls[idx]);
|
|
}
|
|
mProperties = DataRef<PropertyMessageEntry>(mEntries.begin(), mEntries.end());
|
|
mStringOffsets = DataRef<uint32_t>(mStringOffsetArray.begin(), mStringOffsetArray.end());
|
|
}
|
|
|
|
private:
|
|
PropertyMessageDescriptionImpl& operator=(const PropertyMessageDescriptionImpl&);
|
|
};
|
|
|
|
struct PvdObjectModelMetaDataImpl : public PvdObjectModelMetaData, public UserAllocated
|
|
{
|
|
typedef HashMap<NamespacedName, ClassDescImpl*, NamespacedNameHasher> TNameToClassMap;
|
|
typedef HashMap<ClassPropertyName, PropDescImpl*, ClassPropertyNameHasher> TNameToPropMap;
|
|
typedef HashMap<NamespacedName, PropertyMessageDescriptionImpl*, NamespacedNameHasher> TNameToPropertyMessageMap;
|
|
|
|
TNameToClassMap mNameToClasses;
|
|
TNameToPropMap mNameToProperties;
|
|
Array<ClassDescImpl*> mClasses;
|
|
Array<PropDescImpl*> mProperties;
|
|
StringTableImpl* mStringTable;
|
|
TNameToPropertyMessageMap mPropertyMessageMap;
|
|
Array<PropertyMessageDescriptionImpl*> mPropertyMessages;
|
|
int32_t mNextClassId;
|
|
uint32_t mRefCount;
|
|
|
|
PvdObjectModelMetaDataImpl()
|
|
: mNameToClasses("NamespacedName->ClassDescImpl*")
|
|
, mNameToProperties("ClassPropertyName->PropDescImpl*")
|
|
, mClasses("ClassDescImpl*")
|
|
, mProperties("PropDescImpl*")
|
|
, mStringTable(PVD_NEW(StringTableImpl)())
|
|
, mPropertyMessageMap("PropertyMessageMap")
|
|
, mPropertyMessages("PvdObjectModelMetaDataImpl::mPropertyMessages")
|
|
, mNextClassId(1)
|
|
, mRefCount(0)
|
|
{
|
|
}
|
|
|
|
private:
|
|
PvdObjectModelMetaDataImpl& operator=(const PvdObjectModelMetaDataImpl&);
|
|
|
|
public:
|
|
int32_t nextClassId()
|
|
{
|
|
return mNextClassId++;
|
|
}
|
|
void initialize()
|
|
{
|
|
// Create the default classes.
|
|
{
|
|
ClassDescImpl& aryData = getOrCreateClassImpl(getPvdNamespacedNameForType<ArrayData>(),
|
|
DataTypeToPvdTypeMap<ArrayData>::BaseTypeEnum);
|
|
aryData.get32BitSize() = sizeof(ArrayData);
|
|
aryData.get32BitSizeInfo().mAlignment = sizeof(void*);
|
|
aryData.get64BitSize() = sizeof(ArrayData);
|
|
aryData.get64BitSizeInfo().mAlignment = sizeof(void*);
|
|
aryData.mLocked = true;
|
|
}
|
|
#define CREATE_BASIC_PVD_CLASS(type) \
|
|
{ \
|
|
ClassDescImpl& cls = getOrCreateClassImpl(getPvdNamespacedNameForType<type>(), getPvdTypeForType<type>()); \
|
|
cls.get32BitSize() = sizeof(type); \
|
|
cls.get32BitSizeInfo().mAlignment = sizeof(type); \
|
|
cls.get64BitSize() = sizeof(type); \
|
|
cls.get64BitSizeInfo().mAlignment = sizeof(type); \
|
|
cls.mLocked = true; \
|
|
cls.mPackedUniformWidth = sizeof(type); \
|
|
cls.mPackedClassType = getPvdTypeForType<type>(); \
|
|
}
|
|
CREATE_BASIC_PVD_CLASS(int8_t)
|
|
CREATE_BASIC_PVD_CLASS(uint8_t)
|
|
CREATE_BASIC_PVD_CLASS(bool)
|
|
CREATE_BASIC_PVD_CLASS(int16_t)
|
|
CREATE_BASIC_PVD_CLASS(uint16_t)
|
|
CREATE_BASIC_PVD_CLASS(int32_t)
|
|
CREATE_BASIC_PVD_CLASS(uint32_t)
|
|
// CREATE_BASIC_PVD_CLASS(uint32_t)
|
|
CREATE_BASIC_PVD_CLASS(int64_t)
|
|
CREATE_BASIC_PVD_CLASS(uint64_t)
|
|
CREATE_BASIC_PVD_CLASS(float)
|
|
CREATE_BASIC_PVD_CLASS(double)
|
|
#undef CREATE_BASIC_PVD_CLASS
|
|
|
|
#define CREATE_PTR_TYPE_PVD_CLASS(type, ptrType) \
|
|
{ \
|
|
ClassDescImpl& cls = getOrCreateClassImpl(getPvdNamespacedNameForType<type>(), getPvdTypeForType<type>()); \
|
|
cls.get32BitSize() = 4; \
|
|
cls.get32BitSizeInfo().mAlignment = 4; \
|
|
cls.get64BitSize() = 8; \
|
|
cls.get64BitSizeInfo().mAlignment = 8; \
|
|
cls.mLocked = true; \
|
|
cls.addPtrOffset(PtrOffsetType::ptrType, 0, 0); \
|
|
}
|
|
|
|
CREATE_PTR_TYPE_PVD_CLASS(String, StringOffset)
|
|
CREATE_PTR_TYPE_PVD_CLASS(VoidPtr, VoidPtrOffset)
|
|
CREATE_PTR_TYPE_PVD_CLASS(StringHandle, StringOffset)
|
|
CREATE_PTR_TYPE_PVD_CLASS(ObjectRef, VoidPtrOffset)
|
|
|
|
#undef CREATE_64BIT_ADJUST_PVD_CLASS
|
|
|
|
int32_t fltClassType = getPvdTypeForType<float>();
|
|
int32_t u32ClassType = getPvdTypeForType<uint32_t>();
|
|
int32_t v3ClassType = getPvdTypeForType<PxVec3>();
|
|
int32_t v4ClassType = getPvdTypeForType<PxVec4>();
|
|
int32_t qtClassType = getPvdTypeForType<PxQuat>();
|
|
{
|
|
ClassDescImpl& cls =
|
|
getOrCreateClassImpl(getPvdNamespacedNameForType<PvdColor>(), getPvdTypeForType<PvdColor>());
|
|
createProperty(cls.mClassId, "r", "", getPvdTypeForType<uint8_t>(), PropertyType::Scalar);
|
|
createProperty(cls.mClassId, "g", "", getPvdTypeForType<uint8_t>(), PropertyType::Scalar);
|
|
createProperty(cls.mClassId, "b", "", getPvdTypeForType<uint8_t>(), PropertyType::Scalar);
|
|
createProperty(cls.mClassId, "a", "", getPvdTypeForType<uint8_t>(), PropertyType::Scalar);
|
|
PX_ASSERT(cls.get32BitSizeInfo().mAlignment == 1);
|
|
PX_ASSERT(cls.get32BitSize() == 4);
|
|
PX_ASSERT(cls.get64BitSizeInfo().mAlignment == 1);
|
|
PX_ASSERT(cls.get64BitSize() == 4);
|
|
PX_ASSERT(cls.mPackedUniformWidth == 1);
|
|
PX_ASSERT(cls.mPackedClassType == getPvdTypeForType<uint8_t>());
|
|
cls.mLocked = true;
|
|
}
|
|
|
|
{
|
|
ClassDescImpl& cls = getOrCreateClassImpl(getPvdNamespacedNameForType<PxVec2>(), getPvdTypeForType<PxVec2>());
|
|
createProperty(cls.mClassId, "x", "", fltClassType, PropertyType::Scalar);
|
|
createProperty(cls.mClassId, "y", "", fltClassType, PropertyType::Scalar);
|
|
PX_ASSERT(cls.get32BitSizeInfo().mAlignment == 4);
|
|
PX_ASSERT(cls.get32BitSize() == 8);
|
|
PX_ASSERT(cls.get64BitSizeInfo().mAlignment == 4);
|
|
PX_ASSERT(cls.get64BitSize() == 8);
|
|
PX_ASSERT(cls.mPackedUniformWidth == 4);
|
|
PX_ASSERT(cls.mPackedClassType == fltClassType);
|
|
cls.mLocked = true;
|
|
}
|
|
{
|
|
ClassDescImpl& cls = getOrCreateClassImpl(getPvdNamespacedNameForType<PxVec3>(), getPvdTypeForType<PxVec3>());
|
|
createProperty(cls.mClassId, "x", "", fltClassType, PropertyType::Scalar);
|
|
createProperty(cls.mClassId, "y", "", fltClassType, PropertyType::Scalar);
|
|
createProperty(cls.mClassId, "z", "", fltClassType, PropertyType::Scalar);
|
|
PX_ASSERT(cls.get32BitSizeInfo().mAlignment == 4);
|
|
PX_ASSERT(cls.get32BitSize() == 12);
|
|
PX_ASSERT(cls.get64BitSizeInfo().mAlignment == 4);
|
|
PX_ASSERT(cls.get64BitSize() == 12);
|
|
PX_ASSERT(cls.mPackedUniformWidth == 4);
|
|
PX_ASSERT(cls.mPackedClassType == fltClassType);
|
|
cls.mLocked = true;
|
|
}
|
|
{
|
|
ClassDescImpl& cls = getOrCreateClassImpl(getPvdNamespacedNameForType<PxVec4>(), getPvdTypeForType<PxVec4>());
|
|
createProperty(cls.mClassId, "x", "", fltClassType, PropertyType::Scalar);
|
|
createProperty(cls.mClassId, "y", "", fltClassType, PropertyType::Scalar);
|
|
createProperty(cls.mClassId, "z", "", fltClassType, PropertyType::Scalar);
|
|
createProperty(cls.mClassId, "w", "", fltClassType, PropertyType::Scalar);
|
|
PX_ASSERT(cls.get32BitSizeInfo().mAlignment == 4);
|
|
PX_ASSERT(cls.get32BitSize() == 16);
|
|
PX_ASSERT(cls.get64BitSizeInfo().mAlignment == 4);
|
|
PX_ASSERT(cls.get64BitSize() == 16);
|
|
PX_ASSERT(cls.mPackedUniformWidth == 4);
|
|
PX_ASSERT(cls.mPackedClassType == fltClassType);
|
|
cls.mLocked = true;
|
|
}
|
|
|
|
{
|
|
ClassDescImpl& cls = getOrCreateClassImpl(getPvdNamespacedNameForType<PxQuat>(), getPvdTypeForType<PxQuat>());
|
|
createProperty(cls.mClassId, "x", "", fltClassType, PropertyType::Scalar);
|
|
createProperty(cls.mClassId, "y", "", fltClassType, PropertyType::Scalar);
|
|
createProperty(cls.mClassId, "z", "", fltClassType, PropertyType::Scalar);
|
|
createProperty(cls.mClassId, "w", "", fltClassType, PropertyType::Scalar);
|
|
PX_ASSERT(cls.get32BitSizeInfo().mAlignment == 4);
|
|
PX_ASSERT(cls.get32BitSize() == 16);
|
|
PX_ASSERT(cls.get64BitSizeInfo().mAlignment == 4);
|
|
PX_ASSERT(cls.get64BitSize() == 16);
|
|
PX_ASSERT(cls.mPackedUniformWidth == 4);
|
|
PX_ASSERT(cls.mPackedClassType == fltClassType);
|
|
cls.mLocked = true;
|
|
}
|
|
|
|
{
|
|
ClassDescImpl& cls =
|
|
getOrCreateClassImpl(getPvdNamespacedNameForType<PxBounds3>(), getPvdTypeForType<PxBounds3>());
|
|
createProperty(cls.mClassId, "minimum", "", v3ClassType, PropertyType::Scalar);
|
|
createProperty(cls.mClassId, "maximum", "", v3ClassType, PropertyType::Scalar);
|
|
PX_ASSERT(cls.get32BitSizeInfo().mAlignment == 4);
|
|
PX_ASSERT(cls.get32BitSize() == 24);
|
|
PX_ASSERT(cls.mPackedUniformWidth == 4);
|
|
PX_ASSERT(cls.mPackedClassType == fltClassType);
|
|
cls.mLocked = true;
|
|
}
|
|
|
|
{
|
|
ClassDescImpl& cls =
|
|
getOrCreateClassImpl(getPvdNamespacedNameForType<PxTransform>(), getPvdTypeForType<PxTransform>());
|
|
createProperty(cls.mClassId, "q", "", qtClassType, PropertyType::Scalar);
|
|
createProperty(cls.mClassId, "p", "", v3ClassType, PropertyType::Scalar);
|
|
PX_ASSERT(cls.get32BitSizeInfo().mAlignment == 4);
|
|
PX_ASSERT(cls.get32BitSize() == 28);
|
|
PX_ASSERT(cls.mPackedUniformWidth == 4);
|
|
PX_ASSERT(cls.mPackedClassType == fltClassType);
|
|
cls.mLocked = true;
|
|
}
|
|
|
|
{
|
|
ClassDescImpl& cls =
|
|
getOrCreateClassImpl(getPvdNamespacedNameForType<PxMat33>(), getPvdTypeForType<PxMat33>());
|
|
createProperty(cls.mClassId, "column0", "", v3ClassType, PropertyType::Scalar);
|
|
createProperty(cls.mClassId, "column1", "", v3ClassType, PropertyType::Scalar);
|
|
createProperty(cls.mClassId, "column2", "", v3ClassType, PropertyType::Scalar);
|
|
PX_ASSERT(cls.get32BitSizeInfo().mAlignment == 4);
|
|
PX_ASSERT(cls.get32BitSize() == 36);
|
|
PX_ASSERT(cls.mPackedUniformWidth == 4);
|
|
PX_ASSERT(cls.mPackedClassType == fltClassType);
|
|
cls.mLocked = true;
|
|
}
|
|
|
|
{
|
|
ClassDescImpl& cls =
|
|
getOrCreateClassImpl(getPvdNamespacedNameForType<PxMat44>(), getPvdTypeForType<PxMat44>());
|
|
createProperty(cls.mClassId, "column0", "", v4ClassType, PropertyType::Scalar);
|
|
createProperty(cls.mClassId, "column1", "", v4ClassType, PropertyType::Scalar);
|
|
createProperty(cls.mClassId, "column2", "", v4ClassType, PropertyType::Scalar);
|
|
createProperty(cls.mClassId, "column3", "", v4ClassType, PropertyType::Scalar);
|
|
PX_ASSERT(cls.get32BitSizeInfo().mAlignment == 4);
|
|
PX_ASSERT(cls.get32BitSize() == 64);
|
|
PX_ASSERT(cls.mPackedUniformWidth == 4);
|
|
PX_ASSERT(cls.mPackedClassType == fltClassType);
|
|
cls.mLocked = true;
|
|
}
|
|
|
|
{
|
|
ClassDescImpl& cls =
|
|
getOrCreateClassImpl(getPvdNamespacedNameForType<U32Array4>(), getPvdTypeForType<U32Array4>());
|
|
createProperty(cls.mClassId, "d0", "", u32ClassType, PropertyType::Scalar);
|
|
createProperty(cls.mClassId, "d1", "", u32ClassType, PropertyType::Scalar);
|
|
createProperty(cls.mClassId, "d2", "", u32ClassType, PropertyType::Scalar);
|
|
createProperty(cls.mClassId, "d3", "", u32ClassType, PropertyType::Scalar);
|
|
cls.mLocked = true;
|
|
}
|
|
}
|
|
virtual ~PvdObjectModelMetaDataImpl()
|
|
{
|
|
mStringTable->release();
|
|
PVD_FOREACH(idx, mClasses.size())
|
|
{
|
|
if(mClasses[idx] != NULL)
|
|
PVD_DELETE(mClasses[idx]);
|
|
}
|
|
mClasses.clear();
|
|
PVD_FOREACH(idx, mProperties.size()) PVD_DELETE(mProperties[idx]);
|
|
mProperties.clear();
|
|
PVD_FOREACH(idx, mPropertyMessages.size()) PVD_DELETE(mPropertyMessages[idx]);
|
|
mPropertyMessages.clear();
|
|
}
|
|
|
|
ClassDescImpl& getOrCreateClassImpl(const NamespacedName& nm, int32_t idx)
|
|
{
|
|
ClassDescImpl* impl(getClassImpl(idx));
|
|
if(impl)
|
|
return *impl;
|
|
NamespacedName safeName(mStringTable->registerStr(nm.mNamespace), mStringTable->registerStr(nm.mName));
|
|
while(idx >= int32_t(mClasses.size()))
|
|
mClasses.pushBack(NULL);
|
|
mClasses[uint32_t(idx)] = PVD_NEW(ClassDescImpl)(ClassDescription(safeName, idx));
|
|
mNameToClasses.insert(nm, mClasses[uint32_t(idx)]);
|
|
mNextClassId = PxMax(mNextClassId, idx + 1);
|
|
return *mClasses[uint32_t(idx)];
|
|
}
|
|
|
|
ClassDescImpl& getOrCreateClassImpl(const NamespacedName& nm)
|
|
{
|
|
ClassDescImpl* retval = findClassImpl(nm);
|
|
if(retval)
|
|
return *retval;
|
|
return getOrCreateClassImpl(nm, nextClassId());
|
|
}
|
|
virtual ClassDescription getOrCreateClass(const NamespacedName& nm)
|
|
{
|
|
return getOrCreateClassImpl(nm);
|
|
}
|
|
// get or create parent, lock parent. deriveFrom getOrCreatechild.
|
|
virtual bool deriveClass(const NamespacedName& parent, const NamespacedName& child)
|
|
{
|
|
ClassDescImpl& p(getOrCreateClassImpl(parent));
|
|
ClassDescImpl& c(getOrCreateClassImpl(child));
|
|
|
|
if(c.mBaseClass >= 0)
|
|
{
|
|
PX_ASSERT(c.mBaseClass == p.mClassId);
|
|
return false;
|
|
}
|
|
p.mLocked = true;
|
|
c.mBaseClass = p.mClassId;
|
|
c.get32BitSizeInfo() = p.get32BitSizeInfo();
|
|
c.get64BitSizeInfo() = p.get64BitSizeInfo();
|
|
c.mPackedClassType = p.mPackedClassType;
|
|
c.mPackedUniformWidth = p.mPackedUniformWidth;
|
|
c.mRequiresDestruction = p.mRequiresDestruction;
|
|
c.m32OffsetArray = p.m32OffsetArray;
|
|
c.m64OffsetArray = p.m64OffsetArray;
|
|
// Add all the parent propertes to this class in the global name map.
|
|
for(ClassDescImpl* parent0 = &p; parent0 != NULL; parent0 = getClassImpl(parent0->mBaseClass))
|
|
{
|
|
PVD_FOREACH(idx, parent0->mPropImps.size())
|
|
mNameToProperties.insert(ClassPropertyName(c.mName, parent0->mPropImps[idx]->mName), parent0->mPropImps[idx]);
|
|
|
|
if(parent0->mBaseClass < 0)
|
|
break;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
ClassDescImpl* findClassImpl(const NamespacedName& nm) const
|
|
{
|
|
const TNameToClassMap::Entry* entry(mNameToClasses.find(nm));
|
|
if(entry)
|
|
return entry->second;
|
|
return NULL;
|
|
}
|
|
virtual Option<ClassDescription> findClass(const NamespacedName& nm) const
|
|
{
|
|
ClassDescImpl* retval = findClassImpl(nm);
|
|
if(retval)
|
|
return *retval;
|
|
return Option<ClassDescription>();
|
|
}
|
|
|
|
ClassDescImpl* getClassImpl(int32_t classId) const
|
|
{
|
|
if(classId < 0)
|
|
return NULL;
|
|
uint32_t idx = uint32_t(classId);
|
|
if(idx < mClasses.size())
|
|
return mClasses[idx];
|
|
return NULL;
|
|
}
|
|
|
|
virtual Option<ClassDescription> getClass(int32_t classId) const
|
|
{
|
|
ClassDescImpl* impl(getClassImpl(classId));
|
|
if(impl)
|
|
return *impl;
|
|
return None();
|
|
}
|
|
|
|
virtual ClassDescription* getClassPtr(int32_t classId) const
|
|
{
|
|
return getClassImpl(classId);
|
|
}
|
|
|
|
virtual Option<ClassDescription> getParentClass(int32_t classId) const
|
|
{
|
|
ClassDescImpl* impl(getClassImpl(classId));
|
|
if(impl == NULL)
|
|
return None();
|
|
return getClass(impl->mBaseClass);
|
|
}
|
|
|
|
virtual void lockClass(int32_t classId)
|
|
{
|
|
ClassDescImpl* impl(getClassImpl(classId));
|
|
PX_ASSERT(impl);
|
|
if(impl)
|
|
impl->mLocked = true;
|
|
}
|
|
virtual uint32_t getNbClasses() const
|
|
{
|
|
uint32_t total = 0;
|
|
PVD_FOREACH(idx, mClasses.size()) if(mClasses[idx])++ total;
|
|
return total;
|
|
}
|
|
|
|
virtual uint32_t getClasses(ClassDescription* outClasses, uint32_t requestCount, uint32_t startIndex = 0) const
|
|
{
|
|
uint32_t classCount(getNbClasses());
|
|
startIndex = PxMin(classCount, startIndex);
|
|
uint32_t retAmount = PxMin(requestCount, classCount - startIndex);
|
|
|
|
uint32_t idx = 0;
|
|
while(startIndex)
|
|
{
|
|
if(mClasses[idx] != NULL)
|
|
--startIndex;
|
|
++idx;
|
|
}
|
|
|
|
uint32_t inserted = 0;
|
|
uint32_t classesSize = static_cast<uint32_t>(mClasses.size());
|
|
while(inserted < retAmount && idx < classesSize)
|
|
{
|
|
if(mClasses[idx] != NULL)
|
|
{
|
|
outClasses[inserted] = *mClasses[idx];
|
|
++inserted;
|
|
}
|
|
++idx;
|
|
}
|
|
return inserted;
|
|
}
|
|
|
|
uint32_t updateByteSizeAndGetPropertyAlignment(ClassDescriptionSizeInfo& dest, const ClassDescriptionSizeInfo& src)
|
|
{
|
|
uint32_t alignment = src.mAlignment;
|
|
dest.mAlignment = PxMax(dest.mAlignment, alignment);
|
|
uint32_t offset = align(dest.mDataByteSize, alignment);
|
|
dest.mDataByteSize = offset + src.mByteSize;
|
|
dest.mByteSize = align(dest.mDataByteSize, dest.mAlignment);
|
|
return offset;
|
|
}
|
|
|
|
void transferPtrOffsets(ClassDescriptionSizeInfo& destInfo, Array<PtrOffset>& destArray,
|
|
const Array<PtrOffset>& src, uint32_t offset)
|
|
{
|
|
PVD_FOREACH(idx, src.size())
|
|
destArray.pushBack(PtrOffset(src[idx].mOffsetType, src[idx].mOffset + offset));
|
|
destInfo.mPtrOffsets = DataRef<PtrOffset>(destArray.begin(), destArray.end());
|
|
}
|
|
|
|
virtual Option<PropertyDescription> createProperty(int32_t classId, String name, String semantic, int32_t datatype,
|
|
PropertyType::Enum propertyType)
|
|
{
|
|
ClassDescImpl* cls(getClassImpl(classId));
|
|
PX_ASSERT(cls);
|
|
if(!cls)
|
|
return None();
|
|
if(cls->mLocked)
|
|
{
|
|
PX_ASSERT(false);
|
|
return None();
|
|
}
|
|
PropDescImpl* impl(cls->findProperty(name));
|
|
// duplicate property definition
|
|
if(impl)
|
|
{
|
|
PX_ASSERT(false);
|
|
return None();
|
|
}
|
|
if(datatype == getPvdTypeForType<String>())
|
|
{
|
|
PX_ASSERT(false);
|
|
return None();
|
|
}
|
|
// The datatype for this property has not been declared.
|
|
ClassDescImpl* propDType(getClassImpl(datatype));
|
|
PX_ASSERT(propDType);
|
|
if(!propDType)
|
|
return None();
|
|
NamespacedName propClsName(propDType->mName);
|
|
int32_t propPackedWidth = propDType->mPackedUniformWidth;
|
|
int32_t propPackedType = propDType->mPackedClassType;
|
|
// The implications of properties being complex types aren't major
|
|
//*until* you start trying to undue a property event that set values
|
|
// of those complex types. Then things just get too complex.
|
|
if(propDType->mRequiresDestruction)
|
|
{
|
|
PX_ASSERT(false);
|
|
return None();
|
|
}
|
|
bool requiresDestruction = propDType->mRequiresDestruction || cls->mRequiresDestruction;
|
|
|
|
if(propertyType == PropertyType::Array)
|
|
{
|
|
int32_t tempId = DataTypeToPvdTypeMap<ArrayData>::BaseTypeEnum;
|
|
propDType = getClassImpl(tempId);
|
|
PX_ASSERT(propDType);
|
|
if(!propDType)
|
|
return None();
|
|
requiresDestruction = true;
|
|
}
|
|
uint32_t offset32 = updateByteSizeAndGetPropertyAlignment(cls->get32BitSizeInfo(), propDType->get32BitSizeInfo());
|
|
uint32_t offset64 = updateByteSizeAndGetPropertyAlignment(cls->get64BitSizeInfo(), propDType->get64BitSizeInfo());
|
|
transferPtrOffsets(cls->get32BitSizeInfo(), cls->m32OffsetArray, propDType->m32OffsetArray, offset32);
|
|
transferPtrOffsets(cls->get64BitSizeInfo(), cls->m64OffsetArray, propDType->m64OffsetArray, offset64);
|
|
propDType->mLocked = true; // Can't add members to the property type.
|
|
cls->mRequiresDestruction = requiresDestruction;
|
|
int32_t propId = int32_t(mProperties.size());
|
|
PropertyDescription newDesc(cls->mName, cls->mClassId, name, semantic, datatype, propClsName, propertyType,
|
|
propId, offset32, offset64);
|
|
mProperties.pushBack(PVD_NEW(PropDescImpl)(newDesc, *mStringTable));
|
|
mNameToProperties.insert(ClassPropertyName(cls->mName, mProperties.back()->mName), mProperties.back());
|
|
cls->addProperty(mProperties.back());
|
|
bool firstProp = cls->mPropImps.size() == 1;
|
|
|
|
if(firstProp)
|
|
{
|
|
cls->mPackedUniformWidth = propPackedWidth;
|
|
cls->mPackedClassType = propPackedType;
|
|
}
|
|
else
|
|
{
|
|
bool packed = (propPackedWidth > 0) && (cls->get32BitSizeInfo().mDataByteSize % propPackedWidth) == 0;
|
|
if(cls->mPackedClassType >= 0) // maybe uncheck packed class type
|
|
{
|
|
if(propPackedType < 0 || cls->mPackedClassType != propPackedType
|
|
// Object refs require conversion from stream to db id
|
|
||
|
|
datatype == getPvdTypeForType<ObjectRef>()
|
|
// Strings also require conversion from stream to db id.
|
|
||
|
|
datatype == getPvdTypeForType<StringHandle>() || packed == false)
|
|
cls->mPackedClassType = -1;
|
|
}
|
|
if(cls->mPackedUniformWidth >= 0) // maybe uncheck packed class width
|
|
{
|
|
if(propPackedWidth < 0 || cls->mPackedUniformWidth != propPackedWidth
|
|
// object refs, because they require special treatment during parsing,
|
|
// cannot be packed
|
|
||
|
|
datatype == getPvdTypeForType<ObjectRef>()
|
|
// Likewise, string handles are special because the data needs to be sent *after*
|
|
// the
|
|
||
|
|
datatype == getPvdTypeForType<StringHandle>() || packed == false)
|
|
cls->mPackedUniformWidth = -1; // invalid packed width.
|
|
}
|
|
}
|
|
return *mProperties.back();
|
|
}
|
|
|
|
PropDescImpl* findPropImpl(const NamespacedName& clsName, String prop) const
|
|
{
|
|
const TNameToPropMap::Entry* entry = mNameToProperties.find(ClassPropertyName(clsName, prop));
|
|
if(entry)
|
|
return entry->second;
|
|
return NULL;
|
|
}
|
|
virtual Option<PropertyDescription> findProperty(const NamespacedName& cls, String propName) const
|
|
{
|
|
PropDescImpl* prop(findPropImpl(cls, propName));
|
|
if(prop)
|
|
return *prop;
|
|
return None();
|
|
}
|
|
|
|
virtual Option<PropertyDescription> findProperty(int32_t clsId, String propName) const
|
|
{
|
|
ClassDescImpl* cls(getClassImpl(clsId));
|
|
PX_ASSERT(cls);
|
|
if(!cls)
|
|
return None();
|
|
PropDescImpl* prop(findPropImpl(cls->mName, propName));
|
|
if(prop)
|
|
return *prop;
|
|
return None();
|
|
}
|
|
|
|
PropDescImpl* getPropertyImpl(int32_t propId) const
|
|
{
|
|
PX_ASSERT(propId >= 0);
|
|
if(propId < 0)
|
|
return NULL;
|
|
uint32_t val = uint32_t(propId);
|
|
if(val >= mProperties.size())
|
|
{
|
|
PX_ASSERT(false);
|
|
return NULL;
|
|
}
|
|
return mProperties[val];
|
|
}
|
|
|
|
virtual Option<PropertyDescription> getProperty(int32_t propId) const
|
|
{
|
|
PropDescImpl* impl(getPropertyImpl(propId));
|
|
if(impl)
|
|
return *impl;
|
|
return None();
|
|
}
|
|
|
|
virtual void setNamedPropertyValues(DataRef<NamedValue> values, int32_t propId)
|
|
{
|
|
PropDescImpl* impl(getPropertyImpl(propId));
|
|
if(impl)
|
|
{
|
|
impl->mValueNames.resize(values.size());
|
|
PVD_FOREACH(idx, values.size()) impl->mValueNames[idx] = values[idx];
|
|
}
|
|
}
|
|
|
|
virtual DataRef<NamedValue> getNamedPropertyValues(int32_t propId) const
|
|
{
|
|
PropDescImpl* impl(getPropertyImpl(propId));
|
|
if(impl)
|
|
{
|
|
return toDataRef(impl->mValueNames);
|
|
}
|
|
return DataRef<NamedValue>();
|
|
}
|
|
|
|
virtual uint32_t getNbProperties(int32_t classId) const
|
|
{
|
|
uint32_t retval = 0;
|
|
for(ClassDescImpl* impl(getClassImpl(classId)); impl; impl = getClassImpl(impl->mBaseClass))
|
|
{
|
|
retval += impl->mPropImps.size();
|
|
if(impl->mBaseClass < 0)
|
|
break;
|
|
}
|
|
return retval;
|
|
}
|
|
|
|
// Properties need to be returned in base class order, so this requires a recursive function.
|
|
uint32_t getPropertiesImpl(int32_t classId, PropertyDescription*& outBuffer, uint32_t& numItems,
|
|
uint32_t& startIdx) const
|
|
{
|
|
ClassDescImpl* impl = getClassImpl(classId);
|
|
if(impl)
|
|
{
|
|
uint32_t retval = 0;
|
|
if(impl->mBaseClass >= 0)
|
|
retval = getPropertiesImpl(impl->mBaseClass, outBuffer, numItems, startIdx);
|
|
|
|
uint32_t localStart = PxMin(impl->mPropImps.size(), startIdx);
|
|
uint32_t localNumItems = PxMin(numItems, impl->mPropImps.size() - localStart);
|
|
PVD_FOREACH(idx, localNumItems)
|
|
{
|
|
outBuffer[idx] = *impl->mPropImps[localStart + idx];
|
|
}
|
|
|
|
startIdx -= localStart;
|
|
numItems -= localNumItems;
|
|
outBuffer += localNumItems;
|
|
return retval + localNumItems;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
virtual uint32_t getProperties(int32_t classId, PropertyDescription* outBuffer, uint32_t numItems,
|
|
uint32_t startIdx) const
|
|
{
|
|
return getPropertiesImpl(classId, outBuffer, numItems, startIdx);
|
|
}
|
|
|
|
virtual MarshalQueryResult checkMarshalling(int32_t srcClsId, int32_t dstClsId) const
|
|
{
|
|
Option<ClassDescription> propTypeOpt(getClass(dstClsId));
|
|
if(propTypeOpt.hasValue() == false)
|
|
{
|
|
PX_ASSERT(false);
|
|
return MarshalQueryResult();
|
|
}
|
|
const ClassDescription& propType(propTypeOpt);
|
|
|
|
Option<ClassDescription> incomingTypeOpt(getClass(srcClsId));
|
|
if(incomingTypeOpt.hasValue() == false)
|
|
{
|
|
PX_ASSERT(false);
|
|
return MarshalQueryResult();
|
|
}
|
|
const ClassDescription& incomingType(incomingTypeOpt);
|
|
// Can only marshal simple things at this point in time.
|
|
bool needsMarshalling = false;
|
|
bool canMarshal = false;
|
|
TSingleMarshaller single = NULL;
|
|
TBlockMarshaller block = NULL;
|
|
if(incomingType.mClassId != propType.mClassId)
|
|
{
|
|
// Check that marshalling is even possible.
|
|
if((incomingType.mPackedUniformWidth >= 0 && propType.mPackedUniformWidth >= 0) == false)
|
|
{
|
|
PX_ASSERT(false);
|
|
return MarshalQueryResult();
|
|
}
|
|
|
|
int32_t srcType = incomingType.mPackedClassType;
|
|
int32_t dstType = propType.mPackedClassType;
|
|
|
|
int32_t srcWidth = incomingType.mPackedUniformWidth;
|
|
int32_t dstWidth = propType.mPackedUniformWidth;
|
|
canMarshal = getMarshalOperators(single, block, srcType, dstType);
|
|
if(srcWidth == dstWidth)
|
|
needsMarshalling = canMarshal; // If the types are the same width, we assume we can convert between some
|
|
// of them seamlessly (uint16_t, int16_t)
|
|
else
|
|
{
|
|
needsMarshalling = true;
|
|
// If we can't marshall and we have to then we can't set the property value.
|
|
// This indicates that the src and dest are different properties and we don't
|
|
// know how to convert between them.
|
|
if(!canMarshal)
|
|
{
|
|
PX_ASSERT(false);
|
|
return MarshalQueryResult();
|
|
}
|
|
}
|
|
}
|
|
return MarshalQueryResult(srcClsId, dstClsId, canMarshal, needsMarshalling, block);
|
|
}
|
|
|
|
PropertyMessageDescriptionImpl* findPropertyMessageImpl(const NamespacedName& messageName) const
|
|
{
|
|
const TNameToPropertyMessageMap::Entry* entry = mPropertyMessageMap.find(messageName);
|
|
if(entry)
|
|
return entry->second;
|
|
return NULL;
|
|
}
|
|
|
|
PropertyMessageDescriptionImpl* getPropertyMessageImpl(int32_t msg) const
|
|
{
|
|
int32_t msgCount = int32_t(mPropertyMessages.size());
|
|
if(msg >= 0 && msg < msgCount)
|
|
return mPropertyMessages[uint32_t(msg)];
|
|
return NULL;
|
|
}
|
|
|
|
virtual Option<PropertyMessageDescription> createPropertyMessage(const NamespacedName& clsName,
|
|
const NamespacedName& messageName,
|
|
DataRef<PropertyMessageArg> entries,
|
|
uint32_t messageSize)
|
|
{
|
|
PropertyMessageDescriptionImpl* existing(findPropertyMessageImpl(messageName));
|
|
if(existing)
|
|
{
|
|
PX_ASSERT(false);
|
|
return None();
|
|
}
|
|
ClassDescImpl* cls = findClassImpl(clsName);
|
|
PX_ASSERT(cls);
|
|
if(!cls)
|
|
return None();
|
|
int32_t msgId = int32_t(mPropertyMessages.size());
|
|
PropertyMessageDescriptionImpl* newMessage = PVD_NEW(PropertyMessageDescriptionImpl)(
|
|
PropertyMessageDescription(mStringTable->registerName(clsName), cls->mClassId,
|
|
mStringTable->registerName(messageName), msgId, messageSize));
|
|
uint32_t calculatedSize = 0;
|
|
PVD_FOREACH(idx, entries.size())
|
|
{
|
|
PropertyMessageArg entry(entries[idx]);
|
|
ClassDescImpl* dtypeCls = findClassImpl(entry.mDatatypeName);
|
|
if(dtypeCls == NULL)
|
|
{
|
|
PX_ASSERT(false);
|
|
goto DestroyNewMessage;
|
|
}
|
|
ClassDescriptionSizeInfo dtypeInfo(dtypeCls->get32BitSizeInfo());
|
|
uint32_t incomingSize = dtypeInfo.mByteSize;
|
|
if(entry.mByteSize < incomingSize)
|
|
{
|
|
PX_ASSERT(false);
|
|
goto DestroyNewMessage;
|
|
}
|
|
|
|
calculatedSize = PxMax(calculatedSize, entry.mMessageOffset + entry.mByteSize);
|
|
if(calculatedSize > messageSize)
|
|
{
|
|
PX_ASSERT(false);
|
|
goto DestroyNewMessage;
|
|
}
|
|
|
|
Option<PropertyDescription> propName(findProperty(cls->mClassId, entry.mPropertyName));
|
|
if(propName.hasValue() == false)
|
|
{
|
|
PX_ASSERT(false);
|
|
goto DestroyNewMessage;
|
|
}
|
|
|
|
Option<ClassDescription> propCls(getClass(propName.getValue().mDatatype));
|
|
if(propCls.hasValue() == false)
|
|
{
|
|
PX_ASSERT(false);
|
|
goto DestroyNewMessage;
|
|
}
|
|
|
|
PropertyMessageEntryImpl newEntry(PropertyMessageEntry(
|
|
propName, dtypeCls->mName, dtypeCls->mClassId, entry.mMessageOffset, incomingSize, dtypeInfo.mByteSize));
|
|
newMessage->addEntry(newEntry);
|
|
|
|
if(newEntry.mDatatypeId == getPvdTypeForType<String>())
|
|
newMessage->mStringOffsetArray.pushBack(entry.mMessageOffset);
|
|
|
|
// property messages cannot be marshalled at this time.
|
|
if(newEntry.mDatatypeId != getPvdTypeForType<String>() && newEntry.mDatatypeId != getPvdTypeForType<VoidPtr>())
|
|
{
|
|
MarshalQueryResult marshalInfo = checkMarshalling(newEntry.mDatatypeId, newEntry.mProperty.mDatatype);
|
|
if(marshalInfo.needsMarshalling)
|
|
{
|
|
PX_ASSERT(false);
|
|
goto DestroyNewMessage;
|
|
}
|
|
}
|
|
}
|
|
|
|
if(newMessage)
|
|
{
|
|
newMessage->mStringOffsets =
|
|
DataRef<uint32_t>(newMessage->mStringOffsetArray.begin(), newMessage->mStringOffsetArray.end());
|
|
mPropertyMessages.pushBack(newMessage);
|
|
mPropertyMessageMap.insert(messageName, newMessage);
|
|
return *newMessage;
|
|
}
|
|
|
|
DestroyNewMessage:
|
|
if(newMessage)
|
|
PVD_DELETE(newMessage);
|
|
|
|
return None();
|
|
}
|
|
virtual Option<PropertyMessageDescription> findPropertyMessage(const NamespacedName& msgName) const
|
|
{
|
|
PropertyMessageDescriptionImpl* desc(findPropertyMessageImpl(msgName));
|
|
if(desc)
|
|
return *desc;
|
|
return None();
|
|
}
|
|
|
|
virtual Option<PropertyMessageDescription> getPropertyMessage(int32_t msgId) const
|
|
{
|
|
PropertyMessageDescriptionImpl* desc(getPropertyMessageImpl(msgId));
|
|
if(desc)
|
|
return *desc;
|
|
return None();
|
|
}
|
|
|
|
virtual uint32_t getNbPropertyMessages() const
|
|
{
|
|
return mPropertyMessages.size();
|
|
}
|
|
|
|
virtual uint32_t getPropertyMessages(PropertyMessageDescription* msgBuf, uint32_t bufLen, uint32_t startIdx = 0) const
|
|
{
|
|
startIdx = PxMin(startIdx, getNbPropertyMessages());
|
|
bufLen = PxMin(bufLen, getNbPropertyMessages() - startIdx);
|
|
PVD_FOREACH(idx, bufLen) msgBuf[idx] = *mPropertyMessages[idx + startIdx];
|
|
return bufLen;
|
|
}
|
|
|
|
struct MetaDataWriter
|
|
{
|
|
const PvdObjectModelMetaDataImpl& mMetaData;
|
|
PvdOutputStream& mStream;
|
|
MetaDataWriter(const PvdObjectModelMetaDataImpl& meta, PvdOutputStream& stream)
|
|
: mMetaData(meta), mStream(stream)
|
|
{
|
|
}
|
|
|
|
void streamify(NamespacedName& type)
|
|
{
|
|
mStream << mMetaData.mStringTable->strToHandle(type.mNamespace);
|
|
mStream << mMetaData.mStringTable->strToHandle(type.mName);
|
|
}
|
|
void streamify(String& type)
|
|
{
|
|
mStream << mMetaData.mStringTable->strToHandle(type);
|
|
}
|
|
void streamify(int32_t& type)
|
|
{
|
|
mStream << type;
|
|
}
|
|
void streamify(uint32_t& type)
|
|
{
|
|
mStream << type;
|
|
}
|
|
void streamify(uint8_t type)
|
|
{
|
|
mStream << type;
|
|
}
|
|
void streamify(bool type)
|
|
{
|
|
streamify( uint8_t(type));
|
|
}
|
|
void streamify(PropertyType::Enum type)
|
|
{
|
|
uint32_t val = static_cast<uint32_t>(type);
|
|
mStream << val;
|
|
}
|
|
void streamify(NamedValue& type)
|
|
{
|
|
streamify(type.mValue);
|
|
streamify(type.mName);
|
|
}
|
|
void streamifyLinks(PropDescImpl* prop)
|
|
{
|
|
streamify(prop->mPropertyId);
|
|
}
|
|
void streamify(PropertyDescription& prop)
|
|
{
|
|
streamify(prop.mPropertyId);
|
|
}
|
|
void streamify(PropertyMessageEntryImpl& prop)
|
|
{
|
|
prop.serialize(*this);
|
|
}
|
|
void streamify(PtrOffset& off)
|
|
{
|
|
uint32_t type = off.mOffsetType;
|
|
mStream << type;
|
|
mStream << off.mOffset;
|
|
}
|
|
template <typename TDataType>
|
|
void streamify(TDataType* type)
|
|
{
|
|
int32_t existMarker = type ? 1 : 0;
|
|
mStream << existMarker;
|
|
if(type)
|
|
type->serialize(*this);
|
|
}
|
|
template <typename TArrayType>
|
|
void streamify(const Array<TArrayType>& type)
|
|
{
|
|
mStream << static_cast<uint32_t>(type.size());
|
|
PVD_FOREACH(idx, type.size()) streamify(const_cast<TArrayType&>(type[idx]));
|
|
}
|
|
template <typename TArrayType>
|
|
void streamifyLinks(const Array<TArrayType>& type)
|
|
{
|
|
mStream << static_cast<uint32_t>(type.size());
|
|
PVD_FOREACH(idx, type.size()) streamifyLinks(const_cast<TArrayType&>(type[idx]));
|
|
}
|
|
|
|
private:
|
|
MetaDataWriter& operator=(const MetaDataWriter&);
|
|
};
|
|
|
|
template <typename TStreamType>
|
|
struct MetaDataReader
|
|
{
|
|
PvdObjectModelMetaDataImpl& mMetaData;
|
|
TStreamType& mStream;
|
|
MetaDataReader(PvdObjectModelMetaDataImpl& meta, TStreamType& stream) : mMetaData(meta), mStream(stream)
|
|
{
|
|
}
|
|
|
|
void streamify(NamespacedName& type)
|
|
{
|
|
streamify(type.mNamespace);
|
|
streamify(type.mName);
|
|
}
|
|
|
|
void streamify(String& type)
|
|
{
|
|
uint32_t handle;
|
|
mStream >> handle;
|
|
type = mMetaData.mStringTable->handleToStr(handle);
|
|
}
|
|
void streamify(int32_t& type)
|
|
{
|
|
mStream >> type;
|
|
}
|
|
void streamify(uint32_t& type)
|
|
{
|
|
mStream >> type;
|
|
}
|
|
void streamify(bool& type)
|
|
{
|
|
uint8_t data;
|
|
mStream >> data;
|
|
type = data ? true : false;
|
|
}
|
|
|
|
void streamify(PropertyType::Enum& type)
|
|
{
|
|
uint32_t val;
|
|
mStream >> val;
|
|
type = static_cast<PropertyType::Enum>(val);
|
|
}
|
|
void streamify(NamedValue& type)
|
|
{
|
|
streamify(type.mValue);
|
|
streamify(type.mName);
|
|
}
|
|
void streamify(PropertyMessageEntryImpl& type)
|
|
{
|
|
type.serialize(*this);
|
|
}
|
|
void streamify(PtrOffset& off)
|
|
{
|
|
uint32_t type;
|
|
mStream >> type;
|
|
mStream >> off.mOffset;
|
|
off.mOffsetType = static_cast<PtrOffsetType::Enum>(type);
|
|
}
|
|
void streamifyLinks(PropDescImpl*& prop)
|
|
{
|
|
int32_t propId;
|
|
streamify(propId);
|
|
prop = mMetaData.getPropertyImpl(propId);
|
|
}
|
|
void streamify(PropertyDescription& prop)
|
|
{
|
|
streamify(prop.mPropertyId);
|
|
prop = mMetaData.getProperty(prop.mPropertyId);
|
|
}
|
|
template <typename TDataType>
|
|
void streamify(TDataType*& type)
|
|
{
|
|
uint32_t existMarker;
|
|
mStream >> existMarker;
|
|
if(existMarker)
|
|
{
|
|
TDataType* newType = PVD_NEW(TDataType)();
|
|
newType->serialize(*this);
|
|
type = newType;
|
|
}
|
|
else
|
|
type = NULL;
|
|
}
|
|
template <typename TArrayType>
|
|
void streamify(Array<TArrayType>& type)
|
|
{
|
|
uint32_t typeSize;
|
|
mStream >> typeSize;
|
|
type.resize(typeSize);
|
|
PVD_FOREACH(idx, type.size()) streamify(type[idx]);
|
|
}
|
|
template <typename TArrayType>
|
|
void streamifyLinks(Array<TArrayType>& type)
|
|
{
|
|
uint32_t typeSize;
|
|
mStream >> typeSize;
|
|
type.resize(typeSize);
|
|
PVD_FOREACH(idx, type.size()) streamifyLinks(type[idx]);
|
|
}
|
|
|
|
private:
|
|
MetaDataReader& operator=(const MetaDataReader&);
|
|
};
|
|
|
|
virtual void write(PvdOutputStream& stream) const
|
|
{
|
|
stream << getCurrentPvdObjectModelVersion();
|
|
stream << mNextClassId;
|
|
mStringTable->write(stream);
|
|
MetaDataWriter writer(*this, stream);
|
|
writer.streamify(mProperties);
|
|
writer.streamify(mClasses);
|
|
writer.streamify(mPropertyMessages);
|
|
}
|
|
|
|
template <typename TReaderType>
|
|
void read(TReaderType& stream)
|
|
{
|
|
uint32_t version;
|
|
stream >> version;
|
|
stream >> mNextClassId;
|
|
mStringTable->read(stream);
|
|
MetaDataReader<TReaderType> reader(*this, stream);
|
|
reader.streamify(mProperties);
|
|
reader.streamify(mClasses);
|
|
reader.streamify(mPropertyMessages);
|
|
|
|
mNameToClasses.clear();
|
|
mNameToProperties.clear();
|
|
mPropertyMessageMap.clear();
|
|
PVD_FOREACH(i, mClasses.size())
|
|
{
|
|
ClassDescImpl* cls(mClasses[i]);
|
|
if(cls == NULL)
|
|
continue;
|
|
mNameToClasses.insert(cls->mName, mClasses[i]);
|
|
uint32_t propCount = getNbProperties(cls->mClassId);
|
|
PropertyDescription descs[16];
|
|
uint32_t offset = 0;
|
|
for(uint32_t idx = 0; idx < propCount; idx = offset)
|
|
{
|
|
uint32_t numProps = getProperties(cls->mClassId, descs, 16, offset);
|
|
offset += numProps;
|
|
for(uint32_t propIdx = 0; propIdx < numProps; ++propIdx)
|
|
{
|
|
PropDescImpl* prop = getPropertyImpl(descs[propIdx].mPropertyId);
|
|
if(prop)
|
|
mNameToProperties.insert(ClassPropertyName(cls->mName, prop->mName), prop);
|
|
}
|
|
}
|
|
}
|
|
PVD_FOREACH(idx, mPropertyMessages.size())
|
|
mPropertyMessageMap.insert(mPropertyMessages[idx]->mMessageName, mPropertyMessages[idx]);
|
|
}
|
|
|
|
virtual StringTable& getStringTable() const
|
|
{
|
|
return *mStringTable;
|
|
}
|
|
virtual void addRef()
|
|
{
|
|
++mRefCount;
|
|
}
|
|
virtual void release()
|
|
{
|
|
if(mRefCount)
|
|
--mRefCount;
|
|
if(!mRefCount)
|
|
PVD_DELETE(this);
|
|
}
|
|
};
|
|
}
|
|
|
|
uint32_t PvdObjectModelMetaData::getCurrentPvdObjectModelVersion()
|
|
{
|
|
return 1;
|
|
}
|
|
|
|
PvdObjectModelMetaData& PvdObjectModelMetaData::create()
|
|
{
|
|
PvdObjectModelMetaDataImpl& retval(*PVD_NEW(PvdObjectModelMetaDataImpl)());
|
|
retval.initialize();
|
|
return retval;
|
|
}
|
|
|
|
PvdObjectModelMetaData& PvdObjectModelMetaData::create(PvdInputStream& stream)
|
|
{
|
|
PvdObjectModelMetaDataImpl& retval(*PVD_NEW(PvdObjectModelMetaDataImpl)());
|
|
retval.read(stream);
|
|
return retval;
|
|
}
|
|
|
|
StringTable& StringTable::create()
|
|
{
|
|
return *PVD_NEW(StringTableImpl)();
|
|
}
|