feat(physics): wire physx sdk into build

This commit is contained in:
2026-04-15 12:22:15 +08:00
parent 5bf258df6d
commit 31f40e2cbb
2044 changed files with 752623 additions and 1 deletions

View File

@@ -0,0 +1,172 @@
// 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-2025 NVIDIA Corporation. All rights reserved.
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
#include "foundation/windows/PxWindowsInclude.h"
#include "foundation/PxAtomic.h"
namespace physx
{
PxI32 PxAtomicExchange(volatile PxI32* val, PxI32 val2)
{
return (PxI32)InterlockedExchange((volatile LONG*)val, (LONG)val2);
}
PxI64 PxAtomicExchange(volatile PxI64* val, PxI64 val2)
{
return (PxI64)InterlockedExchange64((volatile LONG64*)val, (LONG64)val2);
}
PxI32 PxAtomicCompareExchange(volatile PxI32* dest, PxI32 exch, PxI32 comp)
{
return (PxI32)InterlockedCompareExchange((volatile LONG*)dest, exch, comp);
}
PxI64 PxAtomicCompareExchange(volatile PxI64* dest, PxI64 exch, PxI64 comp)
{
return (PxI64)InterlockedCompareExchange64((volatile LONG64*)dest, exch, comp);
}
void* PxAtomicCompareExchangePointer(volatile void** dest, void* exch, void* comp)
{
return InterlockedCompareExchangePointer((volatile PVOID*)dest, exch, comp);
}
PxI32 PxAtomicIncrement(volatile PxI32* val)
{
return (PxI32)InterlockedIncrement((volatile LONG*)val);
}
PxI64 PxAtomicIncrement(volatile PxI64* val)
{
return (PxI64)InterlockedIncrement64((volatile LONG64*)val);
}
PxI32 PxAtomicDecrement(volatile PxI32* val)
{
return (PxI32)InterlockedDecrement((volatile LONG*)val);
}
PxI64 PxAtomicDecrement(volatile PxI64* val)
{
return (PxI64)InterlockedDecrement64((volatile LONG64*)val);
}
PxI32 PxAtomicAdd(volatile PxI32* val, PxI32 delta)
{
if(1)
{
return (PxI32)InterlockedAdd((volatile LONG*)val, delta);
}
else
{
LONG newValue, oldValue;
do
{
oldValue = *val;
newValue = oldValue + delta;
} while(InterlockedCompareExchange((volatile LONG*)val, newValue, oldValue) != oldValue);
return newValue;
}
}
PxI64 PxAtomicAdd(volatile PxI64* val, PxI64 delta)
{
if(1)
{
return (PxI64)InterlockedAdd64((volatile LONG64*)val, delta);
}
else
{
LONG64 newValue, oldValue;
do
{
oldValue = *val;
newValue = oldValue + delta;
} while(InterlockedCompareExchange64((volatile LONG64*)val, newValue, oldValue) != oldValue);
return newValue;
}
}
PxI32 PxAtomicMax(volatile PxI32* val, PxI32 val2)
{
// Could do this more efficiently in asm...
LONG newValue, oldValue;
do
{
oldValue = *val;
newValue = val2 > oldValue ? val2 : oldValue;
} while(InterlockedCompareExchange((volatile LONG*)val, newValue, oldValue) != oldValue);
return newValue;
}
PxI64 PxAtomicMax(volatile PxI64* val, PxI64 val2)
{
// Could do this more efficiently in asm...
LONG64 newValue, oldValue;
do
{
oldValue = *val;
newValue = val2 > oldValue ? val2 : oldValue;
} while(InterlockedCompareExchange64((volatile LONG64*)val, newValue, oldValue) != oldValue);
return newValue;
}
PxI32 PxAtomicOr(volatile PxI32* val, PxI32 mask)
{
return (PxI32)InterlockedOr((volatile LONG*)val, mask);
}
PxI64 PxAtomicOr(volatile PxI64* val, PxI64 mask)
{
return (PxI64)InterlockedOr64((volatile LONG64*)val, mask);
}
PxI32 PxAtomicAnd(volatile PxI32* val, PxI32 mask)
{
return (PxI32)InterlockedAnd((volatile LONG*)val, mask);
}
PxI64 PxAtomicAnd(volatile PxI64* val, PxI64 mask)
{
return (PxI64)InterlockedAnd64((volatile LONG64*)val, mask);
}
} // namespace physx

View File

