00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #include "stdafx.h"
00027 #include "probes.h"
00028 #ifdef PBRT_PROBES_COUNTERS
00029 #include "parallel.h"
00030 #include <map>
00031 using std::map;
00032
00033
00034 #ifdef PBRT_HAS_64_BIT_ATOMICS
00035 typedef AtomicInt64 StatsCounterType;
00036 #else
00037 typedef AtomicInt32 StatsCounterType;
00038 #endif
00039 class StatsCounter {
00040 public:
00041
00042 StatsCounter(const string &category, const string &name);
00043 void operator++() {
00044 AtomicAdd(&num, 1);
00045 }
00046 void operator++(int) {
00047 AtomicAdd(&num, 1);
00048 }
00049 #ifdef PBRT_HAS_64_BIT_ATOMICS
00050 void Max(int64_t newval) {
00051 int64_t oldval;
00052 do {
00053 oldval = num;
00054 newval = max(oldval, newval);
00055 if (newval == oldval) return;
00056 } while(AtomicCompareAndSwap(&num, newval, oldval) != oldval);
00057 }
00058 void Min(int64_t newval) {
00059 int64_t oldval;
00060 do {
00061 oldval = (uint32_t)num;
00062 newval = min(oldval, newval);
00063 if (newval == oldval) return;
00064 } while(AtomicCompareAndSwap(&num, newval, oldval) != oldval);
00065 }
00066 #else
00067 void Max(int32_t newval) {
00068 int32_t oldval;
00069 do {
00070 oldval = num;
00071 newval = max(oldval, newval);
00072 if (newval == oldval) return;
00073 } while(AtomicCompareAndSwap(&num, newval, oldval) != oldval);
00074 }
00075 void Min(int32_t newval) {
00076 int32_t oldval;
00077 do {
00078 oldval = (uint32_t)num;
00079 newval = min(oldval, newval);
00080 if (newval == oldval) return;
00081 } while(AtomicCompareAndSwap(&num, newval, oldval) != oldval);
00082 }
00083 #endif
00084 #ifdef PBRT_HAS_64_BIT_ATOMICS
00085 operator int64_t() volatile { return (int64_t)num; }
00086 #else
00087 operator int32_t() volatile { return (int32_t)num; }
00088 #endif
00089 private:
00090
00091 StatsCounterType num;
00092 };
00093
00094
00095 class StatsRatio {
00096 public:
00097
00098 StatsRatio(const string &category, const string &name);
00099 void Add(int a, int b) {
00100 AtomicAdd(&na, a);
00101 AtomicAdd(&nb, b);
00102 }
00103 private:
00104
00105 StatsCounterType na, nb;
00106 };
00107
00108
00109 class StatsPercentage {
00110 public:
00111
00112 void Add(int a, int b) {
00113 AtomicAdd(&na, a);
00114 AtomicAdd(&nb, b);
00115 }
00116 StatsPercentage(const string &category, const string &name);
00117 private:
00118
00119 StatsCounterType na, nb;
00120 };
00121
00122
00123
00124
00125 static void ProbesPrintVal(FILE *f, const StatsCounterType &v);
00126 static void ProbesPrintVal(FILE *f, const StatsCounterType &v1,
00127 const StatsCounterType &v2);
00128 struct StatTracker {
00129 StatTracker(const string &cat, const string &n,
00130 StatsCounterType *pa, StatsCounterType *pb = NULL,
00131 bool percentage = true);
00132 string category, name;
00133 StatsCounterType *ptra, *ptrb;
00134 bool percentage;
00135 };
00136
00137
00138 typedef map<std::pair<string, string>, StatTracker *> TrackerMap;
00139 static TrackerMap trackers;
00140 static void addTracker(StatTracker *newTracker) {
00141 static Mutex *mutex = Mutex::Create();
00142 MutexLock lock(*mutex);
00143 std::pair<string, string> s = std::make_pair(newTracker->category, newTracker->name);
00144 if (trackers.find(s) != trackers.end()) {
00145 newTracker->ptra = trackers[s]->ptra;
00146 newTracker->ptrb = trackers[s]->ptrb;
00147 return;
00148 }
00149 trackers[s] = newTracker;
00150 }
00151
00152
00153
00154
00155 void ProbesPrint(FILE *dest) {
00156 fprintf(dest, "Statistics:\n");
00157 TrackerMap::iterator iter = trackers.begin();
00158 string lastCategory;
00159 while (iter != trackers.end()) {
00160
00161 StatTracker *tr = iter->second;
00162 if (tr->category != lastCategory) {
00163 fprintf(dest, "%s\n", tr->category.c_str());
00164 lastCategory = tr->category;
00165 }
00166 fprintf(dest, " %s", tr->name.c_str());
00167
00168
00169 int resultsColumn = 56;
00170 int paddingSpaces = resultsColumn - (int) tr->name.size();
00171 while (paddingSpaces-- > 0)
00172 putc(' ', dest);
00173 if (tr->ptrb == NULL)
00174 ProbesPrintVal(dest, *tr->ptra);
00175 else {
00176 if ((int64_t)(*tr->ptrb) > 0) {
00177 float ratio = double((int64_t)*tr->ptra) / double((int64_t)*tr->ptrb);
00178 ProbesPrintVal(dest, *tr->ptra, *tr->ptrb);
00179 if (tr->percentage)
00180 fprintf(dest, " (%3.2f%%)", 100. * ratio);
00181 else
00182 fprintf(dest, " (%.2fx)", ratio);
00183 }
00184 else
00185 ProbesPrintVal(dest, *tr->ptra, *tr->ptrb);
00186 }
00187 fprintf(dest, "\n");
00188 ++iter;
00189 }
00190 }
00191
00192
00193 static void ProbesPrintVal(FILE *f, const StatsCounterType &v) {
00194 #if defined(PBRT_IS_WINDOWS)
00195 LONG vv = v;
00196 fprintf(f, "%d", vv);
00197 #else
00198 #ifdef PBRT_HAS_64_BIT_ATOMICS
00199 int64_t vv = v;
00200 fprintf(f, "%lld", vv);
00201 #else
00202 int32_t vv = v;
00203 fprintf(f, "%d", vv);
00204 #endif
00205 #endif
00206 }
00207
00208
00209 static void ProbesPrintVal(FILE *f, const StatsCounterType &v1,
00210 const StatsCounterType &v2) {
00211 #if defined(PBRT_IS_WINDOWS)
00212 LONG vv1 = v1, vv2 = v2;
00213 fprintf(f, "%d:%d", vv1, vv2);
00214 #else
00215 #ifdef PBRT_HAS_64_BIT_ATOMICS
00216 int64_t vv1 = v1, vv2 = v2;
00217 fprintf(f, "%lld:%lld", vv1, vv2);
00218 #else
00219 int32_t vv1 = v1, vv2 = v2;
00220 fprintf(f, "%d:%d", vv1, vv2);
00221 #endif
00222 #endif
00223 }
00224
00225
00226 void ProbesCleanup() {
00227 TrackerMap::iterator iter = trackers.begin();
00228 string lastCategory;
00229 while (iter != trackers.end()) {
00230 delete iter->second;
00231 ++iter;
00232 }
00233 trackers.erase(trackers.begin(), trackers.end());
00234 }
00235
00236
00237 StatTracker::StatTracker(const string &cat, const string &n,
00238 StatsCounterType *pa, StatsCounterType *pb, bool p) {
00239 category = cat;
00240 name = n;
00241 ptra = pa;
00242 ptrb = pb;
00243 percentage = p;
00244 }
00245
00246
00247 StatsCounter::StatsCounter(const string &category, const string &name) {
00248 num = 0;
00249 addTracker(new StatTracker(category, name, &num));
00250 }
00251
00252
00253 StatsRatio::StatsRatio(const string &category, const string &name) {
00254 na = nb = 0;
00255 addTracker(new StatTracker(category, name, &na, &nb, false));
00256 }
00257
00258
00259 StatsPercentage::StatsPercentage(const string &category, const string &name) {
00260 addTracker(new StatTracker(category, name, &na, &nb, true));
00261 }
00262
00263
00264
00265
00266 static StatsCounter shapesMade("Shapes", "Total Shapes Created");
00267 static StatsCounter trianglesMade("Shapes", "Total Triangles Created");
00268 static StatsCounter cameraRays("Rays", "Camera Rays Traced");
00269 static StatsCounter specularReflectionRays("Rays", "Specular Reflection Rays Traced");
00270 static StatsCounter specularRefractionRays("Rays", "Specular Refraction Rays Traced");
00271 static StatsCounter shadowRays("Rays", "Shadow Rays Traced");
00272 static StatsCounter nonShadowRays("Rays", "Total Non-Shadow Rays Traced");
00273 static StatsCounter kdTreeInteriorNodes("Kd-Tree", "Interior Nodes Created");
00274 static StatsCounter kdTreeLeafNodes("Kd-Tree", "Interior Nodes Created");
00275 static StatsCounter kdTreeMaxPrims("Kd-Tree", "Maximum Primitives in Leaf");
00276 static StatsCounter kdTreeMaxDepth("Kd-Tree", "Maximum Depth of Leaf Nodes");
00277 static StatsPercentage rayTriIntersections("Intersections", "Ray/Triangle Intersection Hits");
00278 static StatsPercentage rayTriIntersectionPs("Intersections", "Ray/Triangle IntersectionP Hits");
00279
00280
00281 void PBRT_CREATED_SHAPE(Shape *) {
00282 ++shapesMade;
00283 }
00284
00285
00286 void PBRT_CREATED_TRIANGLE(Triangle *) {
00287 ++trianglesMade;
00288 }
00289
00290
00291 void PBRT_STARTED_GENERATING_CAMERA_RAY(const CameraSample *) {
00292 ++cameraRays;
00293 }
00294
00295
00296
00297 void PBRT_KDTREE_CREATED_INTERIOR_NODE(int axis, float split) {
00298 ++kdTreeInteriorNodes;
00299 }
00300
00301
00302
00303 void PBRT_KDTREE_CREATED_LEAF(int nprims, int depth) {
00304 ++kdTreeLeafNodes;
00305 kdTreeMaxPrims.Max(nprims);
00306 kdTreeMaxDepth.Max(depth);
00307 }
00308
00309
00310
00311 void PBRT_RAY_TRIANGLE_INTERSECTION_TEST(const Ray *, const Triangle *) {
00312 rayTriIntersections.Add(0, 1);
00313 }
00314
00315
00316
00317 void PBRT_RAY_TRIANGLE_INTERSECTIONP_TEST(const Ray *, const Triangle *) {
00318 rayTriIntersectionPs.Add(0, 1);
00319 }
00320
00321
00322
00323 void PBRT_RAY_TRIANGLE_INTERSECTION_HIT(const Ray *, float t) {
00324 rayTriIntersections.Add(1, 0);
00325 }
00326
00327
00328
00329 void PBRT_RAY_TRIANGLE_INTERSECTIONP_HIT(const Ray *, float t) {
00330 rayTriIntersectionPs.Add(1, 0);
00331 }
00332
00333
00334
00335 void PBRT_FINISHED_RAY_INTERSECTION(const Ray *, const Intersection *, int hit) {
00336 ++nonShadowRays;
00337 }
00338
00339
00340
00341 void PBRT_FINISHED_RAY_INTERSECTIONP(const Ray *, int hit) {
00342 ++shadowRays;
00343 }
00344
00345
00346
00347 void PBRT_STARTED_SPECULAR_REFLECTION_RAY(const RayDifferential *) {
00348 ++specularReflectionRays;
00349 }
00350
00351
00352
00353 void PBRT_STARTED_SPECULAR_REFRACTION_RAY(const RayDifferential *) {
00354 ++specularRefractionRays;
00355 }
00356
00357
00358 #endif // PBRT_PROBES_COUNTERS