Blender  V3.3
stats.cpp
Go to the documentation of this file.
1 /* SPDX-License-Identifier: Apache-2.0
2  * Copyright 2011-2022 Blender Foundation */
3 
4 #include "scene/stats.h"
5 #include "scene/object.h"
6 #include "util/algorithm.h"
7 #include "util/foreach.h"
8 #include "util/string.h"
9 
11 
12 static int kIndentNumSpaces = 2;
13 
14 /* Named size entry. */
15 
16 namespace {
17 
18 bool namedSizeEntryComparator(const NamedSizeEntry &a, const NamedSizeEntry &b)
19 {
20  /* We sort in descending order. */
21  return a.size > b.size;
22 }
23 
24 bool namedTimeEntryComparator(const NamedTimeEntry &a, const NamedTimeEntry &b)
25 {
26  /* We sort in descending order. */
27  return a.time > b.time;
28 }
29 
30 bool namedTimeSampleEntryComparator(const NamedNestedSampleStats &a,
32 {
33  return a.sum_samples > b.sum_samples;
34 }
35 
36 bool namedSampleCountPairComparator(const NamedSampleCountPair &a, const NamedSampleCountPair &b)
37 {
38  return a.samples > b.samples;
39 }
40 
41 } // namespace
42 
44 {
45 }
46 
47 NamedSizeEntry::NamedSizeEntry(const string &name, size_t size) : name(name), size(size)
48 {
49 }
50 
52 {
53 }
54 
55 NamedTimeEntry::NamedTimeEntry(const string &name, double time) : name(name), time(time)
56 {
57 }
58 
59 /* Named size statistics. */
60 
62 {
63 }
64 
66 {
67  total_size += entry.size;
68  entries.push_back(entry);
69 }
70 
71 string NamedSizeStats::full_report(int indent_level)
72 {
73  const string indent(indent_level * kIndentNumSpaces, ' ');
74  const string double_indent = indent + indent;
75  string result = "";
76  result += string_printf("%sTotal memory: %s (%s)\n",
77  indent.c_str(),
80  sort(entries.begin(), entries.end(), namedSizeEntryComparator);
81  foreach (const NamedSizeEntry &entry, entries) {
82  result += string_printf("%s%-32s %s (%s)\n",
83  double_indent.c_str(),
84  entry.name.c_str(),
85  string_human_readable_size(entry.size).c_str(),
86  string_human_readable_number(entry.size).c_str());
87  }
88  return result;
89 }
90 
91 string NamedTimeStats::full_report(int indent_level)
92 {
93  const string indent(indent_level * kIndentNumSpaces, ' ');
94  const string double_indent = indent + indent;
95  string result = "";
96  result += string_printf("%sTotal time: %fs\n", indent.c_str(), total_time);
97  sort(entries.begin(), entries.end(), namedTimeEntryComparator);
98  foreach (const NamedTimeEntry &entry, entries) {
100  "%s%-40s %fs\n", double_indent.c_str(), entry.name.c_str(), entry.time);
101  }
102  return result;
103 }
104 
105 /* Named time sample statistics. */
106 
107 NamedNestedSampleStats::NamedNestedSampleStats() : name(""), self_samples(0), sum_samples(0)
108 {
109 }
110 
112  : name(name), self_samples(samples), sum_samples(samples)
113 {
114 }
115 
117 {
118  entries.push_back(NamedNestedSampleStats(name_, samples_));
119  return entries[entries.size() - 1];
120 }
121 
123 {
125  foreach (NamedNestedSampleStats &entry, entries) {
126  entry.update_sum();
127  sum_samples += entry.sum_samples;
128  }
129 }
130 
131 string NamedNestedSampleStats::full_report(int indent_level, uint64_t total_samples)
132 {
133  update_sum();
134 
135  if (total_samples == 0) {
136  total_samples = sum_samples;
137  }
138 
139  const string indent(indent_level * kIndentNumSpaces, ' ');
140 
141  const double sum_percent = 100 * ((double)sum_samples) / total_samples;
142  const double sum_seconds = sum_samples * 0.001;
143  const double self_percent = 100 * ((double)self_samples) / total_samples;
144  const double self_seconds = self_samples * 0.001;
145  string info = string_printf("%-32s: Total %3.2f%% (%.2fs), Self %3.2f%% (%.2fs)\n",
146  name.c_str(),
147  sum_percent,
148  sum_seconds,
149  self_percent,
150  self_seconds);
151  string result = indent + info;
152 
153  sort(entries.begin(), entries.end(), namedTimeSampleEntryComparator);
154  foreach (NamedNestedSampleStats &entry, entries) {
155  result += entry.full_report(indent_level + 1, total_samples);
156  }
157  return result;
158 }
159 
160 /* Named sample count pairs. */
161 
163  : name(name), samples(samples), hits(hits)
164 {
165 }
166 
168 {
169 }
170 
171 void NamedSampleCountStats::add(const ustring &name, uint64_t samples, uint64_t hits)
172 {
173  entry_map::iterator entry = entries.find(name);
174  if (entry != entries.end()) {
175  entry->second.samples += samples;
176  entry->second.hits += hits;
177  return;
178  }
179  entries.emplace(name, NamedSampleCountPair(name, samples, hits));
180 }
181 
182 string NamedSampleCountStats::full_report(int indent_level)
183 {
184  const string indent(indent_level * kIndentNumSpaces, ' ');
185 
186  vector<NamedSampleCountPair> sorted_entries;
187  sorted_entries.reserve(entries.size());
188 
189  uint64_t total_hits = 0, total_samples = 0;
190  foreach (entry_map::const_reference entry, entries) {
191  const NamedSampleCountPair &pair = entry.second;
192 
193  total_hits += pair.hits;
194  total_samples += pair.samples;
195 
196  sorted_entries.push_back(pair);
197  }
198  const double avg_samples_per_hit = ((double)total_samples) / total_hits;
199 
200  sort(sorted_entries.begin(), sorted_entries.end(), namedSampleCountPairComparator);
201 
202  string result = "";
203  foreach (const NamedSampleCountPair &entry, sorted_entries) {
204  const double seconds = entry.samples * 0.001;
205  const double relative = ((double)entry.samples) / (entry.hits * avg_samples_per_hit);
206 
207  result += indent +
209  "%-32s: %.2fs (Relative cost: %.2f)\n", entry.name.c_str(), seconds, relative);
210  }
211  return result;
212 }
213 
214 /* Mesh statistics. */
215 
217 {
218 }
219 
220 string MeshStats::full_report(int indent_level)
221 {
222  const string indent(indent_level * kIndentNumSpaces, ' ');
223  string result = "";
224  result += indent + "Geometry:\n" + geometry.full_report(indent_level + 1);
225  return result;
226 }
227 
228 /* Image statistics. */
229 
231 {
232 }
233 
234 string ImageStats::full_report(int indent_level)
235 {
236  const string indent(indent_level * kIndentNumSpaces, ' ');
237  string result = "";
238  result += indent + "Textures:\n" + textures.full_report(indent_level + 1);
239  return result;
240 }
241 
242 /* Overall statistics. */
243 
245 {
246  has_profiling = false;
247 }
248 
250 {
251  has_profiling = true;
252 
253  kernel = NamedNestedSampleStats("Total render time", prof.get_event(PROFILING_UNKNOWN));
254  kernel.add_entry("Ray setup", prof.get_event(PROFILING_RAY_SETUP));
255  kernel.add_entry("Intersect Closest", prof.get_event(PROFILING_INTERSECT_CLOSEST));
256  kernel.add_entry("Intersect Shadow", prof.get_event(PROFILING_INTERSECT_SHADOW));
257  kernel.add_entry("Intersect Subsurface", prof.get_event(PROFILING_INTERSECT_SUBSURFACE));
258  kernel.add_entry("Intersect Volume Stack", prof.get_event(PROFILING_INTERSECT_VOLUME_STACK));
259 
260  NamedNestedSampleStats &surface = kernel.add_entry("Shade Surface", 0);
261  surface.add_entry("Setup", prof.get_event(PROFILING_SHADE_SURFACE_SETUP));
262  surface.add_entry("Shader Evaluation", prof.get_event(PROFILING_SHADE_SURFACE_EVAL));
263  surface.add_entry("Render Passes", prof.get_event(PROFILING_SHADE_SURFACE_PASSES));
264  surface.add_entry("Direct Light", prof.get_event(PROFILING_SHADE_SURFACE_DIRECT_LIGHT));
265  surface.add_entry("Indirect Light", prof.get_event(PROFILING_SHADE_SURFACE_INDIRECT_LIGHT));
266  surface.add_entry("Ambient Occlusion", prof.get_event(PROFILING_SHADE_SURFACE_AO));
267 
268  NamedNestedSampleStats &volume = kernel.add_entry("Shade Volume", 0);
269  volume.add_entry("Setup", prof.get_event(PROFILING_SHADE_VOLUME_SETUP));
270  volume.add_entry("Integrate", prof.get_event(PROFILING_SHADE_VOLUME_INTEGRATE));
271  volume.add_entry("Direct Light", prof.get_event(PROFILING_SHADE_VOLUME_DIRECT_LIGHT));
272  volume.add_entry("Indirect Light", prof.get_event(PROFILING_SHADE_VOLUME_INDIRECT_LIGHT));
273 
274  NamedNestedSampleStats &shadow = kernel.add_entry("Shade Shadow", 0);
275  shadow.add_entry("Setup", prof.get_event(PROFILING_SHADE_SHADOW_SETUP));
276  shadow.add_entry("Surface", prof.get_event(PROFILING_SHADE_SHADOW_SURFACE));
277  shadow.add_entry("Volume", prof.get_event(PROFILING_SHADE_SHADOW_VOLUME));
278 
279  NamedNestedSampleStats &light = kernel.add_entry("Shade Light", 0);
280  light.add_entry("Setup", prof.get_event(PROFILING_SHADE_LIGHT_SETUP));
281  light.add_entry("Shader Evaluation", prof.get_event(PROFILING_SHADE_LIGHT_EVAL));
282 
283  shaders.entries.clear();
284  foreach (Shader *shader, scene->shaders) {
285  uint64_t samples, hits;
286  if (prof.get_shader(shader->id, samples, hits)) {
287  shaders.add(shader->name, samples, hits);
288  }
289  }
290 
291  objects.entries.clear();
292  foreach (Object *object, scene->objects) {
293  uint64_t samples, hits;
294  if (prof.get_object(object->get_device_index(), samples, hits)) {
295  objects.add(object->name, samples, hits);
296  }
297  }
298 }
299 
301 {
302  string result = "";
303  result += "Mesh statistics:\n" + mesh.full_report(1);
304  result += "Image statistics:\n" + image.full_report(1);
305  if (has_profiling) {
306  result += "Kernel statistics:\n" + kernel.full_report(1);
307  result += "Shader statistics:\n" + shaders.full_report(1);
308  result += "Object statistics:\n" + objects.full_report(1);
309  }
310  else {
311  result += "Profiling information not available (only works with CPU rendering)";
312  }
313  return result;
314 }
315 
317 {
318 }
319 
320 string UpdateTimeStats::full_report(int indent_level)
321 {
322  return times.full_report(indent_level + 1);
323 }
324 
326 {
327 }
328 
330 {
331  string result = "";
332  result += "Scene:\n" + scene.full_report(1);
333  result += "Geometry:\n" + geometry.full_report(1);
334  result += "Light:\n" + light.full_report(1);
335  result += "Object:\n" + object.full_report(1);
336  result += "Image:\n" + image.full_report(1);
337  result += "Background:\n" + background.full_report(1);
338  result += "Bake:\n" + bake.full_report(1);
339  result += "Camera:\n" + camera.full_report(1);
340  result += "Film:\n" + film.full_report(1);
341  result += "Integrator:\n" + integrator.full_report(1);
342  result += "OSL:\n" + osl.full_report(1);
343  result += "Particles:\n" + particles.full_report(1);
344  result += "SVM:\n" + svm.full_report(1);
345  result += "Tables:\n" + tables.full_report(1);
346  result += "Procedurals:\n" + procedurals.full_report(1);
347  return result;
348 }
349 
351 {
352  geometry.times.clear();
353  image.times.clear();
354  light.times.clear();
355  object.times.clear();
357  bake.times.clear();
358  camera.times.clear();
359  film.times.clear();
361  osl.times.clear();
363  scene.times.clear();
364  svm.times.clear();
365  tables.times.clear();
367 }
368 
typedef double(DMatrix)[4][4]
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition: btDbvt.cpp:52
void sort(btMatrix3x3 &U, btVector3 &sigma, btMatrix3x3 &V, int t)
Helper function of 3X3 SVD for sorting singular values.
string full_report(int indent_level=0)
Definition: stats.cpp:234
NamedSizeStats textures
Definition: scene/stats.h:160
ImageStats()
Definition: stats.cpp:230
NamedSizeStats geometry
Definition: scene/stats.h:149
MeshStats()
Definition: stats.cpp:216
string full_report(int indent_level=0)
Definition: stats.cpp:220
string full_report(int indent_level=0, uint64_t total_samples=0)
Definition: stats.cpp:131
vector< NamedNestedSampleStats > entries
Definition: scene/stats.h:110
NamedNestedSampleStats & add_entry(const string &name, uint64_t samples)
Definition: stats.cpp:116
NamedSampleCountPair(const ustring &name, uint64_t samples, uint64_t hits)
Definition: stats.cpp:162
string full_report(int indent_level=0)
Definition: stats.cpp:182
void add(const ustring &name, uint64_t samples, uint64_t hits)
Definition: stats.cpp:171
NamedSizeEntry()
Definition: stats.cpp:43
void add_entry(const NamedSizeEntry &entry)
Definition: stats.cpp:65
size_t total_size
Definition: scene/stats.h:55
string full_report(int indent_level=0)
Definition: stats.cpp:71
NamedSizeStats()
Definition: stats.cpp:61
vector< NamedSizeEntry > entries
Definition: scene/stats.h:60
NamedTimeEntry()
Definition: stats.cpp:51
double total_time
Definition: scene/stats.h:78
string full_report(int indent_level=0)
Definition: stats.cpp:91
vector< NamedTimeEntry > entries
Definition: scene/stats.h:83
uint64_t get_event(ProfilingEvent event)
Definition: profiling.cpp:133
bool get_shader(int shader, uint64_t &samples, uint64_t &hits)
Definition: profiling.cpp:139
bool get_object(int object, uint64_t &samples, uint64_t &hits)
Definition: profiling.cpp:150
UpdateTimeStats tables
Definition: scene/stats.h:208
UpdateTimeStats image
Definition: scene/stats.h:196
UpdateTimeStats background
Definition: scene/stats.h:199
UpdateTimeStats light
Definition: scene/stats.h:197
UpdateTimeStats bake
Definition: scene/stats.h:200
UpdateTimeStats film
Definition: scene/stats.h:202
UpdateTimeStats camera
Definition: scene/stats.h:201
UpdateTimeStats geometry
Definition: scene/stats.h:195
string full_report()
Definition: stats.cpp:329
UpdateTimeStats particles
Definition: scene/stats.h:205
UpdateTimeStats procedurals
Definition: scene/stats.h:209
UpdateTimeStats integrator
Definition: scene/stats.h:203
UpdateTimeStats osl
Definition: scene/stats.h:204
void clear()
Definition: stats.cpp:350
UpdateTimeStats scene
Definition: scene/stats.h:206
UpdateTimeStats svm
Definition: scene/stats.h:207
uint id
Definition: scene/shader.h:121
NamedTimeStats times
Definition: scene/stats.h:188
string full_report(int indent_level=0)
Definition: stats.cpp:320
#define CCL_NAMESPACE_END
Definition: cuda/compat.h:9
double time
Scene scene
struct @211::@212 surface
static unsigned a[3]
Definition: RandGen.cpp:78
static const pxr::TfToken b("b", pxr::TfToken::Immortal)
static CCL_NAMESPACE_BEGIN int kIndentNumSpaces
Definition: stats.cpp:12
unsigned __int64 uint64_t
Definition: stdint.h:90
string string_human_readable_size(size_t size)
Definition: string.cpp:229
string string_human_readable_number(size_t num)
Definition: string.cpp:248
CCL_NAMESPACE_BEGIN string string_printf(const char *format,...)
Definition: string.cpp:22
ustring name
Definition: graph/node.h:174
int get_device_index() const
void collect_profiling(Scene *scene, Profiler &prof)
Definition: stats.cpp:249
bool has_profiling
Definition: scene/stats.h:174
string full_report()
Definition: stats.cpp:300
NamedSampleCountStats shaders
Definition: scene/stats.h:179
NamedNestedSampleStats kernel
Definition: scene/stats.h:178
MeshStats mesh
Definition: scene/stats.h:176
RenderStats()
Definition: stats.cpp:244
ImageStats image
Definition: scene/stats.h:177
NamedSampleCountStats objects
Definition: scene/stats.h:180
vector< Shader * > shaders
Definition: scene.h:215
vector< Object * > objects
Definition: scene.h:213
@ PROFILING_SHADE_SURFACE_SETUP
@ PROFILING_SHADE_SHADOW_SURFACE
@ PROFILING_SHADE_VOLUME_INTEGRATE
@ PROFILING_SHADE_SHADOW_VOLUME
@ PROFILING_INTERSECT_SUBSURFACE
@ PROFILING_INTERSECT_SHADOW
@ PROFILING_INTERSECT_CLOSEST
@ PROFILING_SHADE_VOLUME_SETUP
@ PROFILING_SHADE_SURFACE_EVAL
@ PROFILING_SHADE_SURFACE_INDIRECT_LIGHT
@ PROFILING_SHADE_SURFACE_AO
@ PROFILING_SHADE_SURFACE_DIRECT_LIGHT
@ PROFILING_SHADE_LIGHT_SETUP
@ PROFILING_RAY_SETUP
@ PROFILING_SHADE_SHADOW_SETUP
@ PROFILING_INTERSECT_VOLUME_STACK
@ PROFILING_SHADE_VOLUME_DIRECT_LIGHT
@ PROFILING_UNKNOWN
@ PROFILING_SHADE_SURFACE_PASSES
@ PROFILING_SHADE_LIGHT_EVAL
@ PROFILING_SHADE_VOLUME_INDIRECT_LIGHT