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/render')
-rw-r--r--intern/cycles/render/buffers.cpp25
-rw-r--r--intern/cycles/render/buffers.h29
-rw-r--r--intern/cycles/render/camera.cpp12
-rw-r--r--intern/cycles/render/camera.h1
-rw-r--r--intern/cycles/render/graph.cpp14
-rw-r--r--intern/cycles/render/image.cpp75
-rw-r--r--intern/cycles/render/image.h13
-rw-r--r--intern/cycles/render/nodes.cpp135
-rw-r--r--intern/cycles/render/nodes.h11
-rw-r--r--intern/cycles/render/scene.cpp5
-rw-r--r--intern/cycles/render/scene.h7
-rw-r--r--intern/cycles/render/session.cpp220
-rw-r--r--intern/cycles/render/session.h27
-rw-r--r--intern/cycles/render/tile.cpp138
-rw-r--r--intern/cycles/render/tile.h28
15 files changed, 588 insertions, 152 deletions
diff --git a/intern/cycles/render/buffers.cpp b/intern/cycles/render/buffers.cpp
index a79a3591e0f..51568f65323 100644
--- a/intern/cycles/render/buffers.cpp
+++ b/intern/cycles/render/buffers.cpp
@@ -74,6 +74,29 @@ int BufferParams::get_passes_size()
return align_up(size, 4);
}
+/* Render Buffer Task */
+
+RenderTile::RenderTile()
+{
+ x = 0;
+ y = 0;
+ w = 0;
+ h = 0;
+
+ start_sample = 0;
+ num_samples = 0;
+ resolution = 0;
+
+ offset = 0;
+ stride = 0;
+
+ buffer = 0;
+ rng_state = 0;
+ rgba = 0;
+
+ buffers = NULL;
+}
+
/* Render Buffers */
RenderBuffers::RenderBuffers(Device *device_)
@@ -135,7 +158,7 @@ bool RenderBuffers::copy_from_device()
return true;
}
-bool RenderBuffers::get_pass(PassType type, float exposure, int sample, int components, float *pixels)
+bool RenderBuffers::get_pass_rect(PassType type, float exposure, int sample, int components, float *pixels)
{
int pass_offset = 0;
diff --git a/intern/cycles/render/buffers.h b/intern/cycles/render/buffers.h
index 78712ed89ef..ee0d78a1cd8 100644
--- a/intern/cycles/render/buffers.h
+++ b/intern/cycles/render/buffers.h
@@ -67,12 +67,11 @@ class RenderBuffers {
public:
/* buffer parameters */
BufferParams params;
+
/* float buffer */
device_vector<float> buffer;
/* random number generator state */
device_vector<uint> rng_state;
- /* mutex, must be locked manually by callers */
- thread_mutex mutex;
RenderBuffers(Device *device);
~RenderBuffers();
@@ -80,7 +79,7 @@ public:
void reset(Device *device, BufferParams& params);
bool copy_from_device();
- bool get_pass(PassType type, float exposure, int sample, int components, float *pixels);
+ bool get_pass_rect(PassType type, float exposure, int sample, int components, float *pixels);
protected:
void device_free();
@@ -105,8 +104,6 @@ public:
bool transparent;
/* byte buffer for tonemapped result */
device_vector<uchar4> rgba;
- /* mutex, must be locked manually by callers */
- thread_mutex mutex;
DisplayBuffer(Device *device);
~DisplayBuffer();
@@ -124,6 +121,28 @@ protected:
Device *device;
};
+/* Render Tile
+ * Rendering task on a buffer */
+
+class RenderTile {
+public:
+ int x, y, w, h;
+ int start_sample;
+ int num_samples;
+ int sample;
+ int resolution;
+ int offset;
+ int stride;
+
+ device_ptr buffer;
+ device_ptr rng_state;
+ device_ptr rgba;
+
+ RenderBuffers *buffers;
+
+ RenderTile();
+};
+
CCL_NAMESPACE_END
#endif /* __BUFFERS_H__ */
diff --git a/intern/cycles/render/camera.cpp b/intern/cycles/render/camera.cpp
index 55a0f23f8d0..e44caa90f12 100644
--- a/intern/cycles/render/camera.cpp
+++ b/intern/cycles/render/camera.cpp
@@ -75,6 +75,7 @@ Camera::Camera()
need_update = true;
need_device_update = true;
+ previous_need_motion = -1;
}
Camera::~Camera()
@@ -140,8 +141,17 @@ void Camera::update()
void Camera::device_update(Device *device, DeviceScene *dscene, Scene *scene)
{
+ Scene::MotionType need_motion = scene->need_motion();
+
update();
+ if (previous_need_motion != need_motion) {
+ /* scene's motion model could have been changed since previous device
+ * camera update this could happen for example in case when one render
+ * layer has got motion pass and another not */
+ need_device_update = true;
+ }
+
if(!need_device_update)
return;
@@ -159,7 +169,6 @@ void Camera::device_update(Device *device, DeviceScene *dscene, Scene *scene)
kcam->worldtocamera = transform_inverse(cameratoworld);
/* camera motion */
- Scene::MotionType need_motion = scene->need_motion();
kcam->have_motion = 0;
if(need_motion == Scene::MOTION_PASS) {
@@ -226,6 +235,7 @@ void Camera::device_update(Device *device, DeviceScene *dscene, Scene *scene)
kcam->cliplength = (farclip == FLT_MAX)? FLT_MAX: farclip - nearclip;
need_device_update = false;
+ previous_need_motion = need_motion;
}
void Camera::device_free(Device *device, DeviceScene *dscene)
diff --git a/intern/cycles/render/camera.h b/intern/cycles/render/camera.h
index d2a3cce1817..82852bde5e0 100644
--- a/intern/cycles/render/camera.h
+++ b/intern/cycles/render/camera.h
@@ -91,6 +91,7 @@ public:
/* update */
bool need_update;
bool need_device_update;
+ int previous_need_motion;
/* functions */
Camera();
diff --git a/intern/cycles/render/graph.cpp b/intern/cycles/render/graph.cpp
index 6ed0812a239..20fbfa0cf27 100644
--- a/intern/cycles/render/graph.cpp
+++ b/intern/cycles/render/graph.cpp
@@ -402,6 +402,20 @@ void ShaderGraph::clean()
/* break cycles */
break_cycles(output(), visited, on_stack);
+ /* disconnect unused nodes */
+ foreach(ShaderNode *node, nodes) {
+ if(!visited[node->id]) {
+ foreach(ShaderInput *to, node->inputs) {
+ ShaderOutput *from = to->link;
+
+ if (from) {
+ to->link = NULL;
+ from->links.erase(remove(from->links.begin(), from->links.end(), to), from->links.end());
+ }
+ }
+ }
+ }
+
/* remove unused nodes */
foreach(ShaderNode *node, nodes) {
if(visited[node->id])
diff --git a/intern/cycles/render/image.cpp b/intern/cycles/render/image.cpp
index 1af0972ecf9..4ee024dd52a 100644
--- a/intern/cycles/render/image.cpp
+++ b/intern/cycles/render/image.cpp
@@ -36,6 +36,10 @@ ImageManager::ImageManager()
need_update = true;
pack_images = false;
osl_texture_system = NULL;
+
+ tex_num_images = TEX_NUM_IMAGES;
+ tex_num_float_images = TEX_NUM_FLOAT_IMAGES;
+ tex_image_byte_start = TEX_IMAGE_BYTE_START;
}
ImageManager::~ImageManager()
@@ -56,6 +60,13 @@ void ImageManager::set_osl_texture_system(void *texture_system)
osl_texture_system = texture_system;
}
+void ImageManager::set_extended_image_limits(void)
+{
+ tex_num_images = TEX_EXTENDED_NUM_IMAGES;
+ tex_num_float_images = TEX_EXTENDED_NUM_FLOAT_IMAGES;
+ tex_image_byte_start = TEX_EXTENDED_IMAGE_BYTE_START;
+}
+
static bool is_float_image(const string& filename)
{
ImageInput *in = ImageInput::create(filename);
@@ -97,7 +108,7 @@ int ImageManager::add_image(const string& filename, bool& is_float)
for(slot = 0; slot < float_images.size(); slot++) {
if(float_images[slot] && float_images[slot]->filename == filename) {
float_images[slot]->users++;
- return slot+TEX_IMAGE_FLOAT_START;
+ return slot;
}
}
@@ -110,8 +121,8 @@ int ImageManager::add_image(const string& filename, bool& is_float)
if(slot == float_images.size()) {
/* max images limit reached */
if(float_images.size() == TEX_NUM_FLOAT_IMAGES) {
- printf("ImageManager::add_image: byte image limit reached %d, skipping '%s'\n",
- TEX_NUM_IMAGES, filename.c_str());
+ printf("ImageManager::add_image: float image limit reached %d, skipping '%s'\n",
+ tex_num_float_images, filename.c_str());
return -1;
}
@@ -125,14 +136,12 @@ int ImageManager::add_image(const string& filename, bool& is_float)
img->users = 1;
float_images[slot] = img;
- /* report slot out of total set of textures */
- slot += TEX_IMAGE_FLOAT_START;
}
else {
for(slot = 0; slot < images.size(); slot++) {
if(images[slot] && images[slot]->filename == filename) {
images[slot]->users++;
- return slot;
+ return slot+tex_image_byte_start;
}
}
@@ -144,9 +153,9 @@ int ImageManager::add_image(const string& filename, bool& is_float)
if(slot == images.size()) {
/* max images limit reached */
- if(images.size() == TEX_NUM_IMAGES) {
+ if(images.size() == tex_num_images) {
printf("ImageManager::add_image: byte image limit reached %d, skipping '%s'\n",
- TEX_NUM_IMAGES, filename.c_str());
+ tex_num_images, filename.c_str());
return -1;
}
@@ -160,6 +169,8 @@ int ImageManager::add_image(const string& filename, bool& is_float)
img->users = 1;
images[slot] = img;
+
+ slot += tex_image_byte_start;
}
need_update = true;
@@ -340,20 +351,20 @@ void ImageManager::device_load_image(Device *device, DeviceScene *dscene, int sl
Image *img;
bool is_float;
- if(slot < TEX_IMAGE_FLOAT_START) {
- img = images[slot];
+ if(slot >= tex_image_byte_start) {
+ img = images[slot - tex_image_byte_start];
is_float = false;
}
else {
- img = float_images[slot - TEX_IMAGE_FLOAT_START];
+ img = float_images[slot];
is_float = true;
}
if(is_float) {
- string filename = path_filename(float_images[slot - TEX_IMAGE_FLOAT_START]->filename);
+ string filename = path_filename(float_images[slot]->filename);
progress->set_status("Updating Images", "Loading " + filename);
- device_vector<float4>& tex_img = dscene->tex_float_image[slot - TEX_IMAGE_FLOAT_START];
+ device_vector<float4>& tex_img = dscene->tex_float_image[slot];
if(tex_img.device_pointer)
device->tex_free(tex_img);
@@ -377,10 +388,10 @@ void ImageManager::device_load_image(Device *device, DeviceScene *dscene, int sl
device->tex_alloc(name.c_str(), tex_img, true, true);
}
else {
- string filename = path_filename(images[slot]->filename);
+ string filename = path_filename(images[slot - tex_image_byte_start]->filename);
progress->set_status("Updating Images", "Loading " + filename);
- device_vector<uchar4>& tex_img = dscene->tex_image[slot];
+ device_vector<uchar4>& tex_img = dscene->tex_image[slot - tex_image_byte_start];
if(tex_img.device_pointer)
device->tex_free(tex_img);
@@ -412,12 +423,12 @@ void ImageManager::device_free_image(Device *device, DeviceScene *dscene, int sl
Image *img;
bool is_float;
- if(slot < TEX_IMAGE_FLOAT_START) {
- img = images[slot];
+ if(slot >= tex_image_byte_start) {
+ img = images[slot - tex_image_byte_start];
is_float = false;
}
else {
- img = float_images[slot - TEX_IMAGE_FLOAT_START];
+ img = float_images[slot];
is_float = true;
}
@@ -429,18 +440,18 @@ void ImageManager::device_free_image(Device *device, DeviceScene *dscene, int sl
#endif
}
else if(is_float) {
- device->tex_free(dscene->tex_float_image[slot - TEX_IMAGE_FLOAT_START]);
- dscene->tex_float_image[slot - TEX_IMAGE_FLOAT_START].clear();
+ device->tex_free(dscene->tex_float_image[slot]);
+ dscene->tex_float_image[slot].clear();
- delete float_images[slot - TEX_IMAGE_FLOAT_START];
- float_images[slot - TEX_IMAGE_FLOAT_START] = NULL;
+ delete float_images[slot];
+ float_images[slot] = NULL;
}
else {
- device->tex_free(dscene->tex_image[slot]);
- dscene->tex_image[slot].clear();
+ device->tex_free(dscene->tex_image[slot - tex_image_byte_start]);
+ dscene->tex_image[slot - tex_image_byte_start].clear();
- delete images[slot];
- images[slot] = NULL;
+ delete images[slot - tex_image_byte_start];
+ images[slot - tex_image_byte_start] = NULL;
}
}
}
@@ -457,11 +468,11 @@ void ImageManager::device_update(Device *device, DeviceScene *dscene, Progress&
continue;
if(images[slot]->users == 0) {
- device_free_image(device, dscene, slot);
+ device_free_image(device, dscene, slot + tex_image_byte_start);
}
else if(images[slot]->need_load) {
if(!osl_texture_system)
- pool.push(function_bind(&ImageManager::device_load_image, this, device, dscene, slot, &progress));
+ pool.push(function_bind(&ImageManager::device_load_image, this, device, dscene, slot + tex_image_byte_start, &progress));
}
}
@@ -470,11 +481,11 @@ void ImageManager::device_update(Device *device, DeviceScene *dscene, Progress&
continue;
if(float_images[slot]->users == 0) {
- device_free_image(device, dscene, slot + TEX_IMAGE_FLOAT_START);
+ device_free_image(device, dscene, slot);
}
else if(float_images[slot]->need_load) {
if(!osl_texture_system)
- pool.push(function_bind(&ImageManager::device_load_image, this, device, dscene, slot + TEX_IMAGE_FLOAT_START, &progress));
+ pool.push(function_bind(&ImageManager::device_load_image, this, device, dscene, slot, &progress));
}
}
@@ -526,9 +537,9 @@ void ImageManager::device_pack_images(Device *device, DeviceScene *dscene, Progr
void ImageManager::device_free(Device *device, DeviceScene *dscene)
{
for(size_t slot = 0; slot < images.size(); slot++)
- device_free_image(device, dscene, slot);
+ device_free_image(device, dscene, slot + tex_image_byte_start);
for(size_t slot = 0; slot < float_images.size(); slot++)
- device_free_image(device, dscene, slot + TEX_IMAGE_FLOAT_START);
+ device_free_image(device, dscene, slot);
device->tex_free(dscene->tex_image_packed);
dscene->tex_image_packed.clear();
diff --git a/intern/cycles/render/image.h b/intern/cycles/render/image.h
index ef046cfcafb..04a705c27bf 100644
--- a/intern/cycles/render/image.h
+++ b/intern/cycles/render/image.h
@@ -28,8 +28,11 @@ CCL_NAMESPACE_BEGIN
#define TEX_NUM_FLOAT_IMAGES 5
#define TEX_NUM_IMAGES 95
-#define TEX_IMAGE_MAX (TEX_NUM_IMAGES + TEX_NUM_FLOAT_IMAGES)
-#define TEX_IMAGE_FLOAT_START TEX_NUM_IMAGES
+#define TEX_IMAGE_BYTE_START TEX_NUM_FLOAT_IMAGES
+
+#define TEX_EXTENDED_NUM_FLOAT_IMAGES 5
+#define TEX_EXTENDED_NUM_IMAGES 512
+#define TEX_EXTENDED_IMAGE_BYTE_START TEX_EXTENDED_NUM_FLOAT_IMAGES
/* color to use when textures are not found */
#define TEX_IMAGE_MISSING_R 1
@@ -55,9 +58,15 @@ public:
void set_osl_texture_system(void *texture_system);
void set_pack_images(bool pack_images_);
+ void set_extended_image_limits(void);
+
bool need_update;
private:
+ int tex_num_images;
+ int tex_num_float_images;
+ int tex_image_byte_start;
+
struct Image {
string filename;
diff --git a/intern/cycles/render/nodes.cpp b/intern/cycles/render/nodes.cpp
index d5ca20e6af1..da511b2d2f4 100644
--- a/intern/cycles/render/nodes.cpp
+++ b/intern/cycles/render/nodes.cpp
@@ -112,7 +112,18 @@ static ShaderEnum color_space_init()
return enm;
}
+static ShaderEnum image_projection_init()
+{
+ ShaderEnum enm;
+
+ enm.insert("Flat", 0);
+ enm.insert("Box", 1);
+
+ return enm;
+}
+
ShaderEnum ImageTextureNode::color_space_enum = color_space_init();
+ShaderEnum ImageTextureNode::projection_enum = image_projection_init();
ImageTextureNode::ImageTextureNode()
: TextureNode("image_texture")
@@ -122,6 +133,8 @@ ImageTextureNode::ImageTextureNode()
is_float = false;
filename = "";
color_space = ustring("Color");
+ projection = ustring("Flat");;
+ projection_blend = 0.0f;
add_input("Vector", SHADER_SOCKET_POINT, ShaderInput::TEXTURE_UV);
add_output("Color", SHADER_SOCKET_COLOR);
@@ -169,13 +182,25 @@ void ImageTextureNode::compile(SVMCompiler& compiler)
tex_mapping.compile(compiler, vector_in->stack_offset, vector_offset);
}
- compiler.add_node(NODE_TEX_IMAGE,
- slot,
- compiler.encode_uchar4(
- vector_offset,
- color_out->stack_offset,
- alpha_out->stack_offset,
- srgb));
+ if(projection == "Flat") {
+ compiler.add_node(NODE_TEX_IMAGE,
+ slot,
+ compiler.encode_uchar4(
+ vector_offset,
+ color_out->stack_offset,
+ alpha_out->stack_offset,
+ srgb));
+ }
+ else {
+ compiler.add_node(NODE_TEX_IMAGE_BOX,
+ slot,
+ compiler.encode_uchar4(
+ vector_offset,
+ color_out->stack_offset,
+ alpha_out->stack_offset,
+ srgb),
+ __float_as_int(projection_blend));
+ }
if(vector_offset != vector_in->stack_offset)
compiler.stack_clear_offset(vector_in->type, vector_offset);
@@ -205,7 +230,7 @@ void ImageTextureNode::compile(OSLCompiler& compiler)
/* Environment Texture */
-static ShaderEnum projection_init()
+static ShaderEnum env_projection_init()
{
ShaderEnum enm;
@@ -216,7 +241,7 @@ static ShaderEnum projection_init()
}
ShaderEnum EnvironmentTextureNode::color_space_enum = color_space_init();
-ShaderEnum EnvironmentTextureNode::projection_enum = projection_init();
+ShaderEnum EnvironmentTextureNode::projection_enum = env_projection_init();
EnvironmentTextureNode::EnvironmentTextureNode()
: TextureNode("environment_texture")
@@ -873,6 +898,98 @@ void CheckerTextureNode::compile(OSLCompiler& compiler)
compiler.add(this, "node_checker_texture");
}
+/* Brick Texture */
+
+BrickTextureNode::BrickTextureNode()
+: TextureNode("brick_texture")
+{
+ offset = 0.5f;
+ offset_frequency = 2;
+ squash = 1.0f;
+ squash_frequency = 2;
+
+ add_input("Vector", SHADER_SOCKET_POINT, ShaderInput::TEXTURE_GENERATED);
+ add_input("Color1", SHADER_SOCKET_COLOR);
+ add_input("Color2", SHADER_SOCKET_COLOR);
+ add_input("Mortar", SHADER_SOCKET_COLOR);
+ add_input("Scale", SHADER_SOCKET_FLOAT, 5.0f);
+ add_input("Mortar Size", SHADER_SOCKET_FLOAT, 0.02f);
+ add_input("Bias", SHADER_SOCKET_FLOAT, 0.0f);
+ add_input("Brick Width", SHADER_SOCKET_FLOAT, 0.5f);
+ add_input("Row Height", SHADER_SOCKET_FLOAT, 0.25f);
+
+ add_output("Color", SHADER_SOCKET_COLOR);
+ add_output("Fac", SHADER_SOCKET_FLOAT);
+}
+
+void BrickTextureNode::compile(SVMCompiler& compiler)
+{
+ ShaderInput *vector_in = input("Vector");
+ ShaderInput *color1_in = input("Color1");
+ ShaderInput *color2_in = input("Color2");
+ ShaderInput *mortar_in = input("Mortar");
+ ShaderInput *scale_in = input("Scale");
+ ShaderInput *mortar_size_in = input("Mortar Size");
+ ShaderInput *bias_in = input("Bias");
+ ShaderInput *brick_width_in = input("Brick Width");
+ ShaderInput *row_height_in = input("Row Height");
+
+ ShaderOutput *color_out = output("Color");
+ ShaderOutput *fac_out = output("Fac");
+
+ compiler.stack_assign(vector_in);
+ compiler.stack_assign(color1_in);
+ compiler.stack_assign(color2_in);
+ compiler.stack_assign(mortar_in);
+ if(scale_in->link) compiler.stack_assign(scale_in);
+ if(mortar_size_in->link) compiler.stack_assign(mortar_size_in);
+ if(bias_in->link) compiler.stack_assign(bias_in);
+ if(brick_width_in->link) compiler.stack_assign(brick_width_in);
+ if(row_height_in->link) compiler.stack_assign(row_height_in);
+
+ int vector_offset = vector_in->stack_offset;
+
+ if(!tex_mapping.skip()) {
+ vector_offset = compiler.stack_find_offset(SHADER_SOCKET_VECTOR);
+ tex_mapping.compile(compiler, vector_in->stack_offset, vector_offset);
+ }
+
+ if(!color_out->links.empty())
+ compiler.stack_assign(color_out);
+ if(!fac_out->links.empty())
+ compiler.stack_assign(fac_out);
+
+ compiler.add_node(NODE_TEX_BRICK,
+ compiler.encode_uchar4(vector_offset,
+ color1_in->stack_offset, color2_in->stack_offset, mortar_in->stack_offset),
+ compiler.encode_uchar4(scale_in->stack_offset,
+ mortar_size_in->stack_offset, bias_in->stack_offset, brick_width_in->stack_offset),
+ compiler.encode_uchar4(row_height_in->stack_offset,
+ color_out->stack_offset, fac_out->stack_offset));
+
+ compiler.add_node(compiler.encode_uchar4(offset_frequency, squash_frequency),
+ __float_as_int(scale_in->value.x),
+ __float_as_int(mortar_size_in->value.x),
+ __float_as_int(bias_in->value.x));
+
+ compiler.add_node(__float_as_int(brick_width_in->value.x),
+ __float_as_int(row_height_in->value.x),
+ __float_as_int(offset),
+ __float_as_int(squash));
+
+ if(vector_offset != vector_in->stack_offset)
+ compiler.stack_clear_offset(vector_in->type, vector_offset);
+}
+
+void BrickTextureNode::compile(OSLCompiler& compiler)
+{
+ compiler.parameter("Offset", offset);
+ compiler.parameter("Offset Frequency", offset_frequency);
+ compiler.parameter("Squash", squash);
+ compiler.parameter("Squash Frequency", squash_frequency);
+ compiler.add(this, "node_brick_texture");
+}
+
/* Normal */
NormalNode::NormalNode()
diff --git a/intern/cycles/render/nodes.h b/intern/cycles/render/nodes.h
index 650d6092f29..82bead7e41a 100644
--- a/intern/cycles/render/nodes.h
+++ b/intern/cycles/render/nodes.h
@@ -70,8 +70,11 @@ public:
bool is_float;
string filename;
ustring color_space;
+ ustring projection;
+ float projection_blend;
static ShaderEnum color_space_enum;
+ static ShaderEnum projection_enum;
};
class EnvironmentTextureNode : public TextureNode {
@@ -155,6 +158,14 @@ public:
SHADER_NODE_CLASS(CheckerTextureNode)
};
+class BrickTextureNode : public TextureNode {
+public:
+ SHADER_NODE_CLASS(BrickTextureNode)
+
+ float offset, squash;
+ int offset_frequency, squash_frequency;
+};
+
class MappingNode : public ShaderNode {
public:
SHADER_NODE_CLASS(MappingNode)
diff --git a/intern/cycles/render/scene.cpp b/intern/cycles/render/scene.cpp
index 4f5420dec61..071338d49c2 100644
--- a/intern/cycles/render/scene.cpp
+++ b/intern/cycles/render/scene.cpp
@@ -38,7 +38,7 @@
CCL_NAMESPACE_BEGIN
-Scene::Scene(const SceneParams& params_)
+Scene::Scene(const SceneParams& params_, const DeviceInfo& device_info_)
: params(params_)
{
device = NULL;
@@ -55,6 +55,9 @@ Scene::Scene(const SceneParams& params_)
image_manager = new ImageManager();
shader_manager = ShaderManager::create(this);
particle_system_manager = new ParticleSystemManager();
+
+ if (device_info_.type == DEVICE_CPU)
+ image_manager->set_extended_image_limits();
}
Scene::~Scene()
diff --git a/intern/cycles/render/scene.h b/intern/cycles/render/scene.h
index d9341af08e0..f6c1ef44146 100644
--- a/intern/cycles/render/scene.h
+++ b/intern/cycles/render/scene.h
@@ -37,6 +37,7 @@ class AttributeRequestSet;
class Background;
class Camera;
class Device;
+class DeviceInfo;
class Film;
class Filter;
class Integrator;
@@ -99,8 +100,8 @@ public:
device_vector<uint> sobol_directions;
/* images */
- device_vector<uchar4> tex_image[TEX_NUM_IMAGES];
- device_vector<float4> tex_float_image[TEX_NUM_FLOAT_IMAGES];
+ device_vector<uchar4> tex_image[TEX_EXTENDED_NUM_IMAGES];
+ device_vector<float4> tex_float_image[TEX_EXTENDED_NUM_FLOAT_IMAGES];
/* opencl images */
device_vector<uchar4> tex_image_packed;
@@ -183,7 +184,7 @@ public:
/* mutex must be locked manually by callers */
thread_mutex mutex;
- Scene(const SceneParams& params);
+ Scene(const SceneParams& params, const DeviceInfo& device_info);
~Scene();
void device_update(Device *device, Progress& progress);
diff --git a/intern/cycles/render/session.cpp b/intern/cycles/render/session.cpp
index a9f7e5beb56..2fb1f49e563 100644
--- a/intern/cycles/render/session.cpp
+++ b/intern/cycles/render/session.cpp
@@ -27,6 +27,7 @@
#include "util_foreach.h"
#include "util_function.h"
+#include "util_math.h"
#include "util_opengl.h"
#include "util_task.h"
#include "util_time.h"
@@ -35,15 +36,23 @@ CCL_NAMESPACE_BEGIN
Session::Session(const SessionParams& params_)
: params(params_),
- tile_manager(params.progressive, params.samples, params.tile_size, params.min_size)
+ tile_manager(params.progressive, params.samples, params.tile_size, params.resolution,
+ (params.background)? 1: max(params.device.multi_devices.size(), 1))
{
device_use_gl = ((params.device.type != DEVICE_CPU) && !params.background);
TaskScheduler::init(params.threads);
device = Device::create(params.device, params.background, params.threads);
- buffers = new RenderBuffers(device);
- display = new DisplayBuffer(device);
+
+ if(params.background) {
+ buffers = NULL;
+ display = NULL;
+ }
+ else {
+ buffers = new RenderBuffers(device);
+ display = new DisplayBuffer(device);
+ }
session_thread = NULL;
scene = NULL;
@@ -52,7 +61,6 @@ Session::Session(const SessionParams& params_)
reset_time = 0.0;
preview_time = 0.0;
paused_time = 0.0;
- sample = 0;
delayed_reset.do_reset = false;
delayed_reset.samples = 0;
@@ -81,7 +89,7 @@ Session::~Session()
wait();
}
- if(params.output_path != "") {
+ if(display && params.output_path != "") {
tonemap();
progress.set_status("Writing Image", params.output_path);
@@ -118,8 +126,8 @@ void Session::reset_gpu(BufferParams& buffer_params, int samples)
/* block for buffer acces and reset immediately. we can't do this
* in the thread, because we need to allocate an OpenGL buffer, and
* that only works in the main thread */
- thread_scoped_lock display_lock(display->mutex);
- thread_scoped_lock buffers_lock(buffers->mutex);
+ thread_scoped_lock display_lock(display_mutex);
+ thread_scoped_lock buffers_lock(buffers_mutex);
display_outdated = true;
reset_time = time_dt();
@@ -135,7 +143,7 @@ void Session::reset_gpu(BufferParams& buffer_params, int samples)
bool Session::draw_gpu(BufferParams& buffer_params)
{
/* block for buffer access */
- thread_scoped_lock display_lock(display->mutex);
+ thread_scoped_lock display_lock(display_mutex);
/* first check we already rendered something */
if(gpu_draw_ready) {
@@ -145,7 +153,7 @@ bool Session::draw_gpu(BufferParams& buffer_params)
/* for CUDA we need to do tonemapping still, since we can
* only access GL buffers from the main thread */
if(gpu_need_tonemap) {
- thread_scoped_lock buffers_lock(buffers->mutex);
+ thread_scoped_lock buffers_lock(buffers_mutex);
tonemap();
gpu_need_tonemap = false;
gpu_need_tonemap_cond.notify_all();
@@ -226,23 +234,18 @@ void Session::run_gpu()
/* buffers mutex is locked entirely while rendering each
* sample, and released/reacquired on each iteration to allow
* reset and draw in between */
- thread_scoped_lock buffers_lock(buffers->mutex);
+ thread_scoped_lock buffers_lock(buffers_mutex);
/* update status and timing */
update_status_time();
/* path trace */
- foreach(Tile& tile, tile_manager.state.tiles) {
- path_trace(tile);
-
- device->task_wait();
+ path_trace();
- if(device->error_message() != "")
- progress.set_cancel(device->error_message());
+ device->task_wait();
- if(progress.get_cancel())
- break;
- }
+ if(device->error_message() != "")
+ progress.set_cancel(device->error_message());
/* update status and timing */
update_status_time();
@@ -289,7 +292,7 @@ void Session::reset_cpu(BufferParams& buffer_params, int samples)
bool Session::draw_cpu(BufferParams& buffer_params)
{
- thread_scoped_lock display_lock(display->mutex);
+ thread_scoped_lock display_lock(display_mutex);
/* first check we already rendered something */
if(display->draw_ready()) {
@@ -308,13 +311,101 @@ bool Session::draw_cpu(BufferParams& buffer_params)
return false;
}
+bool Session::acquire_tile(Device *tile_device, RenderTile& rtile)
+{
+ if(progress.get_cancel())
+ return false;
+
+ thread_scoped_lock tile_lock(tile_mutex);
+
+ /* get next tile from manager */
+ Tile tile;
+ int device_num = device->device_number(tile_device);
+
+ if(!tile_manager.next_tile(tile, device_num))
+ return false;
+
+ /* fill render tile */
+ 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;
+
+ tile_lock.unlock();
+
+ /* in case of a permant buffer, return it, otherwise we will allocate
+ * a new temporary buffer */
+ if(!write_render_tile_cb) {
+ 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.rgba = display->rgba.device_pointer;
+ rtile.buffers = buffers;
+
+ device->map_tile(tile_device, rtile);
+
+ return true;
+ }
+
+ /* 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);
+
+ /* allocate buffers */
+ RenderBuffers *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.rgba = 0;
+ rtile.buffers = tilebuffers;
+
+ return true;
+}
+
+void Session::update_tile_sample(RenderTile& rtile)
+{
+ thread_scoped_lock tile_lock(tile_mutex);
+
+ if(update_render_tile_cb) {
+ /* todo: optimize this by making it thread safe and removing lock */
+
+ update_render_tile_cb(rtile);
+ }
+
+ update_status_time();
+}
+
+void Session::release_tile(RenderTile& rtile)
+{
+ thread_scoped_lock tile_lock(tile_mutex);
+
+ if(write_render_tile_cb) {
+ /* todo: optimize this by making it thread safe and removing lock */
+ write_render_tile_cb(rtile);
+
+ delete rtile.buffers;
+ }
+
+ update_status_time();
+}
+
void Session::run_cpu()
{
{
/* reset once to start */
thread_scoped_lock reset_lock(delayed_reset.mutex);
- thread_scoped_lock buffers_lock(buffers->mutex);
- thread_scoped_lock display_lock(display->mutex);
+ thread_scoped_lock buffers_lock(buffers_mutex);
+ thread_scoped_lock display_lock(display_mutex);
reset_(delayed_reset.params, delayed_reset.samples);
delayed_reset.do_reset = false;
@@ -364,7 +455,7 @@ void Session::run_cpu()
/* buffers mutex is locked entirely while rendering each
* sample, and released/reacquired on each iteration to allow
* reset and draw in between */
- thread_scoped_lock buffers_lock(buffers->mutex);
+ thread_scoped_lock buffers_lock(buffers_mutex);
/* update scene */
update_scene();
@@ -379,8 +470,7 @@ void Session::run_cpu()
update_status_time();
/* path trace */
- foreach(Tile& tile, tile_manager.state.tiles)
- path_trace(tile);
+ path_trace();
/* update status and timing */
update_status_time();
@@ -396,8 +486,8 @@ void Session::run_cpu()
{
thread_scoped_lock reset_lock(delayed_reset.mutex);
- thread_scoped_lock buffers_lock(buffers->mutex);
- thread_scoped_lock display_lock(display->mutex);
+ thread_scoped_lock buffers_lock(buffers_mutex);
+ thread_scoped_lock display_lock(display_mutex);
if(delayed_reset.do_reset) {
/* reset rendering if request from main thread */
@@ -442,6 +532,9 @@ void Session::run()
/* run */
if(!progress.get_cancel()) {
+ /* reset number of rendered samples */
+ progress.reset_sample();
+
if(device_use_gl)
run_gpu();
else
@@ -465,10 +558,12 @@ bool Session::draw(BufferParams& buffer_params)
void Session::reset_(BufferParams& buffer_params, int samples)
{
- if(buffer_params.modified(buffers->params)) {
- gpu_draw_ready = false;
- buffers->reset(device, buffer_params);
- display->reset(device, buffer_params);
+ if(buffers) {
+ if(buffer_params.modified(buffers->params)) {
+ gpu_draw_ready = false;
+ buffers->reset(device, buffer_params);
+ display->reset(device, buffer_params);
+ }
}
tile_manager.reset(buffer_params, samples);
@@ -476,7 +571,6 @@ void Session::reset_(BufferParams& buffer_params, int samples)
start_time = time_dt();
preview_time = 0.0;
paused_time = 0.0;
- sample = 0;
if(!params.background)
progress.set_start_time(start_time + paused_time);
@@ -532,8 +626,6 @@ void Session::update_scene()
{
thread_scoped_lock scene_lock(scene->mutex);
- progress.set_status("Updating Scene");
-
/* update camera if dimensions changed for progressive render. the camera
* knows nothing about progressive or cropped rendering, it just gets the
* image dimensions passed in */
@@ -548,20 +640,47 @@ void Session::update_scene()
}
/* update scene */
- if(scene->need_update())
+ if(scene->need_update()) {
+ progress.set_status("Updating Scene");
scene->device_update(device, progress);
+ }
}
void Session::update_status_time(bool show_pause, bool show_done)
{
int sample = tile_manager.state.sample;
int resolution = tile_manager.state.resolution;
+ int num_tiles = tile_manager.state.num_tiles;
+ int tile = tile_manager.state.num_rendered_tiles;
/* update status */
string status, substatus;
- if(!params.progressive)
- substatus = "Path Tracing";
+ if(!params.progressive) {
+ substatus = string_printf("Path Tracing Tile %d/%d", tile, num_tiles);
+
+ if(params.device.type == DEVICE_CUDA || params.device.type == DEVICE_OPENCL ||
+ (params.device.type == DEVICE_CPU && num_tiles == 1)) {
+ /* when rendering on GPU multithreading happens within single tile, as in
+ * tiles are handling sequentially and in this case we could display
+ * currently rendering sample number
+ * this helps a lot from feedback point of view.
+ * also display the info on CPU, when using 1 tile only
+ */
+
+ int sample = progress.get_sample(), num_samples = tile_manager.state.num_samples;
+
+ if(tile > 1) {
+ /* sample counter is global for all tiles, subtract samples
+ * from already finished tiles to get sample counter for
+ * current tile only
+ */
+ sample -= (tile - 1) * num_samples;
+ }
+
+ substatus += string_printf(", Sample %d/%d", sample, num_samples);
+ }
+ }
else if(params.samples == INT_MAX)
substatus = string_printf("Path Tracing Sample %d", sample+1);
else
@@ -580,28 +699,29 @@ void Session::update_status_time(bool show_pause, bool show_done)
if(preview_time == 0.0 && resolution == 1)
preview_time = time_dt();
- double sample_time = (sample == 0)? 0.0: (time_dt() - preview_time - paused_time)/(sample);
+ double tile_time = (tile == 0)? 0.0: (time_dt() - preview_time - paused_time)/(sample);
/* negative can happen when we pause a bit before rendering, can discard that */
if(preview_time < 0.0) preview_time = 0.0;
- progress.set_sample(sample + 1, sample_time);
+ progress.set_tile(tile, tile_time);
+}
+
+void Session::update_progress_sample()
+{
+ progress.increment_sample();
}
-void Session::path_trace(Tile& tile)
+void Session::path_trace()
{
/* add path trace task */
DeviceTask task(DeviceTask::PATH_TRACE);
-
- task.x = tile_manager.state.buffer.full_x + tile.x;
- task.y = tile_manager.state.buffer.full_y + tile.y;
- task.w = tile.w;
- task.h = tile.h;
- task.buffer = buffers->buffer.device_pointer;
- task.rng_state = buffers->rng_state.device_pointer;
- task.sample = tile_manager.state.sample;
- task.resolution = tile_manager.state.resolution;
- tile_manager.state.buffer.get_offset_stride(task.offset, task.stride);
+
+ task.acquire_tile = function_bind(&Session::acquire_tile, this, _1, _2);
+ 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);
+ task.update_progress_sample = function_bind(&Session::update_progress_sample, this);
device->task_add(task);
}
diff --git a/intern/cycles/render/session.h b/intern/cycles/render/session.h
index 90616f011ea..7b01357a2b7 100644
--- a/intern/cycles/render/session.h
+++ b/intern/cycles/render/session.h
@@ -47,8 +47,8 @@ public:
bool progressive;
bool experimental;
int samples;
- int tile_size;
- int min_size;
+ int2 tile_size;
+ int resolution;
int threads;
double cancel_timeout;
@@ -63,8 +63,8 @@ public:
progressive = false;
experimental = false;
samples = INT_MAX;
- tile_size = 64;
- min_size = 64;
+ tile_size = make_int2(64, 64);
+ resolution = 4;
threads = 0;
cancel_timeout = 0.1;
@@ -81,7 +81,7 @@ public:
&& progressive == params.progressive
&& experimental == params.experimental
&& tile_size == params.tile_size
- && min_size == params.min_size
+ && resolution == params.resolution
&& threads == params.threads
&& cancel_timeout == params.cancel_timeout
&& reset_timeout == params.reset_timeout
@@ -102,7 +102,10 @@ public:
DisplayBuffer *display;
Progress progress;
SessionParams params;
- int sample;
+ TileManager tile_manager;
+
+ boost::function<void(RenderTile&)> write_render_tile_cb;
+ boost::function<void(RenderTile&)> update_render_tile_cb;
Session(const SessionParams& params);
~Session();
@@ -130,7 +133,7 @@ protected:
void update_status_time(bool show_pause = false, bool show_done = false);
void tonemap();
- void path_trace(Tile& tile);
+ void path_trace();
void reset_(BufferParams& params, int samples);
void run_cpu();
@@ -141,7 +144,12 @@ protected:
bool draw_gpu(BufferParams& params);
void reset_gpu(BufferParams& params, int samples);
- TileManager tile_manager;
+ bool acquire_tile(Device *tile_device, RenderTile& tile);
+ void update_tile_sample(RenderTile& tile);
+ void release_tile(RenderTile& tile);
+
+ void update_progress_sample();
+
bool device_use_gl;
thread *session_thread;
@@ -155,6 +163,9 @@ protected:
bool pause;
thread_condition_variable pause_cond;
thread_mutex pause_mutex;
+ thread_mutex tile_mutex;
+ thread_mutex buffers_mutex;
+ thread_mutex display_mutex;
bool kernels_loaded;
diff --git a/intern/cycles/render/tile.cpp b/intern/cycles/render/tile.cpp
index 04e48d44029..b4156fd9471 100644
--- a/intern/cycles/render/tile.cpp
+++ b/intern/cycles/render/tile.cpp
@@ -19,14 +19,16 @@
#include "tile.h"
#include "util_algorithm.h"
+#include "util_types.h"
CCL_NAMESPACE_BEGIN
-TileManager::TileManager(bool progressive_, int samples_, int tile_size_, int min_size_)
+TileManager::TileManager(bool progressive_, int num_samples_, int2 tile_size_, int resolution_, int num_devices_)
{
progressive = progressive_;
tile_size = tile_size_;
- min_size = min_size_;
+ resolution = resolution_;
+ num_devices = num_devices_;
BufferParams buffer_params;
reset(buffer_params, 0);
@@ -36,34 +38,24 @@ TileManager::~TileManager()
{
}
-void TileManager::reset(BufferParams& params_, int samples_)
+void TileManager::reset(BufferParams& params_, int num_samples_)
{
params = params_;
- start_resolution = 1;
-
- int w = params.width, h = params.height;
-
- if(min_size != INT_MAX) {
- while(w*h > min_size*min_size) {
- w = max(1, w/2);
- h = max(1, h/2);
-
- start_resolution *= 2;
- }
- }
-
- samples = samples_;
+ num_samples = num_samples_;
state.buffer = BufferParams();
state.sample = -1;
- state.resolution = start_resolution;
+ state.num_tiles = 0;
+ state.num_rendered_tiles = 0;
+ state.num_samples = 0;
+ state.resolution = resolution;
state.tiles.clear();
}
-void TileManager::set_samples(int samples_)
+void TileManager::set_samples(int num_samples_)
{
- samples = samples_;
+ num_samples = num_samples_;
}
void TileManager::set_tiles()
@@ -71,24 +63,34 @@ void TileManager::set_tiles()
int resolution = state.resolution;
int image_w = max(1, params.width/resolution);
int image_h = max(1, params.height/resolution);
- int tile_w = (tile_size >= image_w)? 1: (image_w + tile_size - 1)/tile_size;
- int tile_h = (tile_size >= image_h)? 1: (image_h + tile_size - 1)/tile_size;
- int sub_w = image_w/tile_w;
- int sub_h = image_h/tile_h;
state.tiles.clear();
- for(int tile_y = 0; tile_y < tile_h; tile_y++) {
- for(int tile_x = 0; tile_x < tile_w; tile_x++) {
- int x = tile_x * sub_w;
- int y = tile_y * sub_h;
- int w = (tile_x == tile_w-1)? image_w - x: sub_w;
- int h = (tile_y == tile_h-1)? image_h - y: sub_h;
+ int num = min(image_h, num_devices);
+
+ for(int device = 0; device < num; device++) {
+ int device_y = (image_h/num)*device;
+ int device_h = (device == num-1)? image_h - device*(image_h/num): image_h/num;
+
+ int tile_w = (tile_size.x >= image_w)? 1: (image_w + tile_size.x - 1)/tile_size.x;
+ int tile_h = (tile_size.y >= device_h)? 1: (device_h + tile_size.y - 1)/tile_size.y;
+ int sub_w = (image_w + tile_w - 1)/tile_w;
+ int sub_h = (device_h + tile_h - 1)/tile_h;
- state.tiles.push_back(Tile(x, y, w, h));
+ for(int tile_y = 0; tile_y < tile_h; tile_y++) {
+ for(int tile_x = 0; tile_x < tile_w; tile_x++) {
+ int x = tile_x * sub_w;
+ int y = tile_y * sub_h;
+ int w = (tile_x == tile_w-1)? image_w - x: sub_w;
+ int h = (tile_y == tile_h-1)? device_h - y: sub_h;
+
+ state.tiles.push_back(Tile(x, y + device_y, w, h, device));
+ }
}
}
+ state.num_tiles = state.tiles.size();
+
state.buffer.width = image_w;
state.buffer.height = image_h;
@@ -98,9 +100,74 @@ void TileManager::set_tiles()
state.buffer.full_height = max(1, params.full_height/resolution);
}
+list<Tile>::iterator TileManager::next_center_tile(int device)
+{
+ list<Tile>::iterator iter, best = state.tiles.end();
+
+ int resolution = state.resolution;
+ int image_w = max(1, params.width/resolution);
+ int image_h = max(1, params.height/resolution);
+
+ int num = min(image_h, num_devices);
+
+ int device_y = (image_h / num) * device;
+ int device_h = (device == num - 1) ? image_h - device * (image_h / num) : image_h / num;
+
+ int64_t centx = image_w / 2, centy = device_y + device_h / 2, tot = 1;
+ int64_t mindist = (int64_t) image_w * (int64_t) device_h;
+
+ /* find center of rendering tiles, image center counts for 1 too */
+ for(iter = state.tiles.begin(); iter != state.tiles.end(); iter++) {
+ if(iter->rendering) {
+ Tile &cur_tile = *iter;
+ centx += cur_tile.x + cur_tile.w / 2;
+ centy += cur_tile.y + cur_tile.h / 2;
+ tot++;
+ }
+ }
+
+ centx /= tot;
+ centy /= tot;
+
+ /* closest of the non-rendering tiles */
+ for(iter = state.tiles.begin(); iter != state.tiles.end(); iter++) {
+ if(iter->device == device && iter->rendering == false) {
+ Tile &cur_tile = *iter;
+
+ int64_t distx = centx - (cur_tile.x + cur_tile.w / 2);
+ int64_t disty = centy - (cur_tile.y + cur_tile.h / 2);
+ distx = (int64_t) sqrt((double)distx * distx + disty * disty);
+
+ if(distx < mindist) {
+ best = iter;
+ mindist = distx;
+ }
+ }
+ }
+
+ return best;
+}
+
+bool TileManager::next_tile(Tile& tile, int device)
+{
+ list<Tile>::iterator tile_it;
+
+ tile_it = next_center_tile(device);
+
+ if(tile_it != state.tiles.end()) {
+ tile_it->rendering = true;
+ tile = *tile_it;
+ state.num_rendered_tiles++;
+
+ return true;
+ }
+
+ return false;
+}
+
bool TileManager::done()
{
- return (state.sample+1 >= samples && state.resolution == 1);
+ return (state.sample+state.num_samples >= num_samples && state.resolution == 1);
}
bool TileManager::next()
@@ -111,10 +178,17 @@ bool TileManager::next()
if(progressive && state.resolution > 1) {
state.sample = 0;
state.resolution /= 2;
+ state.num_samples = 1;
set_tiles();
}
else {
state.sample++;
+
+ if(progressive)
+ state.num_samples = 1;
+ else
+ state.num_samples = num_samples;
+
state.resolution = 1;
set_tiles();
}
diff --git a/intern/cycles/render/tile.h b/intern/cycles/render/tile.h
index b6e610c8d90..29f2b1ef9f9 100644
--- a/intern/cycles/render/tile.h
+++ b/intern/cycles/render/tile.h
@@ -31,9 +31,14 @@ CCL_NAMESPACE_BEGIN
class Tile {
public:
int x, y, w, h;
+ int device;
+ bool rendering;
- Tile(int x_, int y_, int w_, int h_)
- : x(x_), y(y_), w(w_), h(h_) {}
+ Tile()
+ {}
+
+ Tile(int x_, int y_, int w_, int h_, int device_)
+ : x(x_), y(y_), w(w_), h(h_), device(device_), rendering(false) {}
};
/* Tile Manager */
@@ -45,27 +50,34 @@ public:
struct State {
BufferParams buffer;
int sample;
+ int num_samples;
int resolution;
+ int num_tiles;
+ int num_rendered_tiles;
list<Tile> tiles;
} state;
- TileManager(bool progressive, int samples, int tile_size, int min_size);
+ TileManager(bool progressive, int num_samples, int2 tile_size, int resolution, int num_devices = 1);
~TileManager();
- void reset(BufferParams& params, int samples);
- void set_samples(int samples);
+ void reset(BufferParams& params, int num_samples);
+ void set_samples(int num_samples);
bool next();
+ bool next_tile(Tile& tile, int device = 0);
bool done();
protected:
void set_tiles();
bool progressive;
- int samples;
- int tile_size;
- int min_size;
+ int num_samples;
+ int2 tile_size;
+ int resolution;
+ int num_devices;
int start_resolution;
+
+ list<Tile>::iterator next_center_tile(int device = 0);
};
CCL_NAMESPACE_END