@@ -0,0 +1,88 @@
// 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-2025 NVIDIA Corporation. All rights reserved.
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
#include "foundation/PxFPU.h"
#include "float.h"
#include "foundation/PxIntrinsics.h"
#if PX_X64 || PX_ARM || PX_A64
#define _MCW_ALL _MCW_DN | _MCW_EM | _MCW_RC
#else
#define _MCW_ALL _MCW_DN | _MCW_EM | _MCW_IC | _MCW_RC | _MCW_PC
#endif
physx::PxFPUGuard::PxFPUGuard()
{
// default plus FTZ and DAZ
#if PX_X64 || PX_ARM || PX_A64
// query current control word state
_controlfp_s(mControlWords, 0, 0);
// set both x87 and sse units to default + DAZ
unsigned int cw;
_controlfp_s(&cw, _CW_DEFAULT | _DN_FLUSH, _MCW_ALL);
#else
// query current control word state
__control87_2(0, 0, mControlWords, mControlWords + 1);
// set both x87 and sse units to default + DAZ
unsigned int x87, sse;
__control87_2(_CW_DEFAULT | _DN_FLUSH, _MCW_ALL, &x87, &sse);
#endif
}
physx::PxFPUGuard::~PxFPUGuard()
{
_clearfp();
#if PX_X64 || PX_ARM || PX_A64
// reset FP state
unsigned int cw;
_controlfp_s(&cw, *mControlWords, _MCW_ALL);
#else
// reset FP state
unsigned int x87, sse;
__control87_2(mControlWords[0], _MCW_ALL, &x87, 0);
__control87_2(mControlWords[1], _MCW_ALL, 0, &sse);
#endif
}
void physx::PxEnableFPExceptions()
{
// clear any pending exceptions
_clearfp();
// enable all fp exceptions except inexact and underflow (common, benign)
_controlfp_s(NULL, uint32_t(~_MCW_EM) | _EM_INEXACT | _EM_UNDERFLOW, _MCW_EM);
}
void physx::PxDisableFPExceptions()
{
_controlfp_s(NULL, _MCW_EM, _MCW_EM);
}

View File

@@ -0,0 +1,154 @@
// 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-2025 NVIDIA Corporation. All rights reserved.
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
#include "foundation/windows/PxWindowsInclude.h"
#include "foundation/PxUserAllocated.h"
#include "foundation/PxMutex.h"
#include "foundation/PxErrorCallback.h"
#include "foundation/PxThread.h"
namespace physx
{
namespace
{
struct MutexWinImpl
{
CRITICAL_SECTION mLock;
PxThread::Id mOwner;
};
}
static PX_FORCE_INLINE MutexWinImpl* getMutex(PxMutexImpl* impl)
{
return reinterpret_cast<MutexWinImpl*>(impl);
}
PxMutexImpl::PxMutexImpl()
{
InitializeCriticalSection(&getMutex(this)->mLock);
getMutex(this)->mOwner = 0;
}
PxMutexImpl::~PxMutexImpl()
{
DeleteCriticalSection(&getMutex(this)->mLock);
}
void PxMutexImpl::lock()
{
EnterCriticalSection(&getMutex(this)->mLock);
#if PX_DEBUG
getMutex(this)->mOwner = PxThread::getId();
#endif
}
bool PxMutexImpl::trylock()
{
bool success = TryEnterCriticalSection(&getMutex(this)->mLock) != 0;
#if PX_DEBUG
if(success)
getMutex(this)->mOwner = PxThread::getId();
#endif
return success;
}
void PxMutexImpl::unlock()
{
#if PX_DEBUG
// ensure we are already holding the lock
if(getMutex(this)->mOwner != PxThread::getId())
{
PxGetFoundation().error(PxErrorCode::eINVALID_OPERATION, PX_FL, "Mutex must be unlocked only by thread that has already acquired lock");
return;
}
#endif
LeaveCriticalSection(&getMutex(this)->mLock);
}
uint32_t PxMutexImpl::getSize()
{
return sizeof(MutexWinImpl);
}
class ReadWriteLockImpl
{
PX_NOCOPY(ReadWriteLockImpl)
public:
ReadWriteLockImpl()
{
}
PxMutex mutex;
volatile LONG readerCount; // handle recursive writer locking
};
PxReadWriteLock::PxReadWriteLock()
{
mImpl = reinterpret_cast<ReadWriteLockImpl*>(PX_ALLOC(sizeof(ReadWriteLockImpl), "ReadWriteLockImpl"));
PX_PLACEMENT_NEW(mImpl, ReadWriteLockImpl);
mImpl->readerCount = 0;
}
PxReadWriteLock::~PxReadWriteLock()
{
mImpl->~ReadWriteLockImpl();
PX_FREE(mImpl);
}
void PxReadWriteLock::lockReader(bool takeLock)
{
if(takeLock)
mImpl->mutex.lock();
InterlockedIncrement(&mImpl->readerCount);
if(takeLock)
mImpl->mutex.unlock();
}
void PxReadWriteLock::lockWriter()
{
mImpl->mutex.lock();
// spin lock until no readers
while(mImpl->readerCount);
}
void PxReadWriteLock::unlockReader()
{
InterlockedDecrement(&mImpl->readerCount);
}
void PxReadWriteLock::unlockWriter()
{
mImpl->mutex.unlock();
}
} // namespace physx

