RavEngine
Loading...
Searching...
No Matches
PxProfileEventBufferAtomic.h
1// Redistribution and use in source and binary forms, with or without
2// modification, are permitted provided that the following conditions
3// are met:
4// * Redistributions of source code must retain the above copyright
5// notice, this list of conditions and the following disclaimer.
6// * Redistributions in binary form must reproduce the above copyright
7// notice, this list of conditions and the following disclaimer in the
8// documentation and/or other materials provided with the distribution.
9// * Neither the name of NVIDIA CORPORATION nor the names of its
10// contributors may be used to endorse or promote products derived
11// from this software without specific prior written permission.
12//
13// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
14// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
17// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24//
25// Copyright (c) 2008-2022 NVIDIA Corporation. All rights reserved.
26// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
27// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
28
29#ifndef PX_PROFILE_EVENT_BUFFER_ATOMIC_H
30#define PX_PROFILE_EVENT_BUFFER_ATOMIC_H
31
32#include "PxProfileEvents.h"
33#include "PxProfileEventSerialization.h"
34#include "PxProfileDataBuffer.h"
35
36#include "foundation/PxArray.h"
37#include "foundation/PxAtomic.h"
38#include "foundation/PxAllocator.h"
39#include "foundation/PxAlloca.h"
40#include "foundation/PxTime.h"
41
42
43namespace physx {
44 namespace profile {
45
46 static const uint32_t LOCAL_BUFFER_SIZE = 512;
47
111 template<typename TContextProvider,
112 typename TMutex,
113 typename TScopedLock,
114 typename TEventFilter>
115 class EventBufferAtomic : public DataBuffer < TMutex, TScopedLock >
116 {
117 public:
119 typedef TContextProvider TContextProviderType;
120 typedef TEventFilter TEventFilterType;
121 typedef typename TBaseType::TMutexType TMutexType;
122 typedef typename TBaseType::TScopedLockType TScopedLockType;
126
127 private:
128 TContextProvider mContextProvider;
129 TEventFilterType mEventFilter;
130 volatile int32_t mReserved;
131 volatile int32_t mWritten;
132
133 public:
135 , uint32_t inBufferFullAmount
136 , const TContextProvider& inProvider
137 , TMutexType* inBufferMutex
138 , const TEventFilterType& inEventFilter)
139 : TBaseType(inFoundation, inBufferFullAmount, inBufferMutex, "struct physx::profile::ProfileEvent")
140 , mContextProvider(inProvider)
141 , mEventFilter(inEventFilter)
142 , mReserved(0)
143 , mWritten(0)
144 {
145 }
146
147 TContextProvider& getContextProvider() { return mContextProvider; }
148
149 PX_FORCE_INLINE void startEvent(uint16_t inId, uint32_t threadId, uint64_t contextId, uint8_t cpuId, uint8_t threadPriority, uint64_t inTimestamp)
150 {
151 if (mEventFilter.isEventEnabled(inId))
152 {
153 StartEvent theEvent;
154 theEvent.init(threadId, contextId, cpuId, threadPriority, inTimestamp);
155 doAddProfileEvent(inId, theEvent);
156 }
157 }
158
159 PX_FORCE_INLINE void startEvent(uint16_t inId, uint64_t contextId)
160 {
161 PxProfileEventExecutionContext ctx(mContextProvider.getExecutionContext());
162 startEvent(inId, ctx.mThreadId, contextId, ctx.mCpuId, static_cast<uint8_t>(ctx.mThreadPriority), PxTime::getCurrentCounterValue());
163 }
164
165 PX_FORCE_INLINE void startEvent(uint16_t inId, uint64_t contextId, uint32_t threadId)
166 {
167 startEvent(inId, threadId, contextId, 0, 0, PxTime::getCurrentCounterValue());
168 }
169
170 PX_FORCE_INLINE void stopEvent(uint16_t inId, uint32_t threadId, uint64_t contextId, uint8_t cpuId, uint8_t threadPriority, uint64_t inTimestamp)
171 {
172 if (mEventFilter.isEventEnabled(inId))
173 {
174 StopEvent theEvent;
175 theEvent.init(threadId, contextId, cpuId, threadPriority, inTimestamp);
176 doAddProfileEvent(inId, theEvent);
177 }
178 }
179
180 PX_FORCE_INLINE void stopEvent(uint16_t inId, uint64_t contextId)
181 {
182 PxProfileEventExecutionContext ctx(mContextProvider.getExecutionContext());
183 stopEvent(inId, ctx.mThreadId, contextId, ctx.mCpuId, static_cast<uint8_t>(ctx.mThreadPriority), PxTime::getCurrentCounterValue());
184 }
185
186 PX_FORCE_INLINE void stopEvent(uint16_t inId, uint64_t contextId, uint32_t threadId)
187 {
188 stopEvent(inId, threadId, contextId, 0, 0, PxTime::getCurrentCounterValue());
189 }
190
191 inline void eventValue(uint16_t inId, uint64_t contextId, int64_t inValue)
192 {
193 eventValue(inId, mContextProvider.getThreadId(), contextId, inValue);
194 }
195
196 inline void eventValue(uint16_t inId, uint32_t threadId, uint64_t contextId, int64_t inValue)
197 {
198 EventValue theEvent;
199 theEvent.init(inValue, contextId, threadId);
200 EventHeader theHeader(static_cast<uint8_t>(getEventType<EventValue>()), inId);
201 //set the header relative timestamp;
202 EventValue& theType(theEvent);
203 theType.setupHeader(theHeader);
204
205 int32_t sizeToWrite = int32_t(sizeof(theHeader) + theType.getEventSize(theHeader));
206 int32_t reserved = PxAtomicAdd(&mReserved, sizeToWrite);
207 sendEvent(theHeader, theType, reserved, sizeToWrite);
208 }
209
210 void flushProfileEvents(int32_t reserved = -1)
211 {
212 TScopedLockType lock(TBaseType::mBufferMutex);
213
214 // set the buffer full to lock additional writes
215 int32_t reservedOld = PxAtomicExchange(&mReserved, int32_t(TBaseType::mBufferFullAmount + 1));
216 if (reserved == -1)
217 reserved = reservedOld;
218
219 // spin till we have written all the data
220 while (reserved > mWritten)
221 {
222 }
223
224 // check if we have written all data
225 PX_ASSERT(reserved == mWritten);
226
227 // set the correct size of the serialization data buffer
228 TBaseType::mSerializer.mArray->setEnd(TBaseType::mSerializer.mArray->begin() + mWritten);
229
230 // flush events
231 TBaseType::flushEvents();
232
233 // write master timestamp and set reserved/written to start writing to buffer again
234 mWritten = 0;
235 mReserved = 0;
236 }
237
238 void release()
239 {
240 PX_PROFILE_DELETE(TBaseType::mWrapper.mUserFoundation, this);
241 }
242 protected:
243 //Clears the cache meaning event compression
244 //starts over again.
245 //only called when the buffer mutex is held
246 void clearCachedData()
247 {
248 }
249
250 template<typename TProfileEventType>
251 PX_FORCE_INLINE void doAddProfileEvent(uint16_t eventId, const TProfileEventType& inType)
252 {
253 doAddEvent(static_cast<uint8_t>(getEventType<TProfileEventType>()), eventId, inType);
254 }
255
256 template<typename TDataType>
257 PX_FORCE_INLINE void doAddEvent(uint8_t inEventType, uint16_t eventId, const TDataType& inType)
258 {
259 EventHeader theHeader(inEventType, eventId);
260 TDataType& theType(const_cast<TDataType&>(inType));
261 theType.setupHeader(theHeader, 0);
262
263 const int32_t sizeToWrite = int32_t(sizeof(theHeader) + theType.getEventSize(theHeader));
264
265 int32_t reserved = PxAtomicAdd(&mReserved, sizeToWrite);
266 sendEvent(theHeader, theType, reserved, sizeToWrite);
267 }
268
269 template<typename TDataType>
270 PX_FORCE_INLINE void sendEvent(EventHeader& inHeader, TDataType& inType, int32_t reserved, int32_t sizeToWrite)
271 {
272 // if we don't fit to the buffer, we wait till it is flushed
273 if (reserved - sizeToWrite >= int32_t(TBaseType::mBufferFullAmount))
274 {
275 while (reserved - sizeToWrite >= int32_t(TBaseType::mBufferFullAmount))
276 {
277 // I32 overflow
278 if (mReserved < int32_t(TBaseType::mBufferFullAmount))
279 {
280 reserved = PxAtomicAdd(&mReserved, sizeToWrite);
281 }
282 }
283 }
284
285 int32_t writeIndex = reserved - sizeToWrite;
286 uint32_t writtenSize = 0;
287
288 PX_ASSERT(writeIndex >= 0);
289
290 PX_ALLOCA(tempBuffer, uint8_t, sizeToWrite);
291 TempMemoryBuffer memoryBuffer(tempBuffer, sizeToWrite);
292 EventSerializer<TempMemoryBuffer> eventSerializer(&memoryBuffer);
293
294 writtenSize = inHeader.streamify(eventSerializer);
295 writtenSize += inType.streamify(eventSerializer, inHeader);
296
297 TBaseType::mSerializer.mArray->reserve(writeIndex + writtenSize);
298 TBaseType::mSerializer.mArray->write(&tempBuffer[0], writtenSize, writeIndex);
299
300 PX_ASSERT(writtenSize == uint32_t(sizeToWrite));
301 PxAtomicAdd(&mWritten, sizeToWrite);
302
303 if (reserved >= int32_t(TBaseType::mBufferFullAmount))
304 {
305 TScopedLockType lock(TBaseType::mBufferMutex);
306 // we flush the buffer if its full and we did not flushed him in the meantime
307 if(mReserved >= reserved)
308 flushProfileEvents(reserved);
309 }
310 }
311
312 };
313 }
314}
315#endif
316
Abstract base class for an application defined memory allocator that can be used by the Nv library.
Definition PxAllocatorCallback.h:53
Definition PxProfileDataBuffer.h:41
Definition PxProfileEventBufferAtomic.h:116
Definition PxProfileMemoryBuffer.h:140
#define PX_FORCE_INLINE
Definition PxPreprocessor.h:335
uint32 uint32_t
Definition fwd.hpp:131
Sorts an array of objects in ascending order, assuming that the predicate implements the < operator:
Definition PxBoxController.h:39
Definition PxProfileEvents.h:169
Definition PxProfileEventSerialization.h:44
Definition PxProfileEvents.h:491
Definition PxProfileContextProvider.h:35
Helper class to encapsulate the named allocator.
Definition PxProfileAllocatorWrapper.h:115
Definition PxProfileEvents.h:457
Definition PxProfileEvents.h:475