1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
|
/*
* Copyright (c) 2008-2017, 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.
*/
#pragma once
#include <NvCloth/Callbacks.h>
#include <foundation/PxAllocatorCallback.h>
#include <foundation/PxErrorCallback.h>
#include <foundation/PxProfiler.h>
#include <vector>
#include <map>
#if USE_CUDA
#include <cuda.h>
#endif
#include <string>
#include <sstream>
#include <assert.h>
#include <mutex>
#include <NvCloth/DxContextManagerCallback.h>
#ifdef _MSC_VER
#include <Windows.h>
#endif
class Allocator : public physx::PxAllocatorCallback
{
public:
Allocator()
{
mEnableLeakDetection = false;
}
virtual void* allocate(size_t size, const char* typeName, const char* filename, int line)
{
#ifdef _MSC_VER
void* ptr = _aligned_malloc(size, 16);
#else
void* ptr;
if(posix_memalign(&ptr, 16, size)) ptr = 0;
#endif
if (mEnableLeakDetection)
{
std::lock_guard<std::mutex> lock(mAllocationsMapLock);
mAllocations[ptr] = Allocation(size, typeName, filename, line);
}
return ptr;
}
virtual void deallocate(void* ptr)
{
if (mEnableLeakDetection && ptr)
{
std::lock_guard<std::mutex> lock(mAllocationsMapLock);
auto i = mAllocations.find(ptr);
if (i == mAllocations.end())
{
printf("Tried to deallocate %p which was not allocated with this allocator callback.",ptr);
}
else
{
mAllocations.erase(i);
}
}
#ifdef _MSC_VER
_aligned_free(ptr);
#else
free(ptr);
#endif
}
void StartTrackingLeaks()
{
std::lock_guard<std::mutex> lock(mAllocationsMapLock);
mAllocations.clear();
mEnableLeakDetection = true;
}
void StopTrackingLeaksAndReport()
{
std::lock_guard<std::mutex> lock(mAllocationsMapLock);
mEnableLeakDetection = false;
size_t totalBytes = 0;
std::stringstream message;
message << "Memory leaks detected:\n";
for (auto it = mAllocations.begin(); it != mAllocations.end(); ++it)
{
const Allocation& alloc = it->second;
message << "* Allocated ptr " << it->first << " of " << alloc.mSize << "bytes (type=" << alloc.mTypeName << ") at " << alloc.mFileName << ":" << alloc.mLine<<"\n";
totalBytes += alloc.mSize;
}
if (mAllocations.size()>0)
{
message << "=====Total of " << totalBytes << " bytes in " << mAllocations.size() << " allocations leaked=====";
const std::string& tmp = message.str();
#ifdef _MSC_VER
// OutputDebugString(tmp.c_str()); //Write to visual studio output so we can see it after the application closes
#endif
printf("%s\n", tmp.c_str());
}
mAllocations.clear();
}
private:
bool mEnableLeakDetection;
struct Allocation
{
Allocation(){}
Allocation(size_t size, const char* typeName, const char* filename, int line)
: mSize(size), mTypeName(typeName), mFileName(filename), mLine(line)
{
}
size_t mSize;
std::string mTypeName;
std::string mFileName;
int mLine;
};
std::map<void*,Allocation> mAllocations;
std::mutex mAllocationsMapLock;
};
class ErrorCallback : public physx::PxErrorCallback
{
public:
ErrorCallback(){}
virtual void reportError(physx::PxErrorCode::Enum code, const char* message, const char* file, int line);
};
class AssertHandler : public nv::cloth::PxAssertHandler
{
public:
virtual void operator()(const char* exp, const char* file, int line, bool& ignore)
{
PX_UNUSED(ignore);
printf("NV_CLOTH_ASSERT(%s) from file:%s:%d Failed\n", exp, file, line);
assert(("Assertion failed, see log/console for more info.",0));
}
};
class NvClothEnvironment
{
NvClothEnvironment()
{
SetUp();
}
virtual ~NvClothEnvironment()
{
TearDown();
}
static NvClothEnvironment* sEnv;
public:
static void AllocateEnv()
{
sEnv = new NvClothEnvironment;
}
static void FreeEnv(){ delete sEnv; sEnv = nullptr; }
static void ReportEnvFreed(){ sEnv = nullptr; } //google test will free it for us, so we just reset the value
static NvClothEnvironment* GetEnv(){ return sEnv; }
virtual void SetUp()
{
mAllocator = new Allocator;
mAllocator->StartTrackingLeaks();
mFoundationAllocator = new Allocator;
mFoundationAllocator->StartTrackingLeaks();
mErrorCallback = new ErrorCallback;
mAssertHandler = new AssertHandler;
nv::cloth::InitializeNvCloth(mAllocator, mErrorCallback, mAssertHandler, nullptr);
#if USE_CUDA
cuInit(0);
#endif
}
virtual void TearDown()
{
mAllocator->StopTrackingLeaksAndReport();
mFoundationAllocator->StopTrackingLeaksAndReport();
delete mErrorCallback;
delete mFoundationAllocator;
delete mAllocator;
delete mAssertHandler;
}
Allocator* GetAllocator(){ return mAllocator; }
Allocator* GetFoundationAllocator(){ return mFoundationAllocator; }
ErrorCallback* GetErrorCallback(){ return mErrorCallback; }
AssertHandler* GetAssertHandler(){ return mAssertHandler; }
private:
Allocator* mAllocator;
Allocator* mFoundationAllocator;
ErrorCallback* mErrorCallback;
AssertHandler* mAssertHandler;
};
//#if USE_DX11
class DxContextManagerCallbackImpl : public nv::cloth::DxContextManagerCallback
{
public:
DxContextManagerCallbackImpl(ID3D11Device* device, bool synchronizeResources = false);
~DxContextManagerCallbackImpl();
virtual void acquireContext() override;
virtual void releaseContext() override;
virtual ID3D11Device* getDevice() const override;
virtual ID3D11DeviceContext* getContext() const override;
virtual bool synchronizeResources() const override;
private:
std::recursive_mutex mMutex;
ID3D11Device* mDevice;
ID3D11DeviceContext* mContext;
bool mSynchronizeResources;
#ifdef _DEBUG
uint32_t mLockCountTls;
#endif
};
//#endif
|