View File

@@ -0,0 +1,42 @@
// 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-2025 NVIDIA Corporation. All rights reserved.
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
#include "foundation/PxString.h"
#include <stdio.h>
#include "foundation/windows/PxWindowsInclude.h"
#include <stdio.h>
#include <string.h>
#include <stdarg.h>
void physx::PxPrintString(const char* str)
{
puts(str); // do not use printf here, since str can contain multiple % signs that will not be printed
OutputDebugStringA(str);
OutputDebugStringA("\n");
}

View File

@@ -0,0 +1,68 @@
// 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-2025 NVIDIA Corporation. All rights reserved.
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
#include "foundation/windows/PxWindowsInclude.h"
#include "foundation/PxAllocator.h"
#include "foundation/PxSList.h"
using namespace physx;
template <typename T>
static PX_FORCE_INLINE SLIST_HEADER* getDetail(T* impl)
{
return reinterpret_cast<SLIST_HEADER*>(impl);
}
PxSListImpl::PxSListImpl()
{
InitializeSListHead(getDetail(this));
}
PxSListImpl::~PxSListImpl()
{
}
void PxSListImpl::push(PxSListEntry* entry)
{
InterlockedPushEntrySList(getDetail(this), reinterpret_cast<SLIST_ENTRY*>(entry));
}
PxSListEntry* PxSListImpl::pop()
{
return reinterpret_cast<PxSListEntry*>(InterlockedPopEntrySList(getDetail(this)));
}
PxSListEntry* PxSListImpl::flush()
{
return reinterpret_cast<PxSListEntry*>(InterlockedFlushSList(getDetail(this)));
}
uint32_t PxSListImpl::getSize()
{
return sizeof(SLIST_HEADER);
}

View File

