Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'intern/cycles/device/device_multi.cpp')
-rw-r--r--intern/cycles/device/device_multi.cpp136
1 files changed, 115 insertions, 21 deletions
diff --git a/intern/cycles/device/device_multi.cpp b/intern/cycles/device/device_multi.cpp
index b8587eb0a62..9cbf69a191a 100644
--- a/intern/cycles/device/device_multi.cpp
+++ b/intern/cycles/device/device_multi.cpp
@@ -42,7 +42,7 @@ class MultiDevice : public Device {
map<device_ptr, device_ptr> ptr_map;
};
- list<SubDevice> devices;
+ list<SubDevice> devices, denoising_devices;
device_ptr unique_key;
MultiDevice(DeviceInfo &info, Stats &stats, Profiler &profiler, bool background_)
@@ -61,6 +61,12 @@ class MultiDevice : public Device {
}
}
+ foreach (DeviceInfo &subinfo, info.denoising_devices) {
+ Device *device = Device::create(subinfo, sub_stats_, profiler, background);
+
+ denoising_devices.push_back(SubDevice(device));
+ }
+
#ifdef WITH_NETWORK
/* try to add network devices */
ServerDiscovery discovery(true);
@@ -80,17 +86,18 @@ class MultiDevice : public Device {
{
foreach (SubDevice &sub, devices)
delete sub.device;
+ foreach (SubDevice &sub, denoising_devices)
+ delete sub.device;
}
const string &error_message()
{
- foreach (SubDevice &sub, devices) {
- if (sub.device->error_message() != "") {
- if (error_msg == "")
- error_msg = sub.device->error_message();
- break;
- }
- }
+ error_msg.clear();
+
+ foreach (SubDevice &sub, devices)
+ error_msg += sub.device->error_message();
+ foreach (SubDevice &sub, denoising_devices)
+ error_msg += sub.device->error_message();
return error_msg;
}
@@ -118,6 +125,12 @@ class MultiDevice : public Device {
if (!sub.device->load_kernels(requested_features))
return false;
+ if (requested_features.use_denoising) {
+ foreach (SubDevice &sub, denoising_devices)
+ if (!sub.device->load_kernels(requested_features))
+ return false;
+ }
+
return true;
}
@@ -127,6 +140,12 @@ class MultiDevice : public Device {
if (!sub.device->wait_for_availability(requested_features))
return false;
+ if (requested_features.use_denoising) {
+ foreach (SubDevice &sub, denoising_devices)
+ if (!sub.device->wait_for_availability(requested_features))
+ return false;
+ }
+
return true;
}
@@ -150,16 +169,17 @@ class MultiDevice : public Device {
break;
}
}
+
return result;
}
bool build_optix_bvh(BVH *bvh)
{
- // Broadcast acceleration structure build to all devices
- foreach (SubDevice &sub, devices) {
+ // Broadcast acceleration structure build to all render devices
+ foreach (SubDevice &sub, devices)
if (!sub.device->build_optix_bvh(bvh))
return false;
- }
+
return true;
}
@@ -236,6 +256,17 @@ class MultiDevice : public Device {
sub.ptr_map[key] = mem.device_pointer;
}
+ if (strcmp(mem.name, "RenderBuffers") == 0) {
+ foreach (SubDevice &sub, denoising_devices) {
+ mem.device = sub.device;
+ mem.device_pointer = (existing_key) ? sub.ptr_map[existing_key] : 0;
+ mem.device_size = existing_size;
+
+ sub.device->mem_zero(mem);
+ sub.ptr_map[key] = mem.device_pointer;
+ }
+ }
+
mem.device = this;
mem.device_pointer = key;
stats.mem_alloc(mem.device_size - existing_size);
@@ -255,6 +286,17 @@ class MultiDevice : public Device {
sub.ptr_map.erase(sub.ptr_map.find(key));
}
+ if (strcmp(mem.name, "RenderBuffers") == 0) {
+ foreach (SubDevice &sub, denoising_devices) {
+ mem.device = sub.device;
+ mem.device_pointer = sub.ptr_map[key];
+ mem.device_size = existing_size;
+
+ sub.device->mem_free(mem);
+ sub.ptr_map.erase(sub.ptr_map.find(key));
+ }
+ }
+
mem.device = this;
mem.device_pointer = 0;
mem.device_size = 0;
@@ -302,10 +344,21 @@ class MultiDevice : public Device {
void map_tile(Device *sub_device, RenderTile &tile)
{
+ if (!tile.buffer) {
+ return;
+ }
+
foreach (SubDevice &sub, devices) {
if (sub.device == sub_device) {
- if (tile.buffer)
- tile.buffer = sub.ptr_map[tile.buffer];
+ tile.buffer = sub.ptr_map[tile.buffer];
+ return;
+ }
+ }
+
+ foreach (SubDevice &sub, denoising_devices) {
+ if (sub.device == sub_device) {
+ tile.buffer = sub.ptr_map[tile.buffer];
+ return;
}
}
}
@@ -320,6 +373,12 @@ class MultiDevice : public Device {
i++;
}
+ foreach (SubDevice &sub, denoising_devices) {
+ if (sub.device == sub_device)
+ return i;
+ i++;
+ }
+
return -1;
}
@@ -330,11 +389,20 @@ class MultiDevice : public Device {
continue;
}
+ device_vector<float> &mem = tiles[i].buffers->buffer;
+ tiles[i].buffer = mem.device_pointer;
+
+ if (mem.device == this && denoising_devices.empty()) {
+ /* Skip unnecessary copies in viewport mode (buffer covers the
+ * whole image), but still need to fix up the tile evice pointer. */
+ map_tile(sub_device, tiles[i]);
+ continue;
+ }
+
/* If the tile was rendered on another device, copy its memory to
* to the current device now, for the duration of the denoising task.
* Note that this temporarily modifies the RenderBuffers and calls
* the device, so this function is not thread safe. */
- device_vector<float> &mem = tiles[i].buffers->buffer;
if (mem.device != sub_device) {
/* Only copy from device to host once. This is faster, but
* also required for the case where a CPU thread is denoising
@@ -342,12 +410,20 @@ class MultiDevice : public Device {
* overwriting the buffer being denoised by the CPU thread. */
if (!tiles[i].buffers->map_neighbor_copied) {
tiles[i].buffers->map_neighbor_copied = true;
- mem.copy_from_device(0, mem.data_size, 1);
+ mem.copy_from_device();
}
- mem.swap_device(sub_device, 0, 0);
+ if (mem.device == this) {
+ /* Can re-use memory if tile is already allocated on the sub device. */
+ map_tile(sub_device, tiles[i]);
+ mem.swap_device(sub_device, mem.device_size, tiles[i].buffer);
+ }
+ else {
+ mem.swap_device(sub_device, 0, 0);
+ }
mem.copy_to_device();
+
tiles[i].buffer = mem.device_pointer;
tiles[i].device_size = mem.device_size;
@@ -358,11 +434,17 @@ class MultiDevice : public Device {
void unmap_neighbor_tiles(Device *sub_device, RenderTile *tiles)
{
- /* Copy denoised result back to the host. */
device_vector<float> &mem = tiles[9].buffers->buffer;
+
+ if (mem.device == this && denoising_devices.empty()) {
+ return;
+ }
+
+ /* Copy denoised result back to the host. */
mem.swap_device(sub_device, tiles[9].device_size, tiles[9].buffer);
- mem.copy_from_device(0, mem.data_size, 1);
+ mem.copy_from_device();
mem.restore_device();
+
/* Copy denoised result to the original device. */
mem.copy_to_device();
@@ -372,7 +454,9 @@ class MultiDevice : public Device {
}
device_vector<float> &mem = tiles[i].buffers->buffer;
- if (mem.device != sub_device) {
+
+ if (mem.device != sub_device && mem.device != this) {
+ /* Free up memory again if it was allocated for the copy above. */
mem.swap_device(sub_device, tiles[i].device_size, tiles[i].buffer);
sub_device->mem_free(mem);
mem.restore_device();
@@ -398,10 +482,16 @@ class MultiDevice : public Device {
void task_add(DeviceTask &task)
{
+ list<SubDevice> &task_devices = denoising_devices.empty() ||
+ (task.type != DeviceTask::DENOISE &&
+ task.type != DeviceTask::DENOISE_BUFFER) ?
+ devices :
+ denoising_devices;
+
list<DeviceTask> tasks;
- task.split(tasks, devices.size());
+ task.split(tasks, task_devices.size());
- foreach (SubDevice &sub, devices) {
+ foreach (SubDevice &sub, task_devices) {
if (!tasks.empty()) {
DeviceTask subtask = tasks.front();
tasks.pop_front();
@@ -426,12 +516,16 @@ class MultiDevice : public Device {
{
foreach (SubDevice &sub, devices)
sub.device->task_wait();
+ foreach (SubDevice &sub, denoising_devices)
+ sub.device->task_wait();
}
void task_cancel()
{
foreach (SubDevice &sub, devices)
sub.device->task_cancel();
+ foreach (SubDevice &sub, denoising_devices)
+ sub.device->task_cancel();
}
protected: