[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