@@ -0,0 +1,438 @@
// 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-2025 NVIDIA Corporation. All rights reserved.
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
#include "foundation/PxMathIntrinsics.h"
#include "foundation/windows/PxWindowsInclude.h"
#include "foundation/PxSocket.h"
#include "foundation/PxThread.h"
#include "foundation/PxArray.h"
#include <Winsock2.h>
#pragma comment(lib, "Ws2_32")
namespace physx
{
const uint32_t PxSocket::DEFAULT_BUFFER_SIZE = 32768;
class SocketImpl
{
public:
SocketImpl(bool isBlocking);
virtual ~SocketImpl();
bool connect(const char* host, uint16_t port, uint32_t timeout);
bool listen(uint16_t port);
bool accept(bool block);
void disconnect();
void setBlocking(bool blocking);
virtual uint32_t write(const uint8_t* data, uint32_t length);
virtual bool flush();
uint32_t read(uint8_t* data, uint32_t length);
PX_FORCE_INLINE bool isBlocking() const
{
return mIsBlocking;
}
PX_FORCE_INLINE bool isConnected() const
{
return mIsConnected;
}
PX_FORCE_INLINE const char* getHost() const
{
return mHost;
}
PX_FORCE_INLINE uint16_t getPort() const
{
return mPort;
}
protected:
bool nonBlockingTimeout() const;
void setBlockingInternal(SOCKET socket, bool blocking);
mutable SOCKET mSocket;
SOCKET mListenSocket;
const char* mHost;
uint16_t mPort;
mutable bool mIsConnected;
bool mIsBlocking;
bool mListenMode;
bool mSocketLayerIntialized;
};
SocketImpl::SocketImpl(bool isBlocking)
: mSocket(INVALID_SOCKET)
, mListenSocket(INVALID_SOCKET)
, mPort(0)
, mHost(NULL)
, mIsConnected(false)
, mIsBlocking(isBlocking)
, mListenMode(false)
, mSocketLayerIntialized(false)
{
WORD vreq;
WSADATA wsaData;
vreq = MAKEWORD(2, 2);
mSocketLayerIntialized = (WSAStartup(vreq, &wsaData) == 0);
}
SocketImpl::~SocketImpl()
{
if(mSocketLayerIntialized)
WSACleanup();
}
void SocketImpl::setBlockingInternal(SOCKET socket, bool blocking)
{
uint32_t mode = uint32_t(blocking ? 0 : 1);
ioctlsocket(socket, FIONBIO, (u_long*)&mode);
}
bool SocketImpl::connect(const char* host, uint16_t port, uint32_t timeout)
{
if(!mSocketLayerIntialized)
return false;
sockaddr_in socketAddress;
hostent* hp;
intrinsics::memSet(&socketAddress, 0, sizeof(sockaddr_in));
socketAddress.sin_family = AF_INET;
socketAddress.sin_port = htons(port);
// get host
hp = gethostbyname(host);
if(!hp)
{
in_addr a;
a.s_addr = inet_addr(host);
hp = gethostbyaddr((const char*)&a, sizeof(in_addr), AF_INET);
if(!hp)
return false;
}
intrinsics::memCopy(&socketAddress.sin_addr, hp->h_addr_list[0], (uint32_t)hp->h_length);
// connect
mSocket = socket(PF_INET, SOCK_STREAM, 0);
if(mSocket == INVALID_SOCKET)
return false;
setBlockingInternal(mSocket, false);
::connect(mSocket, (sockaddr*)&socketAddress, sizeof(socketAddress));
// Setup poll function call to monitor the connect call.
// By querying for POLLOUT we're checking if the socket is
// ready for writing.
WSAPOLLFD pfd;
pfd.fd = mSocket;
pfd.events = POLLOUT;
const int pollResult = WSAPoll(&pfd, 1, timeout /*milliseconds*/);
const bool pollTimeout = (pollResult == 0);
const bool pollError = (pollResult == SOCKET_ERROR); // an error inside poll happened. Can check error with `WSAGetLastError`.
if(pollTimeout || pollError)
{
disconnect();
return false;
}
else
{
PX_ASSERT(pollResult == 1);
// check that event was precisely POLLOUT and not anything else (e.g., errors, hang-up)
bool test = (pfd.revents & POLLOUT) && !(pfd.revents & (~POLLOUT));
if(!test)
{
disconnect();
return false;
}
}
setBlockingInternal(mSocket, mIsBlocking);
mIsConnected = true;
mPort = port;
mHost = host;
return true;
}
bool SocketImpl::listen(uint16_t port)
{
if(!mSocketLayerIntialized)
return false;
mListenSocket = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
if(mListenSocket == INVALID_SOCKET)
return false;
mListenMode = true;
sockaddr_in addr = { 0 };
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
addr.sin_addr.s_addr = htonl(INADDR_ANY);
return bind(mListenSocket, (sockaddr*)&addr, sizeof(addr)) == 0 && ::listen(mListenSocket, SOMAXCONN) == 0;
}
bool SocketImpl::accept(bool block)
{
if(mIsConnected || !mListenMode)
return false;
// set the listen socket to be non-blocking.
setBlockingInternal(mListenSocket, block);
SOCKET clientSocket = ::accept(mListenSocket, 0, 0);
if(clientSocket == INVALID_SOCKET)
return false;
mSocket = clientSocket;
mIsConnected = true;
setBlockingInternal(mSocket, mIsBlocking); // force the mode to whatever the user set
return mIsConnected;
}
void SocketImpl::disconnect()
{
if(mListenSocket != INVALID_SOCKET)
{
closesocket(mListenSocket);
mListenSocket = INVALID_SOCKET;
}
if(mSocket != INVALID_SOCKET)
{
WSASendDisconnect(mSocket, NULL);
closesocket(mSocket);
mSocket = INVALID_SOCKET;
}
mIsConnected = false;
mListenMode = false;
mPort = 0;
mHost = NULL;
}
bool SocketImpl::nonBlockingTimeout() const
{
return !mIsBlocking && WSAGetLastError() == WSAEWOULDBLOCK;
}
// should be cross-platform from here down
void SocketImpl::setBlocking(bool blocking)
{
if(blocking != mIsBlocking)
{
mIsBlocking = blocking;
if(isConnected())
setBlockingInternal(mSocket, blocking);
}
}
bool SocketImpl::flush()
{
return true;
}
uint32_t SocketImpl::write(const uint8_t* data, uint32_t length)
{
if(length == 0)
return 0;
int sent = send(mSocket, (const char*)data, (int32_t)length, 0);
if(sent <= 0 && !nonBlockingTimeout())
disconnect();
return uint32_t(sent > 0 ? sent : 0);
}
uint32_t SocketImpl::read(uint8_t* data, uint32_t length)
{
if(length == 0)
return 0;
int32_t received = recv(mSocket, (char*)data, (int32_t)length, 0);
if(received <= 0 && !nonBlockingTimeout())
disconnect();
return uint32_t(received > 0 ? received : 0);
}
class BufferedSocketImpl : public SocketImpl
{
public:
BufferedSocketImpl(bool isBlocking) : SocketImpl(isBlocking), mBufferPos(0)
{
}
virtual ~BufferedSocketImpl()
{
}
bool flush();
uint32_t write(const uint8_t* data, uint32_t length);
private:
uint32_t mBufferPos;
uint8_t mBuffer[PxSocket::DEFAULT_BUFFER_SIZE];
};
bool BufferedSocketImpl::flush()
{
uint32_t totalBytesWritten = 0;
while(totalBytesWritten < mBufferPos && mIsConnected)
totalBytesWritten += (int32_t)SocketImpl::write(mBuffer + totalBytesWritten, mBufferPos - totalBytesWritten);
bool ret = (totalBytesWritten == mBufferPos);
mBufferPos = 0;
return ret;
}
uint32_t BufferedSocketImpl::write(const uint8_t* data, uint32_t length)
{
uint32_t bytesWritten = 0;
while(mBufferPos + length >= PxSocket::DEFAULT_BUFFER_SIZE)
{
uint32_t currentChunk = PxSocket::DEFAULT_BUFFER_SIZE - mBufferPos;
intrinsics::memCopy(mBuffer + mBufferPos, data + bytesWritten, currentChunk);
bytesWritten += (uint32_t)currentChunk; // for the user, this is consumed even if we fail to shove it down a
// non-blocking socket
uint32_t sent = SocketImpl::write(mBuffer, PxSocket::DEFAULT_BUFFER_SIZE);
mBufferPos = PxSocket::DEFAULT_BUFFER_SIZE - sent;
if(sent < PxSocket::DEFAULT_BUFFER_SIZE) // non-blocking or error
{
if(sent) // we can reasonably hope this is rare
intrinsics::memMove(mBuffer, mBuffer + sent, mBufferPos);
return bytesWritten;
}
length -= currentChunk;
}
if(length > 0)
{
intrinsics::memCopy(mBuffer + mBufferPos, data + bytesWritten, length);
bytesWritten += length;
mBufferPos += length;
}
return bytesWritten;
}
PxSocket::PxSocket(bool inIsBuffering, bool isBlocking)
{
if(inIsBuffering)
{
void* mem = PX_ALLOC(sizeof(BufferedSocketImpl), "BufferedSocketImpl");
mImpl = PX_PLACEMENT_NEW(mem, BufferedSocketImpl)(isBlocking);
}
else
{
void* mem = PX_ALLOC(sizeof(SocketImpl), "SocketImpl");
mImpl = PX_PLACEMENT_NEW(mem, SocketImpl)(isBlocking);
}
}
PxSocket::~PxSocket()
{
mImpl->flush();
mImpl->disconnect();
mImpl->~SocketImpl();
PX_FREE(mImpl);
}
bool PxSocket::connect(const char* host, uint16_t port, uint32_t timeout)
{
return mImpl->connect(host, port, timeout);
}
bool PxSocket::listen(uint16_t port)
{
return mImpl->listen(port);
}
bool PxSocket::accept(bool block)
{
return mImpl->accept(block);
}
void PxSocket::disconnect()
{
mImpl->disconnect();
}
bool PxSocket::isConnected() const
{
return mImpl->isConnected();
}
const char* PxSocket::getHost() const
{
return mImpl->getHost();
}
uint16_t PxSocket::getPort() const
{
return mImpl->getPort();
}
bool PxSocket::flush()
{
if(!mImpl->isConnected())
return false;
return mImpl->flush();
}
uint32_t PxSocket::write(const uint8_t* data, uint32_t length)
{
if(!mImpl->isConnected())
return 0;
return mImpl->write(data, length);
}
uint32_t PxSocket::read(uint8_t* data, uint32_t length)
{
if(!mImpl->isConnected())
return 0;
return mImpl->read(data, length);
}
void PxSocket::setBlocking(bool blocking)
{
mImpl->setBlocking(blocking);
}
bool PxSocket::isBlocking() const
{
return mImpl->isBlocking();
}
} // namespace physx

