[Bf-blender-cvs] [c189403126] cycles-tiles-rework: Cycles: Add functions to acquire multiple tiles at once
Mai Lavelle
noreply at git.blender.org
Fri Jan 13 02:52:32 CET 2017
Commit: c189403126d0811210ead30c4c4043cab679ff5c
Author: Mai Lavelle
Date: Fri Jan 6 20:22:31 2017 -0500
Branches: cycles-tiles-rework
https://developer.blender.org/rBc189403126d0811210ead30c4c4043cab679ff5c
Cycles: Add functions to acquire multiple tiles at once
Devices will render multiple smallish tiles (and eventually multiple
samples) at once to keep busy. Using smaller tiles has a few benefits:
there's less of an issue of tiles being cropped at image edges, multiple
devices can share work better, and we may even be able to increase
coherency from rendering multiple samples.
===================================================================
M intern/cycles/device/device_task.h
M intern/cycles/render/session.cpp
M intern/cycles/render/session.h
M intern/cycles/render/tile.cpp
M intern/cycles/render/tile.h
===================================================================
diff --git a/intern/cycles/device/device_task.h b/intern/cycles/device/device_task.h
index 8bd54c3d2b..be79a673ee 100644
--- a/intern/cycles/device/device_task.h
+++ b/intern/cycles/device/device_task.h
@@ -32,6 +32,11 @@ class RenderBuffers;
class RenderTile;
class Tile;
+struct RenderWorkRequest {
+ int num_pixel_samples;
+ int max_pixel_samples;
+};
+
class DeviceTask : public Task {
public:
typedef enum { PATH_TRACE, FILM_CONVERT, SHADER } Type;
@@ -59,6 +64,7 @@ public:
void update_progress(RenderTile *rtile, int pixel_samples = -1);
function<bool(Device *device, RenderTile&)> acquire_tile;
+ function<bool(Device *device, vector<RenderTile>&, const RenderWorkRequest&)> acquire_tiles;
function<void(long, int)> update_progress_sample;
function<void(RenderTile&)> update_tile_sample;
function<void(RenderTile&)> release_tile;
diff --git a/intern/cycles/render/session.cpp b/intern/cycles/render/session.cpp
index 3372104872..0dcfa99dac 100644
--- a/intern/cycles/render/session.cpp
+++ b/intern/cycles/render/session.cpp
@@ -439,6 +439,136 @@ bool Session::acquire_tile(Device *tile_device, RenderTile& rtile)
return true;
}
+bool Session::acquire_tiles(Device *tile_device, vector<RenderTile>& rtiles, const RenderWorkRequest& work_request)
+{
+ assert(rtiles.size() == 0);
+
+ if(progress.get_cancel()) {
+ if(params.progressive_refine == false) {
+ /* for progressive refine current sample should be finished for all tiles */
+ return false;
+ }
+ }
+
+ thread_scoped_lock tile_lock(tile_mutex);
+
+ vector<Tile> tiles;
+ size_t work_acquired = 0;
+ int device_num = device->device_number(tile_device);
+
+ while(work_acquired < work_request.num_pixel_samples) {
+ /* get next tile from manager */
+ Tile tile;
+
+ size_t tile_work_size = tile_manager.next_tile_work_size(device_num);
+ if(tile_work_size == 0 || work_acquired + tile_work_size > work_request.max_pixel_samples) {
+ break;
+ }
+
+ if(!tile_manager.next_tile(tile, device_num)) {
+ break;
+ }
+
+ /* fill render tile */
+ RenderTile rtile;
+ rtile.x = tile_manager.state.buffer.full_x + tile.x;
+ rtile.y = tile_manager.state.buffer.full_y + tile.y;
+ rtile.w = tile.w;
+ rtile.h = tile.h;
+ rtile.start_sample = tile_manager.state.sample;
+ rtile.num_samples = tile_manager.state.num_samples;
+ rtile.resolution = tile_manager.state.resolution_divider;
+
+ tiles.push_back(tile);
+ rtiles.push_back(rtile);
+
+ work_acquired += tile_work_size;
+ }
+
+ if(tiles.size() == 0) {
+ if(tile_manager.next_tile_work_size(device_num) != 0) {
+ progress.set_error("Tile size too large for device");
+ }
+
+ return false;
+ }
+
+ tile_lock.unlock();
+
+ /* in case of a permanent buffer, return it, otherwise we will allocate
+ * a new temporary buffer */
+ if(!(params.background && params.output_path.empty())) {
+ for(int i = 0; i < rtiles.size(); i++) {
+ RenderTile& rtile = rtiles[i];
+
+ tile_manager.state.buffer.get_offset_stride(rtile.offset, rtile.stride);
+
+ rtile.buffer = buffers->buffer.device_pointer;
+ rtile.rng_state = buffers->rng_state.device_pointer;
+ rtile.buffers = buffers;
+
+ device->map_tile(tile_device, rtile);
+ }
+
+ return true;
+ }
+
+ for(int i = 0; i < rtiles.size(); i++) {
+ RenderTile& rtile = rtiles[i];
+
+ /* fill buffer parameters */
+ BufferParams buffer_params = tile_manager.params;
+ buffer_params.full_x = rtile.x;
+ buffer_params.full_y = rtile.y;
+ buffer_params.width = rtile.w;
+ buffer_params.height = rtile.h;
+
+ buffer_params.get_offset_stride(rtile.offset, rtile.stride);
+
+ RenderBuffers *tilebuffers;
+
+ /* allocate buffers */
+ if(params.progressive_refine) {
+ tile_lock.lock();
+
+ if(tile_buffers.size() == 0)
+ tile_buffers.resize(tile_manager.state.num_tiles, NULL);
+
+ /* In certain circumstances number of tiles in the tile manager could
+ * be changed. This is not supported by the progressive refine feature.
+ */
+ assert(tile_buffers.size() == tile_manager.state.num_tiles);
+
+ tilebuffers = tile_buffers[tiles[i].index];
+ if(tilebuffers == NULL) {
+ tilebuffers = new RenderBuffers(tile_device);
+ tile_buffers[tiles[i].index] = tilebuffers;
+
+ tilebuffers->reset(tile_device, buffer_params);
+ }
+
+ tile_lock.unlock();
+ }
+ else {
+ tilebuffers = new RenderBuffers(tile_device);
+
+ tilebuffers->reset(tile_device, buffer_params);
+ }
+
+ rtile.buffer = tilebuffers->buffer.device_pointer;
+ rtile.rng_state = tilebuffers->rng_state.device_pointer;
+ rtile.buffers = tilebuffers;
+
+ /* this will tag tile as IN PROGRESS in blender-side render pipeline,
+ * which is needed to highlight currently rendering tile before first
+ * sample was processed for it
+ */
+ update_tile_sample(rtile);
+ }
+
+ return true;
+}
+
void Session::update_tile_sample(RenderTile& rtile)
{
thread_scoped_lock tile_lock(tile_mutex);
@@ -874,6 +1004,7 @@ void Session::path_trace()
DeviceTask task(DeviceTask::PATH_TRACE);
task.acquire_tile = function_bind(&Session::acquire_tile, this, _1, _2);
+ task.acquire_tiles = function_bind(&Session::acquire_tiles, this, _1, _2, _3);
task.release_tile = function_bind(&Session::release_tile, this, _1);
task.get_cancel = function_bind(&Progress::get_cancel, &this->progress);
task.update_tile_sample = function_bind(&Session::update_tile_sample, this, _1);
diff --git a/intern/cycles/render/session.h b/intern/cycles/render/session.h
index c7ff144617..a0851c159d 100644
--- a/intern/cycles/render/session.h
+++ b/intern/cycles/render/session.h
@@ -174,6 +174,7 @@ protected:
void reset_gpu(BufferParams& params, int samples);
bool acquire_tile(Device *tile_device, RenderTile& tile);
+ bool acquire_tiles(Device *tile_device, vector<RenderTile>& tile, const RenderWorkRequest& work_request);
void update_tile_sample(RenderTile& tile);
void release_tile(RenderTile& tile);
diff --git a/intern/cycles/render/tile.cpp b/intern/cycles/render/tile.cpp
index e59d0c843a..4a30aa2571 100644
--- a/intern/cycles/render/tile.cpp
+++ b/intern/cycles/render/tile.cpp
@@ -347,6 +347,17 @@ bool TileManager::next_tile(Tile& tile, int device)
return true;
}
+size_t TileManager::next_tile_work_size(int device)
+{
+ int logical_device = preserve_tile_device? device: 0;
+
+ if((logical_device >= state.tiles.size()) || state.tiles[logical_device].empty())
+ return 0;
+
+ Tile& tile = state.tiles[logical_device].front();
+ return tile.w * tile.h;
+}
+
bool TileManager::done()
{
int end_sample = (range_num_samples == -1)
diff --git a/intern/cycles/render/tile.h b/intern/cycles/render/tile.h
index 5d92ebac35..fe10bb5094 100644
--- a/intern/cycles/render/tile.h
+++ b/intern/cycles/render/tile.h
@@ -83,6 +83,7 @@ public:
void set_samples(int num_samples);
bool next();
bool next_tile(Tile& tile, int device = 0);
+ size_t next_tile_work_size(int device = 0);
bool done();
void set_tile_order(TileOrder tile_order_) { tile_order = tile_order_; }
More information about the Bf-blender-cvs
mailing list