Alternative Upload geometry data in parallel to multiple GPUs using the "Multi-Device" #107552

Open
William Leeson wants to merge 137 commits from leesonw/blender-cluster:upload_changed into main

When changing the target branch, be careful to rebase the branch in your fork to match. See documentation.
1 changed files with 160 additions and 95 deletions
Showing only changes of commit bbce8a0aae - Show all commits

View File

@ -4,6 +4,15 @@
#ifndef __UTIL_PROGRESS_H__
#define __UTIL_PROGRESS_H__
//#define USE_SPINLOCK
#ifdef USE_SPINLOCK
#define MUTEX SpinLock
#define SCOPED_LOCK(mutex) ScopedSpinLock scopedspinlock(mutex)
#else
#define MUTEX thread_mutex
#define SCOPED_LOCK(mutex) thread_scoped_lock scopedlock(mutex)
#endif
/* Progress
*
* Simple class to communicate progress status messages, timing information,
@ -19,6 +28,45 @@
CCL_NAMESPACE_BEGIN
class SpinLock {
public:
SpinLock()
{
update_status = true;
};
void lock()
{
// Busy wait until update status is true
bool can_update = true;
while (!update_status.compare_exchange_weak(can_update, false)) {
};
};
void unlock()
{
update_status = true;
};
private:
std::atomic<bool> update_status;
};
class ScopedSpinLock {
public:
ScopedSpinLock(SpinLock &spinlock) : spinlock_(spinlock)
{
spinlock_.lock();
};
~ScopedSpinLock()
{
spinlock_.unlock();
}
private:
SpinLock &spinlock_;
};
class Progress {
public:
using callback_type = function<void()>;
@ -45,8 +93,8 @@ class Progress {
error_message = "";
cancel_cb = function_null;
updates = true;
update_call = true;
update_status = true;
// update_call = true;
// update_status = true;
}
Progress(Progress &progress)
@ -56,13 +104,14 @@ class Progress {
Progress &operator=(Progress &progress)
{
update_progress([this, &progress]() {
SCOPED_LOCK(progress_mutex);
//update_progress([this, &progress]() {
progress.get_status(status, substatus);
pixel_samples = progress.pixel_samples;
total_pixel_samples = progress.total_pixel_samples;
current_tile_sample = progress.get_current_sample();
});
//});
return *this;
}
@ -97,11 +146,11 @@ class Progress {
/* cancel */
void set_cancel(const string &cancel_message_)
{
update_progress([this, cancel_message_]() {
cancel_message = cancel_message_;
cancel = true;
update_status = true;
});
SCOPED_LOCK(progress_mutex);
//update_progress([this, cancel_message_]() {
cancel_message = cancel_message_;
cancel = true;
//});
}
bool get_cancel() const
@ -119,11 +168,12 @@ class Progress {
string get_cancel_message() //const
{
string msg;
update_progress([this, &msg]() {
msg = cancel_message;
});
return msg;
SCOPED_LOCK(progress_mutex);
//string msg;
//update_progress([this, &msg]() {
//msg = cancel_message;
//});
return cancel_message;
}
void set_cancel_callback(function<void()> function)
@ -134,13 +184,14 @@ class Progress {
/* error */
void set_error(const string &error_message_)
{
update_progress([this, error_message_]() {
error_message = error_message_;
error = true;
/* If error happens we also stop rendering. */
cancel_message = error_message_;
cancel = true;
});
SCOPED_LOCK(progress_mutex);
//update_progress([this, error_message_]() {
error_message = error_message_;
error = true;
/* If error happens we also stop rendering. */
cancel_message = error_message_;
cancel = true;
//});
}
bool get_error() const
@ -150,34 +201,39 @@ class Progress {
string get_error_message() // const
{
string msg;
update_progress([this, &msg]() {
msg = error_message;
update_status = true;
});
return msg;
SCOPED_LOCK(progress_mutex);
//string msg;
//update_progress([this, &msg]() {
//msg = error_message;
//});
return error_message;
}
/* tile and timing information */
void set_start_time()
{
update_progress([this]() {
start_time = time_dt();
end_time = 0.0;
});
SCOPED_LOCK(progress_mutex);
//update_progress([this]() {
start_time = time_dt();
end_time = 0.0;
//});
}
void set_render_start_time()
{
update_progress([this]() {
render_start_time = time_dt();
});
SCOPED_LOCK(progress_mutex);
//update_progress([this]() {
render_start_time = time_dt();
//});
}
void set_time_limit(double time_limit_)
{
update_progress([this, time_limit_]() { time_limit = time_limit_; });
SCOPED_LOCK(progress_mutex);
//update_progress([this, time_limit_]() {
time_limit = time_limit_;
//});
}
void add_skip_time(const scoped_timer &start_timer, bool only_render)
@ -192,13 +248,14 @@ class Progress {
void get_time(double &total_time_, double &render_time_) //const
{
update_progress([this, &total_time_, &render_time_](){
SCOPED_LOCK(progress_mutex);
//update_progress([this, &total_time_, &render_time_](){
double et = end_time;
double time = (et > 0) ? et : time_dt();
total_time_ = time - start_time;
render_time_ = time - render_start_time;
});
//});
}
void set_end_time()
@ -216,15 +273,17 @@ class Progress {
void set_total_pixel_samples(uint64_t total_pixel_samples_)
{
update_progress([this, total_pixel_samples_](){
SCOPED_LOCK(progress_mutex);
//update_progress([this, total_pixel_samples_](){
total_pixel_samples = total_pixel_samples_;
});
//});
}
double get_progress() //const
{
SCOPED_LOCK(progress_mutex);
double value = 0.0;
update_progress([this, &value]() {
//update_progress([this, &value]() {
if (pixel_samples > 0) {
double progress_percent = (double)pixel_samples / (double)total_pixel_samples;
if (time_limit != 0.0) {
@ -233,17 +292,18 @@ class Progress {
}
value = min(1.0, progress_percent);
}
});
//});
return value;
}
void add_samples(uint64_t pixel_samples_, int tile_sample)
{
update_progress([this, pixel_samples_, tile_sample]() {
SCOPED_LOCK(progress_mutex);
//update_progress([this, pixel_samples_, tile_sample]() {
pixel_samples += pixel_samples_;
current_tile_sample = tile_sample;
});
//});
}
void add_samples_update(uint64_t pixel_samples_, int tile_sample)
@ -254,55 +314,59 @@ class Progress {
void add_finished_tile(bool denoised)
{
update_progress([this, denoised]() {
SCOPED_LOCK(progress_mutex);
//update_progress([this, denoised]() {
if (denoised) {
denoised_tiles++;
}
else {
rendered_tiles++;
}
});
//});
}
int get_current_sample() //const
{
int sample;
update_progress([this, &sample]() {
SCOPED_LOCK(progress_mutex);
//int sample;
//update_progress([this, &sample]() {
/* Note that the value here always belongs to the last tile that updated,
* so it's only useful if there is only one active tile. */
sample = current_tile_sample;
});
return sample;
//sample = current_tile_sample;
//});
return current_tile_sample;
}
int get_rendered_tiles() //const
{
int tiles;
update_progress([this, &tiles]() {
tiles = rendered_tiles;
});
return tiles;
SCOPED_LOCK(progress_mutex);
//int tiles;
//update_progress([this, &tiles]() {
// tiles = rendered_tiles;
//});
return rendered_tiles;
}
int get_denoised_tiles() //const
{
int denoised;
update_progress([this, & denoised]() {
denoised = denoised_tiles;
});
return denoised;
SCOPED_LOCK(progress_mutex);
//int denoised;
//update_progress([this, & denoised]() {
// denoised = denoised_tiles;
//});
return denoised_tiles;
}
/* status messages */
void set_status(const string &status_, const string &substatus_ = "")
{
if(updates)
{
update_progress([this, status_, substatus_]() {
if(updates) {
SCOPED_LOCK(progress_mutex);
//update_progress([this, status_, substatus_]() {
status = status_;
substatus = substatus_;
});
//});
}
set_update();
@ -310,11 +374,11 @@ class Progress {
void set_substatus(const string &substatus_)
{
if(updates)
{
update_progress([this, substatus_]() {
if(updates) {
SCOPED_LOCK(progress_mutex);
//update_progress([this, substatus_]() {
substatus = substatus_;
});
//});
}
set_update();
@ -323,10 +387,11 @@ class Progress {
void set_sync_status(const string &status_, const string &substatus_ = "")
{
if(updates) {
update_progress([this, status_, substatus_]() {
sync_status = status_;
sync_substatus = substatus_;
});
SCOPED_LOCK(progress_mutex);
//update_progress([this, status_, substatus_]() {
sync_status = status_;
sync_substatus = substatus_;
//});
}
set_update();
@ -335,9 +400,10 @@ class Progress {
void set_sync_substatus(const string &substatus_)
{
if(updates) {
update_progress([this, substatus_]() {
sync_substatus = substatus_;
});
SCOPED_LOCK(progress_mutex);
//update_progress([this, substatus_]() {
sync_substatus = substatus_;
//});
}
set_update();
@ -345,7 +411,8 @@ class Progress {
void get_status(string &status_, string &substatus_) // const
{
update_progress([this, &status_, &substatus_]() {
SCOPED_LOCK(progress_mutex);
//update_progress([this, &status_, &substatus_]() {
if (sync_status != "") {
status_ = sync_status;
substatus_ = sync_substatus;
@ -354,7 +421,7 @@ class Progress {
status_ = status;
substatus_ = substatus;
}
});
//});
}
/* callback */
@ -362,11 +429,12 @@ class Progress {
void set_update()
{
if (updates && update_cb) {
SCOPED_LOCK(update_mutex);
// Busy wait until update status is true
bool can_update = true;
while(!update_call.compare_exchange_weak(can_update, false)) {};
//bool can_update = true;
//while(!update_call.compare_exchange_weak(can_update, false)) {};
update_cb();
update_call = true;
//update_call = true;
}
}
@ -375,20 +443,20 @@ class Progress {
update_cb = function;
}
void update_progress(callback_type cb)
{
// Busy wait until update status is true
bool can_update = true;
while(!update_status.compare_exchange_weak(can_update, false)) {};
if (cb) {
cb();
}
update_status = true;
}
// void update_progress(callback_type cb)
// {
// // Busy wait until update status is true
// bool can_update = true;
// while(!update_status.compare_exchange_weak(can_update, false)) {};
// if (cb) {
// cb();
// }
// update_status = true;
// }
protected:
//mutable thread_mutex progress_mutex;
//mutable thread_mutex update_mutex;
mutable MUTEX progress_mutex;
mutable MUTEX update_mutex;
function<void()> update_cb;
function<void()> cancel_cb;
@ -409,9 +477,6 @@ class Progress {
/* End time written when render is done, so it doesn't keep increasing on redraws. */
double end_time;
std::atomic<bool> update_call;
std::atomic<bool> update_status;
string status;
string substatus;