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/framework/src/ApexSDKImpl.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/framework/src/ApexSDKImpl.cpp')
| -rw-r--r-- | APEX_1.4/framework/src/ApexSDKImpl.cpp | 2059 |
1 files changed, 2059 insertions, 0 deletions
diff --git a/APEX_1.4/framework/src/ApexSDKImpl.cpp b/APEX_1.4/framework/src/ApexSDKImpl.cpp new file mode 100644 index 00000000..c6a04972 --- /dev/null +++ b/APEX_1.4/framework/src/ApexSDKImpl.cpp @@ -0,0 +1,2059 @@ +/* + * Copyright (c) 2008-2015, NVIDIA CORPORATION. All rights reserved. + * + * NVIDIA CORPORATION and its licensors retain all intellectual property + * and proprietary rights in and to this software, 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. + */ + + +#include "Apex.h" +#include "ApexUsingNamespace.h" +#include "ApexScene.h" +#include "ApexSDKImpl.h" +#include "FrameworkPerfScope.h" +#include "ApexRenderMeshAsset.h" +#include "ApexRenderMeshActor.h" +#include "ApexRenderMeshAssetAuthoring.h" +#include "ApexResourceProvider.h" +#include "PsMemoryBuffer.h" +#include "ApexString.h" +#include "ApexDefaultStream.h" +#include "ApexRenderDebug.h" + +#include "nvparameterized/NvParameterized.h" +#include "nvparameterized/NvParamUtils.h" + +#include "PsMemoryBuffer.h" +#include "PsFoundation.h" +#include "NvDefaultTraits.h" + +#include "PsFileBuffer.h" +#include "NvSerializerInternal.h" +#include "UserOpaqueMesh.h" +#include "ApexShape.h" + +#include "ApexAssetPreviewScene.h" +#include "RenderResourceManagerWrapper.h" +#include "PsThread.h" + +#include "PxProfileEventNames.h" +#include "ApexPvdClient.h" + +#ifndef WITHOUT_PVD +#include "PvdNxParamSerializer.h" +#include "ApexStubPxProfileZone.h" +#endif + +#define MAX_MSG_SIZE 65536 +#define WITH_DEBUG_ASSET 0 + +#if PX_WINDOWS_FAMILY +#include <windows/PsWindowsInclude.h> +#include <cstdio> +#include "ModuleUpdateLoader.h" + +#include <PxPvdImpl.h> + +// We require at least Visual Studio 2010 w/ SP1 to compile +#if defined(_MSC_VER) +# if _MSC_VER >= 1900 + PX_COMPILE_TIME_ASSERT(_MSC_FULL_VER >= 190000000); +# elif _MSC_VER >= 1800 + PX_COMPILE_TIME_ASSERT(_MSC_FULL_VER >= 180000000); +# elif _MSC_VER >= 1700 + PX_COMPILE_TIME_ASSERT(_MSC_FULL_VER >= 170000000); +# elif _MSC_VER >= 1600 + PX_COMPILE_TIME_ASSERT(_MSC_FULL_VER >= 160040219); +# endif + +# if _MSC_VER > 1900 + #pragma message("Detected compiler newer than Visual Studio 2013, please update min version checking in ApexSDKImpl.cpp") + PX_COMPILE_TIME_ASSERT(_MSC_VER <= 1900); +# endif +#endif + +#endif //PX_WINDOWS_FAMILY + +#if PX_OSX +#include <mach-o/dyld.h> +#include <libproc.h> +#include <dlfcn.h> +#endif + +#if PX_X86 +#define PTR_TO_UINT64(x) ((uint64_t)(uint32_t)(x)) +#else +#define PTR_TO_UINT64(x) ((uint64_t)(x)) +#endif + +#if APEX_CUDA_SUPPORT +#include "windows/PhysXIndicator.h" +#endif + +#include "PxErrorCallback.h" +#include "PxCudaContextManager.h" +#include "PxCpuDispatcher.h" +#include "PxProfileZoneManager.h" +#ifdef PHYSX_PROFILE_SDK +#if PX_PHYSICS_VERSION_MAJOR == 3 +#include "PxPhysics.h" +#endif + +nvidia::profile::PxProfileZone *gProfileZone=NULL; + +#endif + +namespace nvidia +{ +namespace apex +{ + + +extern ApexSDKImpl* gApexSdk; + +#if defined(_USRDLL) || PX_OSX +typedef Module* (NxCreateModule_FUNC)(ApexSDKIntl*, ModuleIntl**, uint32_t, uint32_t, ApexCreateError*); +#else +/* When modules are statically linked, the user must instantiate modules manually before they can be + * created via the ApexSDK::createModule() method. Each module must supply an instantiation function. + */ +#endif + +ApexSDKImpl::ApexSDKImpl(ApexCreateError* errorCode, uint32_t /*inAPEXsdkVersion*/) + : mAuthorableObjects(NULL) + , mBatchSeedSize(128) + , mErrorString(NULL) + , mNumTempMemoriesActive(0) +#if PX_PHYSICS_VERSION_MAJOR == 0 + , mApexThreadPool(0) +#endif + , renderResourceManager(NULL) + , renderResourceManagerWrapper(NULL) + , apexResourceProvider(NULL) + , cookingVersion(0) + , mURRdepthTLSslot(0xFFFFFFFF) + , mEnableApexStats(true) + , mEnableConcurrencyCheck(false) +{ + if (errorCode) + { + *errorCode = APEX_CE_NO_ERROR; + } + +#if PX_DEBUG || PX_CHECKED + mURRdepthTLSslot = shdfnd::TlsAlloc(); +#endif +} + +AuthObjTypeID ApexRenderMeshAsset::mObjTypeID; +#include "ModuleFrameworkRegistration.h" +#include "ModuleCommonRegistration.h" + +void ModuleFramework::init(NvParameterized::Traits* t) +{ + ModuleFrameworkRegistration::invokeRegistration(t); + ModuleCommonRegistration::invokeRegistration(t); +} + +void ModuleFramework::release(NvParameterized::Traits* t) +{ + ModuleFrameworkRegistration::invokeUnregistration(t); + ModuleCommonRegistration::invokeUnregistration(t); +} + +// Many things can't be initialized in the constructor since they depend on gApexSdk +// being present. +void ApexSDKImpl::init(const ApexSDKDesc& desc) +{ + + renderResourceManager = desc.renderResourceManager; +#if PX_DEBUG || PX_CHECKED + if (renderResourceManagerWrapper != NULL) + { + PX_DELETE(renderResourceManagerWrapper); + renderResourceManagerWrapper = NULL; + } + if (renderResourceManager != NULL) + { + renderResourceManagerWrapper = PX_NEW(RenderResourceManagerWrapper)(*renderResourceManager); + } +#endif + + foundation = desc.foundation; + +#if PX_PHYSICS_VERSION_MAJOR == 3 + cooking = desc.cooking; + physXSDK = desc.physXSDK; + physXsdkVersion = desc.physXSDKVersion; +#endif + + mDllLoadPath = desc.dllLoadPath; + mCustomDllNamePostfix = desc.dllNamePostfix; + mWireframeMaterial = desc.wireframeMaterial; + mSolidShadedMaterial = desc.solidShadedMaterial; +#if PX_WINDOWS_FAMILY + mAppGuid = desc.appGuid ? desc.appGuid : DEFAULT_APP_GUID; +#endif + mRMALoadMaterialsLazily = desc.renderMeshActorLoadMaterialsLazily; + + mEnableConcurrencyCheck = desc.enableConcurrencyCheck; + + Framework::initFrameworkProfiling(this); + + apexResourceProvider = PX_NEW(ApexResourceProvider)(); + PX_ASSERT(apexResourceProvider); + apexResourceProvider->setCaseSensitivity(desc.resourceProviderIsCaseSensitive); + apexResourceProvider->registerCallback(desc.resourceCallback); + + // The param traits depend on the resource provider, so do this now + mParameterizedTraits = new NvParameterized::DefaultTraits(NvParameterized::DefaultTraits::BehaviourFlags::DEFAULT_POLICY); + GetInternalApexSDK()->getInternalResourceProvider()->createNameSpace("NvParameterizedFactories", false); + PX_ASSERT(mParameterizedTraits); + + /* create global name space of authorable asset types */ + mObjTypeNS = apexResourceProvider->createNameSpace(APEX_AUTHORABLE_ASSETS_TYPES_NAME_SPACE, false); + + /* create global name space of NvParameterized authorable asset types */ + mNxParamObjTypeNS = apexResourceProvider->createNameSpace(APEX_NV_PARAM_AUTH_ASSETS_TYPES_NAME_SPACE, false); + + /* create namespace for user materials */ + mMaterialNS = apexResourceProvider->createNameSpace(APEX_MATERIALS_NAME_SPACE, true); + + /* create namespace for user opaque meshes */ + mOpaqueMeshNS = apexResourceProvider->createNameSpace(APEX_OPAQUE_MESH_NAME_SPACE, false); + + /* create namespace for custom vertex buffer semantics */ + mCustomVBNS = apexResourceProvider->createNameSpace(APEX_CUSTOM_VB_NAME_SPACE, true); + + /* create namespace for novodex collision groups */ + mCollGroupNS = apexResourceProvider->createNameSpace(APEX_COLLISION_GROUP_NAME_SPACE, false); + + /* create namespace for 128-bit GroupsMasks */ + mCollGroup128NS = apexResourceProvider->createNameSpace(APEX_COLLISION_GROUP_128_NAME_SPACE, false); + + /* create namespace for 64-bit GroupsMasks64 */ + mCollGroup64NS = apexResourceProvider->createNameSpace(APEX_COLLISION_GROUP_64_NAME_SPACE, false); + + /* create namespace for novodex collision groups masks */ + mCollGroupMaskNS = apexResourceProvider->createNameSpace(APEX_COLLISION_GROUP_MASK_NAME_SPACE, false); + + /* create namespace for novodex Material IDs (returned by raycasts) */ + mPhysMatNS = apexResourceProvider->createNameSpace(APEX_PHYSICS_MATERIAL_NAME_SPACE, false); + + /* create namespace for RenderMeshAssets */ + mAuthorableObjects = PX_NEW(ResourceList); + RenderMeshAuthorableObject* AO = PX_NEW(RenderMeshAuthorableObject)(&frameworkModule, *mAuthorableObjects, RenderMeshAssetParameters::staticClassName()); + ApexRenderMeshAsset::mObjTypeID = AO->getResID(); + + frameworkModule.init(mParameterizedTraits); + + /* Create mDebugColorParams */ + void* newPtr = mParameterizedTraits->alloc(sizeof(DebugColorParamsEx)); + mDebugColorParams = NV_PARAM_PLACEMENT_NEW(newPtr, DebugColorParamsEx)(mParameterizedTraits, this); + + for (uint32_t i = 0 ; i < DescHashSize ; i++) + { + mPhysXObjDescHash[i] = 0; + } + mDescFreeList = 0; + + mCachedData = PX_NEW(ApexSDKCachedDataImpl); + + mBatchSeedSize = desc.physXObjDescTableAllocationIncrement; + +#if defined(PHYSX_PROFILE_SDK) + mProfileZone = 0; // &physx::profile::PxProfileZone::createProfileZone(getAllocator(), "ApexSDK"); // TODO: create a profile zone here + gProfileZone = mProfileZone; + mApexPvdClient = pvdsdk::ApexPvdClient::create(desc.pvd); +#endif +} + + +ApexSDKImpl::~ApexSDKImpl() +{ +#if PX_DEBUG || PX_CHECKED + if (mURRdepthTLSslot != 0xFFFFFFFF) + { + TlsFree(mURRdepthTLSslot); + mURRdepthTLSslot = 0xFFFFFFFF; + } +#endif + + Framework::releaseFrameworkProfiling(); +#if PHYSX_PROFILE_SDK + if ( mProfileZone ) + { + mProfileZone->release(); + mProfileZone = NULL; + } + if (mApexPvdClient != NULL) + { + mApexPvdClient->release(); + } + mApexPvdClient = NULL; +#endif +} + +ApexActor* ApexSDKImpl::getApexActor(Actor* nxactor) const +{ + AuthObjTypeID type = nxactor->getOwner()->getObjTypeID(); + if (type == ApexRenderMeshAsset::mObjTypeID) + { + return (ApexRenderMeshActor*) nxactor; + } + + ApexActor* a = NULL; + for (uint32_t i = 0; i < imodules.size(); i++) + { + a = imodules[i]->getApexActor(nxactor, type); + if (a) + { + break; + } + } + + return a; +} + +Scene* ApexSDKImpl::createScene(const SceneDesc& sceneDesc) +{ + if (!sceneDesc.isValid()) + { + return 0; + } + + ApexScene* s = PX_NEW(ApexScene)(sceneDesc, this); + mScenes.pushBack(s); + + // Trigger ModuleSceneIntl creation for all loaded modules + for (uint32_t i = 0; i < imodules.size(); i++) + { + s->moduleCreated(*imodules[i]); + } + + return s; +} + +AssetPreviewScene* ApexSDKImpl::createAssetPreviewScene() +{ + ApexAssetPreviewScene* s = PX_NEW(ApexAssetPreviewScene)(this); + + return s; +} + +void ApexSDKImpl::releaseScene(Scene* nxScene) +{ + ApexScene* scene = DYNAMIC_CAST(ApexScene*)(nxScene); + mScenes.findAndReplaceWithLast(scene); + scene->destroy(); +} + +void ApexSDKImpl::releaseAssetPreviewScene(AssetPreviewScene* nxScene) +{ + ApexAssetPreviewScene* scene = DYNAMIC_CAST(ApexAssetPreviewScene*)(nxScene); + scene->destroy(); +} + +/** Map PhysX objects back to their APEX objects, hold flags and pointers **/ + +uint16_t ApexPhysXObjectDesc::makeHash(size_t hashable) +{ + return static_cast<uint16_t>(UINT16_MAX & (hashable >> 8)); +} + + +PhysXObjectDescIntl* ApexSDKImpl::getGenericPhysXObjectInfo(const void* obj) const +{ + nvidia::Mutex::ScopedLock scopeLock(mPhysXObjDescsLock); + + uint16_t h = (uint16_t)(ApexPhysXObjectDesc::makeHash(reinterpret_cast<size_t>(obj)) & (DescHashSize - 1)); + uint32_t index = mPhysXObjDescHash[h]; + + while (index) + { + ApexPhysXObjectDesc* desc = const_cast<ApexPhysXObjectDesc*>(&mPhysXObjDescs[index]); + if ((void*) desc->mPhysXObject == obj) + { + return desc; + } + else + { + index = desc->mNext; + } + } + return NULL; +} + +#if PX_PHYSICS_VERSION_MAJOR == 3 + +PhysXObjectDescIntl* ApexSDKImpl::createObjectDesc(const Actor* apexActor, const PxActor* actor) +{ + return createObjectDesc(apexActor, (const void*) actor); +} +PhysXObjectDescIntl* ApexSDKImpl::createObjectDesc(const Actor* apexActor, const PxShape* shape) +{ + return createObjectDesc(apexActor, (const void*) shape); +} +PhysXObjectDescIntl* ApexSDKImpl::createObjectDesc(const Actor* apexActor, const PxJoint* joint) +{ + return createObjectDesc(apexActor, (const void*) joint); +} +PhysXObjectDescIntl* ApexSDKImpl::createObjectDesc(const Actor* apexActor, const PxCloth* cloth) +{ + return createObjectDesc(apexActor, (const void*)cloth); +} +PhysXObjectDescIntl* ApexSDKImpl::createObjectDesc(const Actor* apexActor, const PxParticleSystem* particleSystem) +{ + return createObjectDesc(apexActor, (const void*) particleSystem); +} +PhysXObjectDescIntl* ApexSDKImpl::createObjectDesc(const Actor* apexActor, const PxParticleFluid* particleFluid) +{ + return createObjectDesc(apexActor, (const void*)particleFluid); +} +const PhysXObjectDesc* ApexSDKImpl::getPhysXObjectInfo(const PxActor* actor) const +{ + return getGenericPhysXObjectInfo((void*)actor); +} +const PhysXObjectDesc* ApexSDKImpl::getPhysXObjectInfo(const PxShape* shape) const +{ + return getGenericPhysXObjectInfo((void*)shape); +} +const PhysXObjectDesc* ApexSDKImpl::getPhysXObjectInfo(const PxJoint* joint) const +{ + return getGenericPhysXObjectInfo((void*)joint); +} +const PhysXObjectDesc* ApexSDKImpl::getPhysXObjectInfo(const PxCloth* cloth) const +{ + return getGenericPhysXObjectInfo((void*)cloth); +} +const PhysXObjectDesc* ApexSDKImpl::getPhysXObjectInfo(const PxParticleSystem* particleSystem) const +{ + return getGenericPhysXObjectInfo((void*)particleSystem); +} +const PhysXObjectDesc* ApexSDKImpl::getPhysXObjectInfo(const PxParticleFluid* particleFluid) const +{ + return getGenericPhysXObjectInfo((void*)particleFluid); +} +PxPhysics* ApexSDKImpl::getPhysXSDK() +{ + return physXSDK; +} +PxCooking* ApexSDKImpl::getCookingInterface() +{ + return cooking; +} + +#endif + +AuthObjTypeID ApexSDKImpl::registerAuthObjType(const char* authTypeName, ResID nsid) +{ + AuthObjTypeID aotid = apexResourceProvider->createResource(mObjTypeNS, authTypeName, false); + apexResourceProvider->setResource(APEX_AUTHORABLE_ASSETS_TYPES_NAME_SPACE, + authTypeName, + (void*)(size_t) nsid, false); + return aotid; +} + +AuthObjTypeID ApexSDKImpl::registerAuthObjType(const char* authTypeName, AuthorableObjectIntl* authObjPtr) +{ + AuthObjTypeID aotid = apexResourceProvider->createResource(mObjTypeNS, authTypeName, false); + apexResourceProvider->setResource(APEX_AUTHORABLE_ASSETS_TYPES_NAME_SPACE, + authTypeName, + (void*) authObjPtr, false); + return aotid; +} + +AuthObjTypeID ApexSDKImpl::registerNvParamAuthType(const char* authTypeName, AuthorableObjectIntl* authObjPtr) +{ + AuthObjTypeID aotid = apexResourceProvider->createResource(mNxParamObjTypeNS, authTypeName, false); + apexResourceProvider->setResource(APEX_NV_PARAM_AUTH_ASSETS_TYPES_NAME_SPACE, + authTypeName, + (void*) authObjPtr, false); + return aotid; +} + +void ApexSDKImpl::unregisterAuthObjType(const char* authTypeName) +{ + apexResourceProvider->setResource(APEX_AUTHORABLE_ASSETS_TYPES_NAME_SPACE, + authTypeName, + (void*) NULL, false); +} + +void ApexSDKImpl::unregisterNvParamAuthType(const char* authTypeName) +{ + apexResourceProvider->setResource(APEX_NV_PARAM_AUTH_ASSETS_TYPES_NAME_SPACE, + authTypeName, + (void*) NULL, false); +} + +AuthorableObjectIntl* ApexSDKImpl::getAuthorableObject(const char* authTypeName) +{ + if (!apexResourceProvider->checkResource(mObjTypeNS, authTypeName)) + { + return NULL; + } + + void* ao = apexResourceProvider->getResource(APEX_AUTHORABLE_ASSETS_TYPES_NAME_SPACE, authTypeName); + + return static_cast<AuthorableObjectIntl*>(ao); +} + +AuthorableObjectIntl* ApexSDKImpl::getParamAuthObject(const char* paramName) +{ + if (!apexResourceProvider->checkResource(mNxParamObjTypeNS, paramName)) + { + return NULL; + } + + void* ao = apexResourceProvider->getResource(APEX_NV_PARAM_AUTH_ASSETS_TYPES_NAME_SPACE, paramName); + + return static_cast<AuthorableObjectIntl*>(ao); +} + +bool ApexSDKImpl::getAuthorableObjectNames(const char** authTypeNames, uint32_t& outCount, uint32_t inCount) +{ + ResID ids[128]; + + if (!apexResourceProvider->getResourceIDs(APEX_AUTHORABLE_ASSETS_TYPES_NAME_SPACE, ids, outCount, 128)) + { + return false; + } + + if (outCount > inCount) + { + return false; + } + + for (uint32_t i = 0; i < outCount; i++) + { + authTypeNames[i] = apexResourceProvider->getResourceName(ids[i]); + +#define JUST_A_TEST 0 +#if JUST_A_TEST +#include <stdio.h> + AuthorableObjectIntl* ao = (AuthorableObjectIntl*)getAuthorableObject(authTypeNames[i]); + + Asset* assetList[32]; + uint32_t retCount = 0; + ao->getAssetList(assetList, retCount, 32); + + if (retCount) + { + printf("%s count: %d\n", authTypeNames[i], retCount); + const NvParameterized::Interface* p = assetList[0]->getAssetNvParameterized(); + if (p) + { + printf(" NvParam class name: %s\n", p->className()); + } + } +#endif + } + + return true; +} + +ResID ApexSDKImpl::getApexMeshNameSpace() +{ + AuthorableObjectIntl* AO = getAuthorableObject(RENDER_MESH_AUTHORING_TYPE_NAME); + if (AO) + { + return AO->getResID(); + } + else + { + return INVALID_RESOURCE_ID; + } +} + + + +PhysXObjectDescIntl* ApexSDKImpl::createObjectDesc(const Actor* apexActor, const void* nxPtr) +{ + nvidia::Mutex::ScopedLock scopeLock(mPhysXObjDescsLock); + + uint16_t h = (uint16_t)(ApexPhysXObjectDesc::makeHash(reinterpret_cast<size_t>(nxPtr)) & (DescHashSize - 1)); + uint32_t index = mPhysXObjDescHash[ h ]; + + while (index) + { + ApexPhysXObjectDesc* desc = &mPhysXObjDescs[ index ]; + if (desc->mPhysXObject == nxPtr) + { + APEX_DEBUG_WARNING("createObjectDesc: Object already registered"); + bool hasActor = false; + for (uint32_t i = desc->mApexActors.size(); i--;) + { + if (desc->mApexActors[i] == apexActor) + { + hasActor = true; + break; + } + } + if (hasActor) + { + APEX_DEBUG_WARNING("createObjectDesc: Object already registered with the given Actor"); + } + else + { + desc->mApexActors.pushBack(apexActor); + } + return desc; + } + else + { + index = desc->mNext; + } + } + + // Match not found, allocate new object descriptor + + if (!mDescFreeList) + { + // Free list is empty, seed it with new batch + uint32_t size = mPhysXObjDescs.size(); + if (size == 0) // special initial case, reserve entry 0 + { + size = 1; + mPhysXObjDescs.resize(size + mBatchSeedSize); + } + else + { + PX_PROFILE_ZONE("objDescsResize", GetInternalApexSDK()->getContextId()); + + // Instead of doing a straight resize of mPhysXObjDescs the array is resized by swapping. Doing so removes the potential + // copying/reallocating of the arrays held in ApexPhysXObjectDesc elements which is costly performance wise. + physx::Array<ApexPhysXObjectDesc> swapArray; + swapArray.swap(mPhysXObjDescs); + + mPhysXObjDescs.resize(size + mBatchSeedSize); + ApexPhysXObjectDesc* src = swapArray.begin(); + ApexPhysXObjectDesc* dst = mPhysXObjDescs.begin(); + for (physx::PxU32 i = 0; i < size; i++) + { + src[i].swap(dst[i]); + } + } + + for (uint32_t i = size ; i < size + mBatchSeedSize ; i++) + { + mPhysXObjDescs[i].mNext = mDescFreeList; + mDescFreeList = i; + } + } + + index = mDescFreeList; + ApexPhysXObjectDesc* desc = &mPhysXObjDescs[ index ]; + mDescFreeList = desc->mNext; + + desc->mFlags = 0; + desc->userData = NULL; + desc->mApexActors.reset(); + desc->mApexActors.pushBack(apexActor); + desc->mNext = mPhysXObjDescHash[ h ]; + if (desc->mNext) + { + PX_ASSERT(mPhysXObjDescs[ desc->mNext ].mPrev == 0); + mPhysXObjDescs[ desc->mNext ].mPrev = index; + } + desc->mPrev = 0; + desc->mPhysXObject = nxPtr; + mPhysXObjDescHash[ h ] = index; + + /* Calling function can set mFlags and userData */ + + return desc; +} + +void ApexSDKImpl::releaseObjectDesc(void* physXObject) +{ + nvidia::Mutex::ScopedLock scopeLock(mPhysXObjDescsLock); + + uint16_t h = (uint16_t)(ApexPhysXObjectDesc::makeHash(reinterpret_cast<size_t>(physXObject)) & (DescHashSize - 1)); + uint32_t index = mPhysXObjDescHash[ h ]; + + while (index) + { + ApexPhysXObjectDesc* desc = &mPhysXObjDescs[ index ]; + + if (desc->mPhysXObject == physXObject) + { + if (desc->mPrev) + { + mPhysXObjDescs[ desc->mPrev ].mNext = desc->mNext; + } + else + { + mPhysXObjDescHash[ h ] = desc->mNext; + } + + if (desc->mNext) + { + mPhysXObjDescs[ desc->mNext ].mPrev = desc->mPrev; + } + + desc->mNext = mDescFreeList; + mDescFreeList = index; + + desc->mApexActors.reset(); + return; + } + else + { + index = desc->mNext; + } + } + + APEX_DEBUG_WARNING("releaseObjectDesc: Unable to release object descriptor"); +} + + +void ApexSDKImpl::releaseModule(Module* module) +{ + for (uint32_t i = 0; i < modules.size(); i++) + { + if (modules[i] != module) + { + continue; + } + + // The module will remove its ModuleScenesIntl from each Scene + mCachedData->unregisterModuleDataCache(imodules[ i ]->getModuleDataCache()); + + ModuleIntl *im = imodules[i]; + imodules[i] = NULL; + modules[i] = NULL; + im->destroy(); + +// modules.replaceWithLast(i); +// imodules.replaceWithLast(i); + + break; + } +} + +void ApexSDKImpl::registerModule(Module* newModule, ModuleIntl* newIModule) +{ + + uint32_t newIndex = modules.size(); + for (uint32_t i=0; i<newIndex; i++) + { + if ( imodules[i] == NULL ) + { + newIndex = i; + break; + } + } + if ( newIndex == modules.size() ) + { + modules.pushBack(newModule); + imodules.pushBack(newIModule); + } + + // Trigger ModuleSceneIntl creation for all existing scenes + for (uint32_t i = 0 ; i < mScenes.size(); i++) + { + (DYNAMIC_CAST(ApexScene*)(mScenes[i]))->moduleCreated(*newIModule); + } + + mCachedData->registerModuleDataCache(newIModule->getModuleDataCache()); +} + +Module* ApexSDKImpl::createModule(const char* name, ApexCreateError* err) +{ + if (err) + { + *err = APEX_CE_NO_ERROR; + } + + // Return existing module if it's already loaded + for (uint32_t i = 0; i < modules.size(); i++) + { + if ( modules[i] && !nvidia::strcmp(modules[ i ]->getName(), name)) + { + ModuleIntl *imodule = imodules[i]; + if( imodule->isCreateOk() ) + { + return modules[ i ]; + } + else + { + APEX_DEBUG_WARNING("ApexSDKImpl::createModule(%s) Not allowed.", name ); + if (err) + { + *err = APEX_CE_CREATE_NO_ALLOWED; + } + return NULL; + } + } + } + + Module* newModule = NULL; + ModuleIntl* newIModule = NULL; + +#if defined(_USRDLL) || PX_OSX + /* Dynamically linked module libraries */ + +#if defined(WIN32) + ApexSimpleString dllName = mDllLoadPath + ApexSimpleString("APEX_") + ApexSimpleString(name); +#if _DEBUG + // Request DEBUG DLL unless the user has explicitly asked for it + const size_t nameLen = strlen(name); + if (nameLen <= 5 || nvidia::strcmp(name + nameLen - 5, "DEBUG")) + { + dllName += ApexSimpleString("DEBUG"); + } +#elif PX_CHECKED + dllName += ApexSimpleString("CHECKED"); +#elif defined(PHYSX_PROFILE_SDK) + dllName += ApexSimpleString("PROFILE"); +#endif + +#if PX_X86 + dllName += ApexSimpleString("_x86"); +#elif PX_X64 + dllName += ApexSimpleString("_x64"); +#endif + + dllName += mCustomDllNamePostfix; + + dllName += ApexSimpleString(".dll"); + + HMODULE library = NULL; + { + ModuleUpdateLoader moduleLoader(UPDATE_LOADER_DLL_NAME); + library = moduleLoader.loadModule(dllName.c_str(), getAppGuid()); + + if (NULL == library) + { + dllName = ApexSimpleString("APEX/") + dllName; + library = moduleLoader.loadModule(dllName.c_str(), getAppGuid()); + } + } + + if (library) + { + NxCreateModule_FUNC* createModuleFunc = (NxCreateModule_FUNC*) GetProcAddress(library, "createModule"); + if (createModuleFunc) + { + newModule = createModuleFunc((ApexSDKIntl*) this, + &newIModule, + APEX_SDK_VERSION, + PX_PHYSICS_VERSION, + err); + } + } +#elif PX_OSX + ApexSimpleString dylibName = ApexSimpleString("libAPEX_") + ApexSimpleString(name); + +#if _DEBUG + // Request DEBUG DLL unless the user has explicitly asked for it + const size_t nameLen = strlen(name); + if (nameLen <= 5 || nvidia::strcmp(name + nameLen - 5, "DEBUG")) + { + dylibName += ApexSimpleString("DEBUG"); + } +#elif PX_CHECKED + dylibName += ApexSimpleString("CHECKED"); +#elif defined(PHYSX_PROFILE_SDK) + dylibName += ApexSimpleString("PROFILE"); +#endif + + dylibName += mCustomDllNamePostfix; + + dylibName += ApexSimpleString(".dylib"); + + ApexSimpleString dylibPath = mDllLoadPath + dylibName; + + void* library = NULL; + { + // Check if dylib is already loaded + library = dlopen(dylibPath.c_str(), RTLD_NOLOAD | RTLD_LAZY | RTLD_LOCAL); + if (!library) + { + library = dlopen((ApexSimpleString("@rpath/") + dylibName).c_str(), RTLD_NOLOAD | RTLD_LAZY | RTLD_LOCAL); + } + if (!library) + { + // Not loaded yet, so try to open it + library = dlopen(dylibPath.c_str(), RTLD_LAZY | RTLD_LOCAL); + } + } + + if (library) + { + NxCreateModule_FUNC* createModuleFunc = (NxCreateModule_FUNC*)dlsym(library, "createModule"); + if (createModuleFunc) + { + newModule = createModuleFunc((ApexSDKIntl*) this, + &newIModule, + APEX_SDK_VERSION, + PX_PHYSICS_VERSION, + err); + } + } +#else + /* TODO: other platform dynamic linking? */ +#endif + +#else + /* Statically linked module libraries */ + + /* Modules must supply an instantiation function which calls ApexSDKIntl::registerModule() + * The user must call this function after creating ApexSDKImpl and before createModule(). + */ +#endif + + // register new module and its parameters + if (newModule) + { + registerModule(newModule, newIModule); + } + else if (err) + { + *err = APEX_CE_NOT_FOUND; + } + + return newModule; +} + +ModuleIntl* ApexSDKImpl::getInternalModuleByName(const char* name) +{ + // Return existing module if it's already loaded + for (uint32_t i = 0; i < modules.size(); i++) + { + if (!nvidia::strcmp(modules[ i ]->getName(), name)) + { + return imodules[ i ]; + } + } + return NULL; +} + +PxFileBuf* ApexSDKImpl::createStream(const char* filename, PxFileBuf::OpenMode mode) +{ + return PX_NEW(PsFileBuffer)(filename, mode); +} + +// deprecated, use getErrorCallback instead +PxErrorCallback* ApexSDKImpl::getOutputStream() +{ + return getErrorCallback(); +} + +PxFoundation* ApexSDKImpl::getFoundation() const +{ + return foundation; +} + +PxErrorCallback* ApexSDKImpl::getErrorCallback() const +{ + PX_ASSERT(foundation); + return &foundation->getErrorCallback(); +} + +PxAllocatorCallback* ApexSDKImpl::getAllocator() const +{ + PX_ASSERT(foundation); + return &foundation->getAllocatorCallback(); +} + +ResourceProvider* ApexSDKImpl::getNamedResourceProvider() +{ + return apexResourceProvider; +} + +ResourceProviderIntl* ApexSDKImpl::getInternalResourceProvider() +{ + return apexResourceProvider; +} + +uint32_t ApexSDKImpl::getNbModules() +{ + uint32_t moduleCount = 0; + for (uint32_t i=0; i<modules.size(); i++) + { + if (modules[i] != NULL) + { + moduleCount++; + } + } + + return moduleCount; +} + +Module** ApexSDKImpl::getModules() +{ + if (modules.size() > 0) + { + moduleListForAPI.resize(0); + for (uint32_t i=0; i<modules.size(); i++) + { + if (modules[i] != NULL) + { + moduleListForAPI.pushBack(modules[i]); + } + } + + return &moduleListForAPI.front(); + } + else + { + return NULL; + } +} + + +ModuleIntl** ApexSDKImpl::getInternalModules() +{ + if (imodules.size() > 0) + { + return &imodules.front(); + } + else + { + return NULL; + } +} + +uint32_t ApexSDKImpl::forceLoadAssets() +{ + uint32_t loadedAssetCount = 0; + + // handle render meshes, since they don't live in a module + if (mAuthorableObjects != NULL) + { + for (uint32_t i = 0; i < mAuthorableObjects->getSize(); i++) + { + AuthorableObjectIntl* ao = static_cast<AuthorableObjectIntl*>(mAuthorableObjects->getResource(i)); + loadedAssetCount += ao->forceLoadAssets(); + } + } + + for (uint32_t i = 0; i < imodules.size(); i++) + { + loadedAssetCount += imodules[i]->forceLoadAssets(); + } + + return loadedAssetCount; +} + + +void ApexSDKImpl::debugAsset(Asset* asset, const char* name) +{ + PX_UNUSED(asset); + PX_UNUSED(name); +#if WITH_DEBUG_ASSET + if (asset) + { + const NvParameterized::Interface* pm = asset->getAssetNvParameterized(); + if (pm) + { + NvParameterized::Serializer* s1 = internalCreateSerializer(NvParameterized::Serializer::NST_XML, mParameterizedTraits); + NvParameterized::Serializer* s2 = internalCreateSerializer(NvParameterized::Serializer::NST_BINARY, mParameterizedTraits); + if (s1 && s2) + { + nvidia::PsMemoryBuffer mb1; + nvidia::PsMemoryBuffer mb2; + s1->serialize(mb1, &pm, 1); + s2->serialize(mb2, &pm, 1); + { + char scratch[512]; + nvidia::strlcpy(scratch, 512, name); + char* dot = NULL; + char* scan = scratch; + while (*scan) + { + if (*scan == '/') + { + *scan = '_'; + } + if (*scan == '\\') + { + *scan = '_'; + } + if (*scan == '.') + { + dot = scan; + } + scan++; + } + + if (dot) + { + *dot = 0; + } + + nvidia::strlcat(scratch, 512, ".apx"); + FILE* fph = fopen(scratch, "wb"); + if (fph) + { + fwrite(mb1.getWriteBuffer(), mb1.getWriteBufferSize(), 1, fph); + fclose(fph); + } + if (dot) + { + *dot = 0; + } + + nvidia::strlcat(scratch, 512, ".apb"); + fph = fopen(scratch, "wb"); + if (fph) + { + fwrite(mb2.getWriteBuffer(), mb2.getWriteBufferSize(), 1, fph); + fclose(fph); + } + + } + s1->release(); + s2->release(); + } + } + } +#endif +} + +/** + * checkAssetName + * -If name is NULL, we'll autogenerate one that won't collide with other names and issue a warning + * -If name collides with another name, we'll issue a warning and return NULL, so as not to confuse the + * user by creating an asset authoring with a name that's different from the name specified. + */ +const char* ApexSDKImpl::checkAssetName(AuthorableObjectIntl& ao, const char* inName, ApexSimpleString& autoNameStorage) +{ + ResourceProviderIntl* iNRP = getInternalResourceProvider(); + + if (!inName) + { + autoNameStorage = ao.getName(); + iNRP->generateUniqueName(ao.getResID(), autoNameStorage); + + APEX_DEBUG_INFO("No name provided for asset, auto-naming <%s>.", autoNameStorage.c_str()); + return autoNameStorage.c_str(); + } + + if (iNRP->checkResource(ao.getResID(), inName)) + { + // name collides with another asset [author] + APEX_DEBUG_WARNING("Name provided collides with another asset in the %s namespace: <%s>, no asset created.", ao.getName().c_str(), inName); + + return NULL; + } + + return inName; +} + +/** + * createAsset + * This method will load *any* APEX asset. + * 1. Read the APEX serialization header + * 2. Determine the correct module + * 3. Pass the remainder of the stream to the module along with the asset type name and asset version + */ + +Asset* ApexSDKImpl::createAsset(AssetAuthoring& nxAssetAuthoring, const char* name) +{ + Asset* ret = NULL; + AuthorableObjectIntl* ao = getAuthorableObject(nxAssetAuthoring.getObjTypeName()); + if (ao) + { + ApexSimpleString autoName; + name = checkAssetName(*ao, name, autoName); + if (!name) + { + return NULL; + } + + ret = ao->createAsset(nxAssetAuthoring, name); + } + else + { + APEX_INTERNAL_ERROR("Unknown authorable type: %s, please load all required modules.", nxAssetAuthoring.getObjTypeName()); + } + debugAsset(ret, name); + return ret; +} + +Asset* ApexSDKImpl::createAsset(NvParameterized::Interface* params, const char* name) +{ + Asset* ret = NULL; + // params->className() will tell us the name of the parameterized struct + // there is a mapping of parameterized structs to + PX_ASSERT(params); + if (params) + { + AuthorableObjectIntl* ao = getParamAuthObject(params->className()); + if (ao) + { + ApexSimpleString autoName; + name = checkAssetName(*ao, name, autoName); + if (!name) + { + return NULL; + } + + ret = ao->createAsset(params, name); + } + else + { + APEX_INTERNAL_ERROR("Unknown authorable type: %s, please load all required modules.", params->className()); + } + } + debugAsset(ret, name); + return ret; +} + +AssetAuthoring* ApexSDKImpl::createAssetAuthoring(const char* aoTypeName) +{ + AuthorableObjectIntl* ao = getAuthorableObject(aoTypeName); + if (ao) + { + ApexSimpleString autoName; + const char* name = 0; + name = checkAssetName(*ao, name, autoName); + if (!name) + { + return NULL; + } + + + return ao->createAssetAuthoring(name); + } + else + { + APEX_INTERNAL_ERROR("Unknown authorable type: %s, please load all required modules.", aoTypeName); + } + + return NULL; +} + +AssetAuthoring* ApexSDKImpl::createAssetAuthoring(const char* aoTypeName, const char* name) +{ + AuthorableObjectIntl* ao = getAuthorableObject(aoTypeName); + if (ao) + { + ApexSimpleString autoName; + name = checkAssetName(*ao, name, autoName); + if (!name) + { + return NULL; + } + + return ao->createAssetAuthoring(name); + } + else + { + APEX_INTERNAL_ERROR("Unknown authorable type: %s, please load all required modules.", aoTypeName); + } + + return NULL; +} + +AssetAuthoring* ApexSDKImpl::createAssetAuthoring(NvParameterized::Interface* params, const char* name) +{ + PX_ASSERT(params); + if (!params) + { + APEX_DEBUG_WARNING("NULL NvParameterized Interface, no asset author created."); + return NULL; + } + + AuthorableObjectIntl* ao = getParamAuthObject(params->className()); + if (ao) + { + ApexSimpleString autoName; + name = checkAssetName(*ao, name, autoName); + if (!name) + { + return NULL; + } + + return ao->createAssetAuthoring(params, name); + } + else + { + APEX_INTERNAL_ERROR("Unknown authorable type: %s, please load all required modules.", params->className()); + } + + return NULL; +} + +/** + * releaseAsset + * + */ +void ApexSDKImpl::releaseAsset(Asset& nxasset) +{ + AuthorableObjectIntl* ao = getAuthorableObject(nxasset.getObjTypeName()); + if (ao) + { + return ao->releaseAsset(nxasset); + } + else + { + APEX_INTERNAL_ERROR("Unknown authorable type: %s, please load all required modules.", nxasset.getObjTypeName()); + } +} + +void ApexSDKImpl::releaseAssetAuthoring(AssetAuthoring& nxAssetAuthoring) +{ + AuthorableObjectIntl* ao = getAuthorableObject(nxAssetAuthoring.getObjTypeName()); + if (ao) + { + return ao->releaseAssetAuthoring(nxAssetAuthoring); + } + else + { + APEX_INTERNAL_ERROR("Unknown authorable type: %s, please load all required modules.", nxAssetAuthoring.getObjTypeName()); + } +} + +void ApexSDKImpl::reportError(PxErrorCode::Enum code, const char* file, int line, const char* functionName, const char* msgFormat, ...) +{ + mReportErrorLock.lock(); + + if (gApexSdk) + { + if (getErrorCallback()) + { + if (mErrorString == NULL && code != PxErrorCode::eOUT_OF_MEMORY) + { + mErrorString = (char*) PX_ALLOC(sizeof(char) * MAX_MSG_SIZE, PX_DEBUG_EXP("char")); + } + if (mErrorString != NULL) + { + va_list va; + va_start(va, msgFormat); + + size_t tempLength = 0; + if (functionName != NULL) + { + shdfnd::snprintf(mErrorString,MAX_MSG_SIZE, "%s: ", functionName); + tempLength = strlen(mErrorString); + } + + vsprintf(mErrorString + tempLength, msgFormat, va); + va_end(va); + getErrorCallback()->reportError(code, mErrorString, file, line); + } + else + { + // we can't allocate any memory anymore, let's hope the stack has still a bit of space + char buf[ 100 ]; + va_list va; + va_start(va, msgFormat); + vsprintf(buf, msgFormat, va); + va_end(va); + getErrorCallback()->reportError(code, buf, file, line); + } + } + } + mReportErrorLock.unlock(); +} + + + +void* ApexSDKImpl::getTempMemory(uint32_t size) +{ + mTempMemoryLock.lock(); + + if (size == 0 || mTempMemories.size() > 100) //later growing a size 0 allocation is not handled gracefully! + { + // this is most likely a leak in temp memory consumption + mTempMemoryLock.unlock(); + return NULL; + } + + // now find the smallest one that is bigger than 'size' + int32_t found = -1; + uint32_t bestSize = 0; + for (uint32_t i = mNumTempMemoriesActive; i < mTempMemories.size(); i++) + { + if (mTempMemories[i].size >= size) + { + if (found == -1 || bestSize > mTempMemories[i].size) + { + found = (int32_t)i; + bestSize = mTempMemories[i].size; + } + } + } + + TempMemory result; + + if (found != -1) + { + // found + if ((uint32_t)found > mNumTempMemoriesActive) + { + // swap them + TempMemory temp = mTempMemories[mNumTempMemoriesActive]; + mTempMemories[mNumTempMemoriesActive] = mTempMemories[(uint32_t)found]; + mTempMemories[(uint32_t)found] = temp; + } + PX_ASSERT(mTempMemories[mNumTempMemoriesActive].used == 0); + mTempMemories[mNumTempMemoriesActive].used = size; + result = mTempMemories[mNumTempMemoriesActive]; + mNumTempMemoriesActive++; + } + else if (mNumTempMemoriesActive < mTempMemories.size()) + { + // not found, use last one + + // swap + TempMemory temp = mTempMemories.back(); + mTempMemories.back() = mTempMemories[mNumTempMemoriesActive]; + + void* nb = PX_ALLOC(size, PX_DEBUG_EXP("ApexSDKImpl::getTempMemory")); + if (nb) + { + memcpy(nb, temp.memory, PxMin(temp.size, size)); + } + PX_FREE(temp.memory); + temp.memory = nb; + temp.size = size; + PX_ASSERT(temp.used == 0); + temp.used = size; + + mTempMemories[mNumTempMemoriesActive] = temp; + result = temp; + mNumTempMemoriesActive++; + } + else + { + mNumTempMemoriesActive++; + TempMemory& newTemp = mTempMemories.insert(); + newTemp.memory = PX_ALLOC(size, PX_DEBUG_EXP("ApexSDKImpl::getTempMemory")); + newTemp.size = size; + newTemp.used = size; + result = newTemp; + } + mTempMemoryLock.unlock(); + +#ifdef _DEBUG + if (result.used < result.size) + { + memset((char*)result.memory + result.used, 0xfd, result.size - result.used); + } +#endif + + return result.memory; +} + + +void ApexSDKImpl::releaseTempMemory(void* data) +{ + if (data == NULL) //this is a valid consequence of permittion 0 sized allocations. + { + return; + } + + mTempMemoryLock.lock(); + uint32_t numReleased = 0; + + for (uint32_t i = 0; i < mNumTempMemoriesActive; i++) + { + if (mTempMemories[i].memory == data) + { + PX_ASSERT(mTempMemories[i].used > 0); +#ifdef _DEBUG + if (mTempMemories[i].used < mTempMemories[i].size) + { + for (uint32_t j = mTempMemories[i].used; j < mTempMemories[i].size; j++) + { + unsigned char cur = ((unsigned char*)mTempMemories[i].memory)[j]; + if (cur != 0xfd) + { + PX_ASSERT(cur == 0xfd); + break; // only hit this assert once per error + } + } + } + // you should not operate on data that has been released! + memset(mTempMemories[i].memory, 0xcd, mTempMemories[i].size); +#endif + mTempMemories[i].used = 0; + + // swap with last valid one + if (i < mNumTempMemoriesActive - 1) + { + TempMemory temp = mTempMemories[mNumTempMemoriesActive - 1]; + mTempMemories[mNumTempMemoriesActive - 1] = mTempMemories[i]; + mTempMemories[i] = temp; + } + mNumTempMemoriesActive--; + + numReleased++; + break; + } + } + + PX_ASSERT(numReleased == 1); + + mTempMemoryLock.unlock(); +} + + +void ApexSDKImpl::release() +{ + if (renderResourceManagerWrapper != NULL) + { + PX_DELETE(renderResourceManagerWrapper); + renderResourceManagerWrapper = NULL; + } + + for (uint32_t i = 0; i < mScenes.size(); i++) + { + (DYNAMIC_CAST(ApexScene*)(mScenes[ i ]))->destroy(); + } + mScenes.clear(); + + // Notify all modules that the ApexSDKImpl is getting destructed + for (uint32_t i = 0; i < modules.size(); i++) + { + if ( imodules[i] ) + { + imodules[ i ]->notifyReleaseSDK(); + } + } + + // Now we destroy each module; but we make sure to null out each array element before we call the + // actual destruction routine so that the array of avlie/registered modules contains no pointers to deleted objects + for (uint32_t i = 0; i < modules.size(); i++) + { + ModuleIntl *d = imodules[i]; + imodules[i] = NULL; + modules[i] = NULL; + if ( d ) + { + d->destroy(); + } + } + modules.clear(); + imodules.clear(); + + /* Free all render meshes created from the SDK, release named resources */ + if (mAuthorableObjects != NULL) + { + PX_DELETE(mAuthorableObjects); + mAuthorableObjects = NULL; + } + + if (mDebugColorParams) + { + mDebugColorParams->destroy(); + mDebugColorParams = NULL; + } + + frameworkModule.release(mParameterizedTraits); + + delete mParameterizedTraits; + mParameterizedTraits = 0; + + apexResourceProvider->destroy(); + apexResourceProvider = 0; + + + mPhysXObjDescs.clear(); + + for (uint32_t i = 0; i < mTempMemories.size(); i++) + { + if (mTempMemories[i].memory != NULL) + { + PX_FREE(mTempMemories[i].memory); + mTempMemories[i].memory = NULL; + mTempMemories[i].size = 0; + } + } + mTempMemories.clear(); + + PX_DELETE(mCachedData); + mCachedData = NULL; + + if (mErrorString) + { + PX_FREE_AND_RESET(mErrorString); + } + +#if PX_PHYSICS_VERSION_MAJOR == 0 + if (mApexThreadPool) + { + PX_DELETE(mApexThreadPool); + mApexThreadPool = NULL; + } + while (mUserAllocThreadPools.size()) + { + releaseCpuDispatcher(*mUserAllocThreadPools[0]); + } +#endif + + delete this; + // be very careful what goes below this line! + + gApexSdk = NULL; + +} + +RenderDebugInterface* ApexSDKImpl::createApexRenderDebug(RENDER_DEBUG::RenderDebugInterface* interface, bool useRemoteDebugVisualization) +{ + PX_UNUSED(useRemoteDebugVisualization); + +#ifdef WITHOUT_DEBUG_VISUALIZE + return NULL; + +#else + + return nvidia::apex::createApexRenderDebug(this, interface, useRemoteDebugVisualization); +#endif +} + +void ApexSDKImpl::releaseApexRenderDebug(RenderDebugInterface& debug) +{ +#ifdef WITHOUT_DEBUG_VISUALIZE + PX_UNUSED(debug); +#else + debug.release(); +#endif +} + +SphereShape* ApexSDKImpl::createApexSphereShape() +{ + ApexSphereShape* m = PX_NEW(ApexSphereShape); + return static_cast< SphereShape*>(m); +} + +CapsuleShape* ApexSDKImpl::createApexCapsuleShape() +{ + ApexCapsuleShape* m = PX_NEW(ApexCapsuleShape); + return static_cast< CapsuleShape*>(m); +} + +BoxShape* ApexSDKImpl::createApexBoxShape() +{ + ApexBoxShape* m = PX_NEW(ApexBoxShape); + return static_cast< BoxShape*>(m); +} + +HalfSpaceShape* ApexSDKImpl::createApexHalfSpaceShape() +{ + ApexHalfSpaceShape* m = PX_NEW(ApexHalfSpaceShape); + return static_cast< HalfSpaceShape*>(m); +} + +void ApexSDKImpl::releaseApexShape(Shape& shape) +{ + shape.releaseApexShape(); +} + +const char* ApexSDKImpl::getWireframeMaterial() +{ + return mWireframeMaterial.c_str(); +} + +const char* ApexSDKImpl::getSolidShadedMaterial() +{ + return mSolidShadedMaterial.c_str(); +} + +pvdsdk::ApexPvdClient* ApexSDKImpl::getApexPvdClient() +{ +#if defined(PHYSX_PROFILE_SDK) + return mApexPvdClient; +#else + return NULL; +#endif +} + +profile::PxProfileZone * ApexSDKImpl::getProfileZone() +{ +#if defined(PHYSX_PROFILE_SDK) + return mProfileZone; +#else + return NULL; +#endif +} + +profile::PxProfileZoneManager * ApexSDKImpl::getProfileZoneManager() +{ +#if defined(PHYSX_PROFILE_SDK) + return mProfileZone ? mProfileZone->getProfileZoneManager() : NULL; +#else + return NULL; +#endif +} + +#if PX_WINDOWS_FAMILY +const char* ApexSDKImpl::getAppGuid() +{ + return mAppGuid.c_str(); +} +#endif + +#if APEX_CUDA_SUPPORT +PhysXGpuIndicator* ApexSDKImpl::registerPhysXIndicatorGpuClient() +{ + //allocate memory for the PhysXGpuIndicator + PhysXGpuIndicator* gpuIndicator = static_cast<PhysXGpuIndicator*>(PX_ALLOC(sizeof(PhysXGpuIndicator), PX_DEBUG_EXP("PhysXGpuIndicator"))); + PX_PLACEMENT_NEW(gpuIndicator, PhysXGpuIndicator); + + gpuIndicator->gpuOn(); + return gpuIndicator; +} + +void ApexSDKImpl::unregisterPhysXIndicatorGpuClient(PhysXGpuIndicator* gpuIndicator) +{ + if (gpuIndicator != NULL) + { + gpuIndicator->~PhysXGpuIndicator(); + PX_FREE(gpuIndicator); + } +} +#endif + +void ApexSDKImpl::updateDebugColorParams(const char* color, uint32_t val) +{ + for (uint32_t i = 0; i < mScenes.size(); i++) + { + DYNAMIC_CAST(ApexScene*)(mScenes[ i ])->updateDebugColorParams(color, val); + } +} + + +bool ApexSDKImpl::getRMALoadMaterialsLazily() +{ + return mRMALoadMaterialsLazily; +} + +/////////////////////////////////////////////////////////////////////////////// +// ApexRenderMeshAssetAuthoring +/////////////////////////////////////////////////////////////////////////////// + + +Asset* RenderMeshAuthorableObject::createAsset(AssetAuthoring& author, const char* name) +{ + NvParameterized::Interface* newObj = NULL; + author.getNvParameterized()->clone(newObj); + return createAsset(newObj, name); +} + +Asset* RenderMeshAuthorableObject::createAsset(NvParameterized::Interface* params, const char* name) +{ + ApexRenderMeshAsset* asset = PX_NEW(ApexRenderMeshAsset)(mAssets, name, 0); + if (asset) + { + asset->createFromParameters((RenderMeshAssetParameters*)params); + GetInternalApexSDK()->getNamedResourceProvider()->setResource(mAOTypeName.c_str(), name, asset); + } + return asset; +} + +void RenderMeshAuthorableObject::releaseAsset(Asset& nxasset) +{ + ApexRenderMeshAsset* aa = DYNAMIC_CAST(ApexRenderMeshAsset*)(&nxasset); + GetInternalApexSDK()->getInternalResourceProvider()->setResource(ApexRenderMeshAsset::getClassName(), nxasset.getName(), NULL, false, false); + aa->destroy(); +} + +// this should no longer be called now that we're auto-assigning names in createAssetAuthoring() +AssetAuthoring* RenderMeshAuthorableObject::createAssetAuthoring() +{ + return createAssetAuthoring(""); +} + +AssetAuthoring* RenderMeshAuthorableObject::createAssetAuthoring(NvParameterized::Interface* params, const char* name) +{ +#ifdef WITHOUT_APEX_AUTHORING + PX_UNUSED(params); + PX_UNUSED(name); + return NULL; +#else + ApexRenderMeshAssetAuthoring* assetAuthor = PX_NEW(ApexRenderMeshAssetAuthoring)(mAssetAuthors, (RenderMeshAssetParameters*)params, name); + if (assetAuthor) + { + GetInternalApexSDK()->getNamedResourceProvider()->setResource(mAOTypeName.c_str(), name, assetAuthor); + } + return assetAuthor; + +#endif +} + +AssetAuthoring* RenderMeshAuthorableObject::createAssetAuthoring(const char* name) +{ +#ifdef WITHOUT_APEX_AUTHORING + PX_UNUSED(name); + return NULL; +#else + NvParameterized::Traits* traits = GetInternalApexSDK()->getParameterizedTraits(); + RenderMeshAssetParameters* params = (RenderMeshAssetParameters*)traits->createNvParameterized(RenderMeshAssetParameters::staticClassName()); + ApexRenderMeshAssetAuthoring* assetAuthor = PX_NEW(ApexRenderMeshAssetAuthoring)(mAssetAuthors, params, name); + if (assetAuthor) + { + GetInternalApexSDK()->getNamedResourceProvider()->setResource(mAOTypeName.c_str(), name, assetAuthor); + } + return assetAuthor; + +#endif +} + +void RenderMeshAuthorableObject::releaseAssetAuthoring(AssetAuthoring& nxauthor) +{ +#ifdef WITHOUT_APEX_AUTHORING + PX_UNUSED(nxauthor); +#else + ApexRenderMeshAssetAuthoring* aa = DYNAMIC_CAST(ApexRenderMeshAssetAuthoring*)(&nxauthor); + GetInternalApexSDK()->getInternalResourceProvider()->setResource(mAOTypeName.c_str(), aa->getName(), NULL, false, false); + + aa->destroy(); +#endif +} + + +uint32_t RenderMeshAuthorableObject::forceLoadAssets() +{ + uint32_t loadedAssetCount = 0; + + for (uint32_t i = 0; i < mAssets.getSize(); i++) + { + ApexRenderMeshAsset* asset = DYNAMIC_CAST(ApexRenderMeshAsset*)(mAssets.getResource(i)); + loadedAssetCount += asset->forceLoadAssets(); + } + return loadedAssetCount; +} + + +// Resource methods +void RenderMeshAuthorableObject::release() +{ + // test this by releasing the module before the individual assets + + // remove all assets that we loaded (must do now else we cannot unregister) + mAssets.clear(); + mAssetAuthors.clear(); + + // remove this AO's name from the authorable namespace + GetInternalApexSDK()->unregisterAuthObjType(mAOTypeName.c_str()); + destroy(); +} + +void RenderMeshAuthorableObject::destroy() +{ + delete this; +} + + +/** +Returns a PxFileBuf which reads from a buffer in memory. +*/ +PxFileBuf* ApexSDKImpl::createMemoryReadStream(const void* mem, uint32_t len) +{ + PxFileBuf* ret = 0; + + nvidia::PsMemoryBuffer* rb = PX_NEW(nvidia::PsMemoryBuffer)((const uint8_t*)mem, len); + ret = static_cast< PxFileBuf*>(rb); + + return ret; +} + +/** +Returns a PxFileBuf which writes to memory. +*/ +PxFileBuf* ApexSDKImpl::createMemoryWriteStream(uint32_t alignment) +{ + PxFileBuf* ret = 0; + + nvidia::PsMemoryBuffer* mb = PX_NEW(nvidia::PsMemoryBuffer)(nvidia::BUFFER_SIZE_DEFAULT, alignment); + ret = static_cast< PxFileBuf*>(mb); + + return ret; +} + +/** +Returns the address and length of the contents of a memory write buffer stream. +*/ +const void* ApexSDKImpl::getMemoryWriteBuffer(PxFileBuf& stream, uint32_t& len) +{ + const void* ret = 0; + + nvidia::PsMemoryBuffer* wb = static_cast< nvidia::PsMemoryBuffer*>(&stream); + len = wb->getWriteBufferSize(); + ret = wb->getWriteBuffer(); + + return ret; +} + +/** +Releases a previously created PxFileBuf used as a write or read buffer. +*/ +void ApexSDKImpl::releaseMemoryReadStream(PxFileBuf& stream) +{ + nvidia::PsMemoryBuffer* rb = static_cast< nvidia::PsMemoryBuffer*>(&stream); + delete rb; +} + +void ApexSDKImpl::releaseMemoryWriteStream(PxFileBuf& stream) +{ + nvidia::PsMemoryBuffer* wb = static_cast< nvidia::PsMemoryBuffer*>(&stream); + delete wb; +} + + +NvParameterized::Serializer* ApexSDKImpl::createSerializer(NvParameterized::Serializer::SerializeType type) +{ + return NvParameterized::internalCreateSerializer(type, mParameterizedTraits); +} + +NvParameterized::Serializer* ApexSDKImpl::createSerializer(NvParameterized::Serializer::SerializeType type, NvParameterized::Traits* traits) +{ + return NvParameterized::internalCreateSerializer(type, traits); +} + +NvParameterized::Serializer::SerializeType ApexSDKImpl::getSerializeType(const void* data, uint32_t dlen) +{ + PsMemoryBuffer stream(data, dlen); + return NvParameterized::Serializer::peekSerializeType(stream); +} + +NvParameterized::Serializer::SerializeType ApexSDKImpl::getSerializeType(PxFileBuf& stream) +{ + return NvParameterized::Serializer::peekSerializeType(stream); +} + +NvParameterized::Serializer::ErrorType ApexSDKImpl::getSerializePlatform(const void* data, uint32_t dlen, NvParameterized::SerializePlatform& platform) +{ + if (dlen < 56) + { + APEX_INVALID_PARAMETER("At least 56 Bytes are needed to read the platform of a binary file"); + } + + PsMemoryBuffer stream(data, dlen); + return NvParameterized::Serializer::peekPlatform(stream, platform); +} + +NvParameterized::Serializer::ErrorType ApexSDKImpl::getSerializePlatform(PxFileBuf& stream, NvParameterized::SerializePlatform& platform) +{ + return NvParameterized::Serializer::peekPlatform(stream, platform); +} + +void ApexSDKImpl::getCurrentPlatform(NvParameterized::SerializePlatform& platform) const +{ + platform = NvParameterized::GetCurrentPlatform(); +} + +bool ApexSDKImpl::getPlatformFromString(const char* name, NvParameterized::SerializePlatform& platform) const +{ + return NvParameterized::GetPlatform(name, platform); +} + +const char* ApexSDKImpl::getPlatformName(const NvParameterized::SerializePlatform& platform) const +{ + return NvParameterized::GetPlatformName(platform); +} + +Asset* ApexSDKImpl::createAsset(const char* opaqueMeshName, UserOpaqueMesh* om) +{ + Asset* ret = NULL; + NvParameterized::Interface* params = getParameterizedTraits()->createNvParameterized(RenderMeshAssetParameters::staticClassName()); + if (params) + { + ret = this->createAsset(params, opaqueMeshName); + if (ret) + { + NvParameterized::setParamBool(*params, "isReferenced", false); + ApexRenderMeshAsset* nrma = static_cast<ApexRenderMeshAsset*>(ret); + nrma->setOpaqueMesh(om); + } + else + { + params->destroy(); + } + } + return ret; +} + +ModuleIntl *ApexSDKImpl::getInternalModule(Module *module) +{ + ModuleIntl *ret = NULL; + + for (uint32_t i = 0; i < modules.size(); i++) + { + if ( modules[ i ] == module ) + { + ret = imodules[i]; + break; + } + } + + return ret; +} + +Module *ApexSDKImpl::getModule(ModuleIntl *module) +{ + Module *ret = NULL; + + for (uint32_t i = 0; i < imodules.size(); i++) + { + if ( imodules[ i ] == module ) + { + ret = modules[i]; + break; + } + } + + return ret; +} + + +void ApexSDKImpl::enterURR() +{ + if (mURRdepthTLSslot != 0xFFFFFFFF) + { + uint64_t currentDepth = PTR_TO_UINT64(TlsGet(mURRdepthTLSslot)); + ++currentDepth; + TlsSet(mURRdepthTLSslot, (void*)currentDepth); + } +} + + +void ApexSDKImpl::leaveURR() +{ + if (mURRdepthTLSslot != 0xFFFFFFFF) + { + uint64_t currentDepth = PTR_TO_UINT64(TlsGet(mURRdepthTLSslot)); + if (currentDepth > 0) + { + --currentDepth; + TlsSet(mURRdepthTLSslot, (void*)currentDepth); + } + else + { + // if this is hit, something is wrong with the + // URR_SCOPE implementation + PX_ALWAYS_ASSERT(); + } + } +} + + +void ApexSDKImpl::checkURR() +{ + if (mURRdepthTLSslot != 0xFFFFFFFF) + { + uint64_t currentDepth = PTR_TO_UINT64(TlsGet(mURRdepthTLSslot)); + if (currentDepth == 0) + { + // if this assert is hit it means that + // - either some render resources are created where it's not allowed + // (outside of updateRenderResources or prepareRenderResources) + // => change the place in code where the resource is created + // + // - or the updateRenderResources call is not marked with a URR_SCOPE. + // => add the macro + PX_ALWAYS_ASSERT(); + } + } +} + +} +} // end namespace nvidia::apex |