View File

@@ -0,0 +1,72 @@
// 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-2025 NVIDIA Corporation. All rights reserved.
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
#include "foundation/windows/PxWindowsInclude.h"
#include "foundation/PxUserAllocated.h"
#include "foundation/PxSync.h"
using namespace physx;
static PX_FORCE_INLINE HANDLE& getSync(PxSyncImpl* impl)
{
return *reinterpret_cast<HANDLE*>(impl);
}
uint32_t PxSyncImpl::getSize()
{
return sizeof(HANDLE);
}
PxSyncImpl::PxSyncImpl()
{
getSync(this) = CreateEvent(0, true, false, 0);
}
PxSyncImpl::~PxSyncImpl()
{
CloseHandle(getSync(this));
}
void PxSyncImpl::reset()
{
ResetEvent(getSync(this));
}
void PxSyncImpl::set()
{
SetEvent(getSync(this));
}
bool PxSyncImpl::wait(uint32_t milliseconds)
{
if(milliseconds == -1)
milliseconds = INFINITE;
return WaitForSingleObject(getSync(this), milliseconds) == WAIT_OBJECT_0;
}

View File

@@ -0,0 +1,421 @@
// 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-2025 NVIDIA Corporation. All rights reserved.
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
#include "foundation/windows/PxWindowsInclude.h"
#include "foundation/PxErrorCallback.h"
#include "foundation/PxAssert.h"
#include "foundation/PxThread.h"
#include "foundation/PxAlloca.h"
// an exception for setting the thread name in Microsoft debuggers
#define NS_MS_VC_EXCEPTION 0x406D1388
namespace physx
{
namespace
{
#if PX_VC
#pragma warning(disable : 4061) // enumerator 'identifier' in switch of enum 'enumeration' is not handled
#pragma warning(disable : 4191) //'operator/operation' : unsafe conversion from 'type of expression' to 'type required'
#endif
// struct for naming a thread in the debugger
#pragma pack(push, 8)
typedef struct tagTHREADNAME_INFO
{
DWORD dwType; // Must be 0x1000.
LPCSTR szName; // Pointer to name (in user addr space).
DWORD dwThreadID; // Thread ID (-1=caller thread).
DWORD dwFlags; // Reserved for future use, must be zero.
} THREADNAME_INFO;
#pragma pack(pop)
class ThreadImpl
{
public:
enum State
{
NotStarted,
Started,
Stopped
};
HANDLE thread;
LONG quitNow; // Should be 32bit aligned on SMP systems.
State state;
DWORD threadID;
PxThreadImpl::ExecuteFn fn;
void* arg;
uint32_t affinityMask;
const char* name;
};
static PX_FORCE_INLINE ThreadImpl* getThread(PxThreadImpl* impl)
{
return reinterpret_cast<ThreadImpl*>(impl);
}
static DWORD WINAPI PxThreadStart(LPVOID arg)
{
ThreadImpl* impl = getThread((PxThreadImpl*)arg);
// run either the passed in function or execute from the derived class (Runnable).
if(impl->fn)
(*impl->fn)(impl->arg);
else if(impl->arg)
((PxRunnable*)impl->arg)->execute();
return 0;
}
// cache physical thread count
static uint32_t gPhysicalCoreCount = 0;
}
uint32_t PxThreadImpl::getSize()
{
return sizeof(ThreadImpl);
}
PxThreadImpl::Id PxThreadImpl::getId()
{
return static_cast<Id>(GetCurrentThreadId());
}
// fwd GetLogicalProcessorInformation()
typedef BOOL(WINAPI* LPFN_GLPI)(PSYSTEM_LOGICAL_PROCESSOR_INFORMATION, PDWORD);
uint32_t PxThreadImpl::getNbPhysicalCores()
{
if(!gPhysicalCoreCount)
{
// modified example code from: http://msdn.microsoft.com/en-us/library/ms683194
LPFN_GLPI glpi;
PSYSTEM_LOGICAL_PROCESSOR_INFORMATION buffer = NULL;
PSYSTEM_LOGICAL_PROCESSOR_INFORMATION ptr = NULL;
DWORD returnLength = 0;
DWORD processorCoreCount = 0;
DWORD byteOffset = 0;
glpi = (LPFN_GLPI)GetProcAddress(GetModuleHandle(TEXT("kernel32")), "GetLogicalProcessorInformation");
if(NULL == glpi)
{
// GetLogicalProcessorInformation not supported on OS < XP Service Pack 3
return 0;
}
DWORD rc = (DWORD)glpi(NULL, &returnLength);
PX_ASSERT(rc == FALSE);
PX_UNUSED(rc);
// first query reports required buffer space
if(GetLastError() == ERROR_INSUFFICIENT_BUFFER)
{
buffer = (PSYSTEM_LOGICAL_PROCESSOR_INFORMATION)PxAlloca(returnLength);
}
else
{
PxGetFoundation().error(PxErrorCode::eINTERNAL_ERROR, PX_FL, "Error querying buffer size for number of physical processors");
return 0;
}
// retrieve data
rc = (DWORD)glpi(buffer, &returnLength);
if(rc != TRUE)
{
PxGetFoundation().error(PxErrorCode::eINTERNAL_ERROR, PX_FL, "Error querying number of physical processors");
return 0;
}
ptr = buffer;
while(byteOffset + sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION) <= returnLength)
{
switch(ptr->Relationship)
{
case RelationProcessorCore:
processorCoreCount++;
break;
default:
break;
}
byteOffset += sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION);
ptr++;
}
gPhysicalCoreCount = processorCoreCount;
}
return gPhysicalCoreCount;
}
PxThreadImpl::PxThreadImpl()
{
getThread(this)->thread = NULL;
getThread(this)->state = ThreadImpl::NotStarted;
getThread(this)->quitNow = 0;
getThread(this)->fn = NULL;
getThread(this)->arg = NULL;
getThread(this)->affinityMask = 0;
getThread(this)->name = NULL;
}
PxThreadImpl::PxThreadImpl(ExecuteFn fn, void* arg, const char* name)
{
getThread(this)->thread = NULL;
getThread(this)->state = ThreadImpl::NotStarted;
getThread(this)->quitNow = 0;
getThread(this)->fn = fn;
getThread(this)->arg = arg;
getThread(this)->affinityMask = 0;
getThread(this)->name = name;
start(0, NULL);
}
PxThreadImpl::~PxThreadImpl()
{
if(getThread(this)->state == ThreadImpl::Started)
kill();
CloseHandle(getThread(this)->thread);
}
void PxThreadImpl::start(uint32_t stackSize, PxRunnable* runnable)
{
if(getThread(this)->state != ThreadImpl::NotStarted)
return;
getThread(this)->state = ThreadImpl::Started;
if(runnable && !getThread(this)->arg && !getThread(this)->fn)
getThread(this)->arg = runnable;
getThread(this)->thread =
CreateThread(NULL, stackSize, PxThreadStart, (LPVOID) this, CREATE_SUSPENDED, &getThread(this)->threadID);
if(!getThread(this)->thread)
{
PxGetFoundation().error(PxErrorCode::eINTERNAL_ERROR, PX_FL, "FdWindowsThread::start: Failed to create thread.");
getThread(this)->state = ThreadImpl::NotStarted;
return;
}
// set affinity, set name and resume
if(getThread(this)->affinityMask)
setAffinityMask(getThread(this)->affinityMask);
if (getThread(this)->name)
setName(getThread(this)->name);
DWORD rc = ResumeThread(getThread(this)->thread);
if(rc == DWORD(-1))
{
PxGetFoundation().error(PxErrorCode::eINTERNAL_ERROR, PX_FL, "FdWindowsThread::start: Failed to resume thread.");
getThread(this)->state = ThreadImpl::NotStarted;
return;
}
}
void PxThreadImpl::signalQuit()
{
InterlockedIncrement(&(getThread(this)->quitNow));
}
bool PxThreadImpl::waitForQuit()
{
if(getThread(this)->state == ThreadImpl::NotStarted)
return false;
WaitForSingleObject(getThread(this)->thread, INFINITE);
getThread(this)->state = ThreadImpl::Stopped;
return true;
}
bool PxThreadImpl::quitIsSignalled()
{
return InterlockedCompareExchange(&(getThread(this)->quitNow), 0, 0) != 0;
}
void PxThreadImpl::quit()
{
getThread(this)->state = ThreadImpl::Stopped;
ExitThread(0);
}
void PxThreadImpl::kill()
{
if(getThread(this)->state == ThreadImpl::Started)
TerminateThread(getThread(this)->thread, 0);
getThread(this)->state = ThreadImpl::Stopped;
}
void PxThreadImpl::sleep(uint32_t ms)
{
Sleep(ms);
}
void PxThreadImpl::yield()
{
SwitchToThread();
}
void PxThreadImpl::yieldProcessor()
{
YieldProcessor();
}
uint32_t PxThreadImpl::setAffinityMask(uint32_t mask)
{
if(mask)
{
// store affinity
getThread(this)->affinityMask = mask;
// if thread already started apply immediately
if(getThread(this)->state == ThreadImpl::Started)
{
uint32_t err = uint32_t(SetThreadAffinityMask(getThread(this)->thread, mask));
return err;
}
}
return 0;
}
void PxThreadImpl::setName(const char* name)
{
getThread(this)->name = name;
if (getThread(this)->state == ThreadImpl::Started)
{
THREADNAME_INFO info;
info.dwType = 0x1000;
info.szName = name;
info.dwThreadID = getThread(this)->threadID;
info.dwFlags = 0;
// C++ Exceptions are disabled for this project, but SEH is not (and cannot be)
// http://stackoverflow.com/questions/943087/what-exactly-will-happen-if-i-disable-c-exceptions-in-a-project
__try
{
RaiseException(NS_MS_VC_EXCEPTION, 0, sizeof(info) / sizeof(ULONG_PTR), (ULONG_PTR*)&info);
}
__except (EXCEPTION_EXECUTE_HANDLER)
{
// this runs if not attached to a debugger (thus not really naming the thread)
}
}
}
void PxThreadImpl::setPriority(PxThreadPriority::Enum prio)
{
BOOL rc = false;
switch(prio)
{
case PxThreadPriority::eHIGH:
rc = SetThreadPriority(getThread(this)->thread, THREAD_PRIORITY_HIGHEST);
break;
case PxThreadPriority::eABOVE_NORMAL:
rc = SetThreadPriority(getThread(this)->thread, THREAD_PRIORITY_ABOVE_NORMAL);
break;
case PxThreadPriority::eNORMAL:
rc = SetThreadPriority(getThread(this)->thread, THREAD_PRIORITY_NORMAL);
break;
case PxThreadPriority::eBELOW_NORMAL:
rc = SetThreadPriority(getThread(this)->thread, THREAD_PRIORITY_BELOW_NORMAL);
break;
case PxThreadPriority::eLOW:
rc = SetThreadPriority(getThread(this)->thread, THREAD_PRIORITY_LOWEST);
break;
default:
break;
}
if(!rc)
{
PxGetFoundation().error(PxErrorCode::eINTERNAL_ERROR, PX_FL, "FdWindowsThread::setPriority: Failed to set thread priority.");
}
}
PxThreadPriority::Enum PxThreadImpl::getPriority(Id threadId)
{
PxThreadPriority::Enum retval = PxThreadPriority::eLOW;
int priority = GetThreadPriority((HANDLE)threadId);
PX_COMPILE_TIME_ASSERT(THREAD_PRIORITY_HIGHEST > THREAD_PRIORITY_ABOVE_NORMAL);
if(priority >= THREAD_PRIORITY_HIGHEST)
retval = PxThreadPriority::eHIGH;
else if(priority >= THREAD_PRIORITY_ABOVE_NORMAL)
retval = PxThreadPriority::eABOVE_NORMAL;
else if(priority >= THREAD_PRIORITY_NORMAL)
retval = PxThreadPriority::eNORMAL;
else if(priority >= THREAD_PRIORITY_BELOW_NORMAL)
retval = PxThreadPriority::eBELOW_NORMAL;
return retval;
}
PxU32 PxTlsAlloc()
{
DWORD rv = ::TlsAlloc();
PX_ASSERT(rv != TLS_OUT_OF_INDEXES);
return (PxU32)rv;
}
void PxTlsFree(PxU32 index)
{
::TlsFree(index);
}
void* PxTlsGet(PxU32 index)
{
return ::TlsGetValue(index);
}
size_t PxTlsGetValue(PxU32 index)
{
return size_t(::TlsGetValue(index));
}
PxU32 PxTlsSet(PxU32 index, void* value)
{
return PxU32(::TlsSetValue(index, value));
}
PxU32 PxTlsSetValue(PxU32 index, size_t value)
{
return PxU32(::TlsSetValue(index, reinterpret_cast<void*>(value)));
}
PxU32 PxThreadImpl::getDefaultStackSize()
{
return 1048576;
};
} // namespace physx

