44 #define FW_MEM_DEBUG 0
84 bool SafeSpinlock::s_inited =
false;
89 static size_t s_memoryUsed = 0;
90 static bool s_hasFailed =
false;
91 static int s_nestingLevel = 0;
92 static bool s_discardEvents =
false;
93 static String s_emptyString;
99 static bool s_memPushingOwner =
false;
100 static AllocHeader s_memAllocs = { &s_memAllocs, &s_memAllocs, 0,
NULL };
104 static bool s_profileStarted =
false;
113 static void deinitString(
void* str)
129 fail(
"Out of memory!");
131 void*
ptr = alloc + 1;
133 alloc->
next = &s_memAllocs;
137 alloc->
ownerID =
"Uncategorized";
138 s_memoryUsed +=
size;
140 if (!s_memPushingOwner)
143 if (s_memOwnerStacks.contains(threadID) && s_memOwnerStacks[threadID].getSize())
144 alloc->
ownerID = s_memOwnerStacks[threadID].getLast();
152 fail(
"Out of memory!");
155 s_memoryUsed += _msize(ptr);
175 s_memoryUsed -= alloc->
size;
182 s_memoryUsed -= _msize(ptr);
210 size_t oldSize = _msize(ptr);
213 fail(
"Out of memory!");
216 s_memoryUsed += _msize(newPtr) - oldSize;
232 for (
int i = 0; i < s_logFiles.getSize(); i++)
233 s_logStreams[i]->writefv(fmt, args);
246 str.
setfv(fmt, args);
261 str->
setfv(fmt, args);
299 return (str) ? *str : s_emptyString;
309 bool alreadyFailed = s_hasFailed;
320 tmp.
setfv(fmt, args);
331 MessageBox(
NULL, tmp.
getPtr(),
"Fatal error", MB_OK);
335 if (IsDebuggerPresent())
347 DWORD err = GetLastError();
348 LPTSTR msgBuf =
NULL;
349 FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
NULL, err, 0, (LPTSTR)&msgBuf, 0,
NULL);
354 fail(
"%s() failed!\n%s", funcName, msg.
getPtr());
356 fail(
"%s() failed!\nError %d\n", funcName, err);
371 int old = s_nestingLevel;
372 s_nestingLevel += delta;
380 bool old = s_discardEvents;
381 s_discardEvents = discard;
389 return s_discardEvents;
399 s_logFiles.add(file);
409 if (s_logFiles.getSize())
411 s_logStreams.getLast()->flush();
412 delete s_logFiles.removeLast();
413 delete s_logStreams.removeLast();
414 if (!s_logFiles.getSize())
417 s_logStreams.reset();
427 return (s_logFiles.getSize() != 0);
445 s_memPushingOwner =
true;
451 stack = &s_memOwnerStacks.
add(threadID);
456 s_memPushingOwner =
false;
473 s_memOwnerStacks.remove(threadID);
474 if (!s_memOwnerStacks.getSize())
475 s_memOwnerStacks.reset();
504 if (!owners.
contains(alloc->ownerID))
505 owners.
add(alloc->ownerID, 0);
506 owners[alloc->ownerID] += alloc->size;
516 printf(
"%-32s%.2f\n",
"Memory usage / megs", (
F32)s_memoryUsed *
exp2(-20));
520 printf(
" %-30s%-12.2f%.0f%%\n",
534 fail(
"profileStart() can only be used in the main thread!");
535 if (s_profileStarted)
538 s_profileStarted =
true;
546 if (!s_profileStarted)
549 fail(
"profilePush() can only be used in the main thread!");
554 S32* found = s_profilePointerToToken.search(
id);
559 found = s_profileStringToToken.search(
id);
564 token = s_profileStringToToken.getSize();
565 s_profileStringToToken.add(
id, token);
567 s_profilePointerToToken.add(
id, token);
572 Vec2i timerKey(-1, token);
574 timerKey.x = s_profileStack.
getLast();
577 found = s_profileTimerHash.search(timerKey);
582 timerIdx = s_profileTimers.getSize();
583 s_profileTimerHash.add(timerKey, timerIdx);
586 timer.
parent = timerKey.x;
587 if (timerKey.x != -1)
588 s_profileTimers[timerKey.x].children.add(timerIdx);
593 if (s_profileStack.
getSize() == 1)
594 s_profileTimers[s_profileStack[0]].timer.start();
595 s_profileStack.
add(timerIdx);
596 if (s_profileStack.
getSize() > 1)
597 s_profileTimers[timerIdx].timer.start();
604 if (!s_profileStarted || s_profileStack.
getSize() == 0)
607 fail(
"profilePop() can only be used in the main thread!");
609 if (s_profileStack.
getSize() > 1)
610 s_profileTimers[s_profileStack.
getLast()].timer.end();
612 if (s_profileStack.
getSize() == 1)
613 s_profileTimers[s_profileStack.
getLast()].timer.end();
621 fail(
"profileEnd() can only be used in the main thread!");
622 if (!s_profileStarted)
627 while (s_profileStack.
getSize())
632 if (printResults && s_profileTimers.getSize() > 1)
655 s_profileStarted =
false;
656 s_profilePointerToToken.reset();
657 s_profileStringToToken.reset();
658 s_profileTimerHash.reset();
659 s_profileTimers.reset();
660 s_profileStack.
reset();
int nextSlot(int slot) const
bool contains(const K &key) const
const char * getPtr(void) const
void * malloc(size_t size)
void setUserData(const String &id, void *data, DeinitFunc deinitFunc=NULL)
void setError(const char *fmt,...)
String & setfv(const char *fmt, va_list args)
void failWin32Error(const char *funcName)
static void suspendAll(void)
bool getDiscardEvents(void)
void * getUserData(const String &id)
bool restoreError(const String &old)
const Entry & getSlot(int slot) const
const T & getLast(void) const
size_t getMemoryUsed(void)
const String & getError(void)
bool setDiscardEvents(bool discard)
FW_CUDA_FUNC T min(const VectorBase< T, L, S > &v)
void pushMemOwner(const char *id)
void * realloc(void *ptr, size_t size)
void pushLogFile(const String &name, bool append=true)
int getLength(void) const
int incNestingLevel(int delta)
String sprintf(const char *fmt,...)
V & add(const K &key, const V &value)
void printf(const char *fmt,...)
static Thread * getCurrent(void)
void fail(const char *fmt,...)
void profileEnd(bool printResults=true)
CUdevice int ordinal char int CUdevice dev CUdevprop CUdevice dev CUcontext ctx CUcontext ctx CUcontext pctx CUmodule const void image CUmodule const void fatCubin CUfunction CUmodule const char name void p CUfunction unsigned int bytes CUtexref pTexRef CUtexref CUarray unsigned int Flags CUtexref int CUaddress_mode am CUtexref unsigned int Flags CUaddress_mode CUtexref int dim CUarray_format int CUtexref hTexRef CUfunction unsigned int numbytes CUfunction int float value CUfunction int CUtexref hTexRef CUfunction int int grid_height CUevent unsigned int Flags CUevent hEvent CUevent hEvent CUstream unsigned int Flags CUstream hStream GLuint bufferobj unsigned int CUdevice dev CUdeviceptr unsigned int CUmodule const char name CUdeviceptr unsigned int bytesize CUdeviceptr dptr void unsigned int bytesize void CUdeviceptr unsigned int ByteCount CUarray unsigned int CUdeviceptr unsigned int ByteCount CUarray unsigned int const void unsigned int ByteCount CUarray unsigned int CUarray unsigned int unsigned int ByteCount void CUarray unsigned int unsigned int CUstream hStream const CUDA_MEMCPY2D pCopy CUdeviceptr const void unsigned int CUstream hStream const CUDA_MEMCPY2D CUstream hStream CUdeviceptr unsigned char unsigned int N CUdeviceptr unsigned int unsigned int N CUdeviceptr unsigned int unsigned short unsigned int unsigned int Height CUarray const CUDA_ARRAY_DESCRIPTOR pAllocateArray CUarray const CUDA_ARRAY3D_DESCRIPTOR pAllocateArray unsigned int CUtexref CUdeviceptr unsigned int bytes CUcontext unsigned int CUdevice device GLenum texture GLenum GLuint buffer GLenum GLuint renderbuffer GLenum GLsizeiptr size
void profilePush(const char *id)
int firstSlot(void) const