util_profiling.h 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. /*
  2. * Copyright 2011-2018 Blender Foundation
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. #ifndef __UTIL_PROFILING_H__
  17. #define __UTIL_PROFILING_H__
  18. #include <atomic>
  19. #include "util/util_foreach.h"
  20. #include "util/util_map.h"
  21. #include "util/util_thread.h"
  22. #include "util/util_vector.h"
  23. CCL_NAMESPACE_BEGIN
  24. enum ProfilingEvent : uint32_t {
  25. PROFILING_UNKNOWN,
  26. PROFILING_RAY_SETUP,
  27. PROFILING_PATH_INTEGRATE,
  28. PROFILING_SCENE_INTERSECT,
  29. PROFILING_INDIRECT_EMISSION,
  30. PROFILING_VOLUME,
  31. PROFILING_SHADER_SETUP,
  32. PROFILING_SHADER_EVAL,
  33. PROFILING_SHADER_APPLY,
  34. PROFILING_AO,
  35. PROFILING_SUBSURFACE,
  36. PROFILING_CONNECT_LIGHT,
  37. PROFILING_SURFACE_BOUNCE,
  38. PROFILING_WRITE_RESULT,
  39. PROFILING_INTERSECT,
  40. PROFILING_INTERSECT_LOCAL,
  41. PROFILING_INTERSECT_SHADOW_ALL,
  42. PROFILING_INTERSECT_VOLUME,
  43. PROFILING_INTERSECT_VOLUME_ALL,
  44. PROFILING_CLOSURE_EVAL,
  45. PROFILING_CLOSURE_SAMPLE,
  46. PROFILING_CLOSURE_VOLUME_EVAL,
  47. PROFILING_CLOSURE_VOLUME_SAMPLE,
  48. PROFILING_DENOISING,
  49. PROFILING_DENOISING_CONSTRUCT_TRANSFORM,
  50. PROFILING_DENOISING_RECONSTRUCT,
  51. PROFILING_DENOISING_DIVIDE_SHADOW,
  52. PROFILING_DENOISING_NON_LOCAL_MEANS,
  53. PROFILING_DENOISING_COMBINE_HALVES,
  54. PROFILING_DENOISING_GET_FEATURE,
  55. PROFILING_DENOISING_DETECT_OUTLIERS,
  56. PROFILING_NUM_EVENTS,
  57. };
  58. /* Contains the current execution state of a worker thread.
  59. * These values are constantly updated by the worker.
  60. * Periodically the profiler thread will wake up, read them
  61. * and update its internal counters based on it.
  62. *
  63. * Atomics aren't needed here since we're only doing direct
  64. * writes and reads to (4-byte-aligned) uint32_t, which is
  65. * guaranteed to be atomic on x86 since the 486.
  66. * Memory ordering is not guaranteed but does not matter.
  67. *
  68. * And even on other architectures, the extremely rare corner
  69. * case of reading an intermediate state could at worst result
  70. * in a single incorrect sample. */
  71. struct ProfilingState {
  72. volatile uint32_t event = PROFILING_UNKNOWN;
  73. volatile int32_t shader = -1;
  74. volatile int32_t object = -1;
  75. volatile bool active = false;
  76. vector<uint64_t> shader_hits;
  77. vector<uint64_t> object_hits;
  78. };
  79. class Profiler {
  80. public:
  81. Profiler();
  82. ~Profiler();
  83. void reset(int num_shaders, int num_objects);
  84. void start();
  85. void stop();
  86. void add_state(ProfilingState *state);
  87. void remove_state(ProfilingState *state);
  88. uint64_t get_event(ProfilingEvent event);
  89. bool get_shader(int shader, uint64_t &samples, uint64_t &hits);
  90. bool get_object(int object, uint64_t &samples, uint64_t &hits);
  91. protected:
  92. void run();
  93. /* Tracks how often the worker was in each ProfilingEvent while sampling,
  94. * so multiplying the values by the sample frequency (currently 1ms)
  95. * gives the approximate time spent in each state. */
  96. vector<uint64_t> event_samples;
  97. vector<uint64_t> shader_samples;
  98. vector<uint64_t> object_samples;
  99. /* Tracks the total amounts every object/shader was hit.
  100. * Used to evaluate relative cost, written by the render thread.
  101. * Indexed by the shader and object IDs that the kernel also uses
  102. * to index __object_flag and __shaders. */
  103. vector<uint64_t> shader_hits;
  104. vector<uint64_t> object_hits;
  105. volatile bool do_stop_worker;
  106. thread *worker;
  107. thread_mutex mutex;
  108. vector<ProfilingState *> states;
  109. };
  110. class ProfilingHelper {
  111. public:
  112. ProfilingHelper(ProfilingState *state, ProfilingEvent event) : state(state)
  113. {
  114. previous_event = state->event;
  115. state->event = event;
  116. }
  117. inline void set_event(ProfilingEvent event)
  118. {
  119. state->event = event;
  120. }
  121. inline void set_shader(int shader)
  122. {
  123. state->shader = shader;
  124. if (state->active) {
  125. assert(shader < state->shader_hits.size());
  126. state->shader_hits[shader]++;
  127. }
  128. }
  129. inline void set_object(int object)
  130. {
  131. state->object = object;
  132. if (state->active) {
  133. assert(object < state->object_hits.size());
  134. state->object_hits[object]++;
  135. }
  136. }
  137. ~ProfilingHelper()
  138. {
  139. state->event = previous_event;
  140. }
  141. private:
  142. ProfilingState *state;
  143. uint32_t previous_event;
  144. };
  145. CCL_NAMESPACE_END
  146. #endif /* __UTIL_PROFILING_H__ */