1a0bedd640
Some of the files are not accurate to blender-v4.3-release and not due to any goo engine additions Likely due to merges from beyond 4.3 that made it into 4.2 since it is an LTS and gets more support So merging these changes to keep it in line with the release version of 4.3
166 lines
4.0 KiB
C++
166 lines
4.0 KiB
C++
/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
|
|
*
|
|
* SPDX-License-Identifier: Apache-2.0 */
|
|
|
|
#include "util/profiling.h"
|
|
#include "util/algorithm.h"
|
|
#include "util/foreach.h"
|
|
#include "util/set.h"
|
|
|
|
CCL_NAMESPACE_BEGIN
|
|
|
|
Profiler::Profiler() : do_stop_worker(true), worker(NULL) {}
|
|
|
|
Profiler::~Profiler()
|
|
{
|
|
assert(worker == NULL);
|
|
}
|
|
|
|
void Profiler::run()
|
|
{
|
|
uint64_t updates = 0;
|
|
auto start_time = std::chrono::system_clock::now();
|
|
while (!do_stop_worker) {
|
|
thread_scoped_lock lock(mutex);
|
|
foreach (ProfilingState *state, states) {
|
|
uint32_t cur_event = state->event;
|
|
int32_t cur_shader = state->shader;
|
|
int32_t cur_object = state->object;
|
|
|
|
/* The state reads/writes should be atomic, but just to be sure
|
|
* check the values for validity anyways. */
|
|
if (cur_event < PROFILING_NUM_EVENTS) {
|
|
event_samples[cur_event]++;
|
|
}
|
|
|
|
if (cur_shader >= 0 && cur_shader < shader_samples.size()) {
|
|
shader_samples[cur_shader]++;
|
|
}
|
|
|
|
if (cur_object >= 0 && cur_object < object_samples.size()) {
|
|
object_samples[cur_object]++;
|
|
}
|
|
}
|
|
lock.unlock();
|
|
|
|
/* Relative waits always overshoot a bit, so just waiting 1ms every
|
|
* time would cause the sampling to drift over time.
|
|
* By keeping track of the absolute time, the wait times correct themselves -
|
|
* if one wait overshoots a lot, the next one will be shorter to compensate. */
|
|
updates++;
|
|
std::this_thread::sleep_until(start_time + updates * std::chrono::milliseconds(1));
|
|
}
|
|
}
|
|
|
|
void Profiler::reset(int num_shaders, int num_objects)
|
|
{
|
|
bool running = (worker != NULL);
|
|
if (running) {
|
|
stop();
|
|
}
|
|
|
|
/* Resize and clear the accumulation vectors. */
|
|
shader_hits.assign(num_shaders, 0);
|
|
object_hits.assign(num_objects, 0);
|
|
|
|
event_samples.assign(PROFILING_NUM_EVENTS, 0);
|
|
shader_samples.assign(num_shaders, 0);
|
|
object_samples.assign(num_objects, 0);
|
|
|
|
if (running) {
|
|
start();
|
|
}
|
|
}
|
|
|
|
void Profiler::start()
|
|
{
|
|
assert(worker == NULL);
|
|
do_stop_worker = false;
|
|
worker = new thread(function_bind(&Profiler::run, this));
|
|
}
|
|
|
|
void Profiler::stop()
|
|
{
|
|
if (worker != NULL) {
|
|
do_stop_worker = true;
|
|
|
|
worker->join();
|
|
delete worker;
|
|
worker = NULL;
|
|
}
|
|
}
|
|
|
|
void Profiler::add_state(ProfilingState *state)
|
|
{
|
|
thread_scoped_lock lock(mutex);
|
|
|
|
/* Add the ProfilingState from the list of sampled states. */
|
|
assert(std::find(states.begin(), states.end(), state) == states.end());
|
|
states.push_back(state);
|
|
|
|
/* Resize thread-local hit counters. */
|
|
state->shader_hits.assign(shader_hits.size(), 0);
|
|
state->object_hits.assign(object_hits.size(), 0);
|
|
|
|
/* Initialize the state. */
|
|
state->event = PROFILING_UNKNOWN;
|
|
state->shader = -1;
|
|
state->object = -1;
|
|
state->active = true;
|
|
}
|
|
|
|
void Profiler::remove_state(ProfilingState *state)
|
|
{
|
|
thread_scoped_lock lock(mutex);
|
|
|
|
/* Remove the ProfilingState from the list of sampled states. */
|
|
states.erase(std::remove(states.begin(), states.end(), state), states.end());
|
|
state->active = false;
|
|
|
|
/* Merge thread-local hit counters. */
|
|
assert(shader_hits.size() == state->shader_hits.size());
|
|
for (int i = 0; i < shader_hits.size(); i++) {
|
|
shader_hits[i] += state->shader_hits[i];
|
|
}
|
|
|
|
assert(object_hits.size() == state->object_hits.size());
|
|
for (int i = 0; i < object_hits.size(); i++) {
|
|
object_hits[i] += state->object_hits[i];
|
|
}
|
|
}
|
|
|
|
uint64_t Profiler::get_event(ProfilingEvent event)
|
|
{
|
|
assert(worker == NULL);
|
|
return event_samples[event];
|
|
}
|
|
|
|
bool Profiler::get_shader(int shader, uint64_t &samples, uint64_t &hits)
|
|
{
|
|
assert(worker == NULL);
|
|
if (shader_samples[shader] == 0) {
|
|
return false;
|
|
}
|
|
samples = shader_samples[shader];
|
|
hits = shader_hits[shader];
|
|
return true;
|
|
}
|
|
|
|
bool Profiler::get_object(int object, uint64_t &samples, uint64_t &hits)
|
|
{
|
|
assert(worker == NULL);
|
|
if (object_samples[object] == 0) {
|
|
return false;
|
|
}
|
|
samples = object_samples[object];
|
|
hits = object_hits[object];
|
|
return true;
|
|
}
|
|
|
|
bool Profiler::active() const
|
|
{
|
|
return (worker != nullptr);
|
|
}
|
|
|
|
CCL_NAMESPACE_END
|