View File

@@ -0,0 +1,92 @@
// 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-2025 NVIDIA Corporation. All rights reserved.
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
#include "foundation/PxTime.h"
#include "foundation/windows/PxWindowsInclude.h"
using namespace physx;
static int64_t getTimeTicks()
{
LARGE_INTEGER a;
QueryPerformanceCounter(&a);
return a.QuadPart;
}
static double getTickDuration()
{
LARGE_INTEGER a;
QueryPerformanceFrequency(&a);
return 1.0f / double(a.QuadPart);
}
static double sTickDuration = getTickDuration();
static const PxCounterFrequencyToTensOfNanos gCounterFreq = PxTime::getCounterFrequency();
const PxCounterFrequencyToTensOfNanos& PxTime::getBootCounterFrequency()
{
return gCounterFreq;
}
PxCounterFrequencyToTensOfNanos PxTime::getCounterFrequency()
{
LARGE_INTEGER freq;
QueryPerformanceFrequency(&freq);
return PxCounterFrequencyToTensOfNanos(PxTime::sNumTensOfNanoSecondsInASecond, (uint64_t)freq.QuadPart);
}
uint64_t PxTime::getCurrentCounterValue()
{
LARGE_INTEGER ticks;
QueryPerformanceCounter(&ticks);
return (uint64_t)ticks.QuadPart;
}
PxTime::PxTime() : mTickCount(0)
{
getElapsedSeconds();
}
PxTime::Second PxTime::getElapsedSeconds()
{
int64_t lastTickCount = mTickCount;
mTickCount = getTimeTicks();
return (mTickCount - lastTickCount) * sTickDuration;
}
PxTime::Second PxTime::peekElapsedSeconds()
{
return (getTimeTicks() - mTickCount) * sTickDuration;
}
PxTime::Second PxTime::getLastTime() const
{
return mTickCount * sTickDuration;
}