diff options
Diffstat (limited to 'intern')
-rw-r--r-- | intern/cycles/blender/blender_session.cpp | 10 | ||||
-rw-r--r-- | intern/cycles/blender/blender_session.h | 2 | ||||
-rw-r--r-- | intern/cycles/blender/blender_shader.cpp | 6 | ||||
-rw-r--r-- | intern/cycles/blender/blender_sync.cpp | 3 | ||||
-rw-r--r-- | intern/cycles/blender/blender_util.h | 19 | ||||
-rw-r--r-- | intern/cycles/kernel/svm/svm.h | 2 | ||||
-rw-r--r-- | intern/cycles/kernel/svm/svm_image.h | 53 | ||||
-rw-r--r-- | intern/cycles/render/image.cpp | 2 | ||||
-rw-r--r-- | intern/cycles/render/image.h | 2 | ||||
-rw-r--r-- | intern/cycles/render/light.cpp | 3 | ||||
-rw-r--r-- | intern/cycles/render/mesh.cpp | 47 | ||||
-rw-r--r-- | intern/cycles/render/mesh.h | 3 | ||||
-rw-r--r-- | intern/cycles/render/nodes.cpp | 288 | ||||
-rw-r--r-- | intern/cycles/render/nodes.h | 18 | ||||
-rw-r--r-- | intern/cycles/render/osl.cpp | 15 | ||||
-rw-r--r-- | intern/cycles/render/osl.h | 8 | ||||
-rw-r--r-- | intern/cycles/render/scene.h | 3 | ||||
-rw-r--r-- | intern/cycles/render/svm.cpp | 18 | ||||
-rw-r--r-- | intern/cycles/render/svm.h | 13 | ||||
-rw-r--r-- | intern/cycles/test/render_graph_finalize_test.cpp | 3 |
20 files changed, 369 insertions, 149 deletions
diff --git a/intern/cycles/blender/blender_session.cpp b/intern/cycles/blender/blender_session.cpp index 53f2fdb91b9..78fb49db6c8 100644 --- a/intern/cycles/blender/blender_session.cpp +++ b/intern/cycles/blender/blender_session.cpp @@ -142,9 +142,9 @@ void BlenderSession::create_session() scene->image_manager->builtin_image_info_cb = function_bind( &BlenderSession::builtin_image_info, this, _1, _2, _3); scene->image_manager->builtin_image_pixels_cb = function_bind( - &BlenderSession::builtin_image_pixels, this, _1, _2, _3, _4, _5, _6); + &BlenderSession::builtin_image_pixels, this, _1, _2, _3, _4, _5, _6, _7); scene->image_manager->builtin_image_float_pixels_cb = function_bind( - &BlenderSession::builtin_image_float_pixels, this, _1, _2, _3, _4, _5, _6); + &BlenderSession::builtin_image_float_pixels, this, _1, _2, _3, _4, _5, _6, _7); session->scene = scene; @@ -1210,6 +1210,7 @@ void BlenderSession::builtin_image_info(const string &builtin_name, bool BlenderSession::builtin_image_pixels(const string &builtin_name, void *builtin_data, + int tile, unsigned char *pixels, const size_t pixels_size, const bool associate_alpha, @@ -1229,7 +1230,7 @@ bool BlenderSession::builtin_image_pixels(const string &builtin_name, const int height = b_image.size()[1]; const int channels = b_image.channels(); - unsigned char *image_pixels = image_get_pixels_for_frame(b_image, frame); + unsigned char *image_pixels = image_get_pixels_for_frame(b_image, frame, tile); const size_t num_pixels = ((size_t)width) * height; if (image_pixels && num_pixels * channels == pixels_size) { @@ -1276,6 +1277,7 @@ bool BlenderSession::builtin_image_pixels(const string &builtin_name, bool BlenderSession::builtin_image_float_pixels(const string &builtin_name, void *builtin_data, + int tile, float *pixels, const size_t pixels_size, const bool, @@ -1299,7 +1301,7 @@ bool BlenderSession::builtin_image_float_pixels(const string &builtin_name, const int channels = b_image.channels(); float *image_pixels; - image_pixels = image_get_float_pixels_for_frame(b_image, frame); + image_pixels = image_get_float_pixels_for_frame(b_image, frame, tile); const size_t num_pixels = ((size_t)width) * height; if (image_pixels && num_pixels * channels == pixels_size) { diff --git a/intern/cycles/blender/blender_session.h b/intern/cycles/blender/blender_session.h index 7445fb53458..2f25ec740f9 100644 --- a/intern/cycles/blender/blender_session.h +++ b/intern/cycles/blender/blender_session.h @@ -157,12 +157,14 @@ class BlenderSession { void builtin_image_info(const string &builtin_name, void *builtin_data, ImageMetaData &metadata); bool builtin_image_pixels(const string &builtin_name, void *builtin_data, + int tile, unsigned char *pixels, const size_t pixels_size, const bool associate_alpha, const bool free_cache); bool builtin_image_float_pixels(const string &builtin_name, void *builtin_data, + int tile, float *pixels, const size_t pixels_size, const bool associate_alpha, diff --git a/intern/cycles/blender/blender_shader.cpp b/intern/cycles/blender/blender_shader.cpp index c3564eac940..6bbc73f72ec 100644 --- a/intern/cycles/blender/blender_shader.cpp +++ b/intern/cycles/blender/blender_shader.cpp @@ -665,6 +665,12 @@ static ShaderNode *add_node(Scene *scene, image->animated = b_image_node.image_user().use_auto_refresh(); image->alpha_type = get_image_alpha_type(b_image); + image->tiles.clear(); + BL::Image::tiles_iterator b_iter; + for (b_image.tiles.begin(b_iter); b_iter != b_image.tiles.end(); ++b_iter) { + image->tiles.push_back(b_iter->number()); + } + /* TODO: restore */ /* TODO(sergey): Does not work properly when we change builtin type. */ #if 0 diff --git a/intern/cycles/blender/blender_sync.cpp b/intern/cycles/blender/blender_sync.cpp index bb52c740bfb..332ee3575c0 100644 --- a/intern/cycles/blender/blender_sync.cpp +++ b/intern/cycles/blender/blender_sync.cpp @@ -729,6 +729,9 @@ SceneParams BlenderSync::get_scene_params(BL::Scene &b_scene, bool background) params.bvh_layout = RNA_boolean_get(&cscene, "use_bvh_embree") ? BVH_LAYOUT_EMBREE : params.bvh_layout; #endif + + params.background = background; + return params; } diff --git a/intern/cycles/blender/blender_util.h b/intern/cycles/blender/blender_util.h index cbe61e367fa..efed96ec9f5 100644 --- a/intern/cycles/blender/blender_util.h +++ b/intern/cycles/blender/blender_util.h @@ -34,8 +34,8 @@ extern "C" { void BKE_image_user_frame_calc(void *ima, void *iuser, int cfra); void BKE_image_user_file_path(void *iuser, void *ima, char *path); -unsigned char *BKE_image_get_pixels_for_frame(void *image, int frame); -float *BKE_image_get_float_pixels_for_frame(void *image, int frame); +unsigned char *BKE_image_get_pixels_for_frame(void *image, int frame, int tile); +float *BKE_image_get_float_pixels_for_frame(void *image, int frame, int tile); } CCL_NAMESPACE_BEGIN @@ -234,8 +234,15 @@ static inline int render_resolution_y(BL::RenderSettings &b_render) static inline string image_user_file_path(BL::ImageUser &iuser, BL::Image &ima, int cfra) { char filepath[1024]; + iuser.tile(0); BKE_image_user_frame_calc(NULL, iuser.ptr.data, cfra); BKE_image_user_file_path(iuser.ptr.data, ima.ptr.data, filepath); + if (ima.source() == BL::Image::source_TILED) { + char *udim_id = strstr(filepath, "1001"); + if (udim_id != NULL) { + memcpy(udim_id, "%04d", 4); + } + } return string(filepath); } @@ -245,14 +252,14 @@ static inline int image_user_frame_number(BL::ImageUser &iuser, int cfra) return iuser.frame_current(); } -static inline unsigned char *image_get_pixels_for_frame(BL::Image &image, int frame) +static inline unsigned char *image_get_pixels_for_frame(BL::Image &image, int frame, int tile) { - return BKE_image_get_pixels_for_frame(image.ptr.data, frame); + return BKE_image_get_pixels_for_frame(image.ptr.data, frame, tile); } -static inline float *image_get_float_pixels_for_frame(BL::Image &image, int frame) +static inline float *image_get_float_pixels_for_frame(BL::Image &image, int frame, int tile) { - return BKE_image_get_float_pixels_for_frame(image.ptr.data, frame); + return BKE_image_get_float_pixels_for_frame(image.ptr.data, frame, tile); } static inline void render_add_metadata(BL::RenderResult &b_rr, string name, string value) diff --git a/intern/cycles/kernel/svm/svm.h b/intern/cycles/kernel/svm/svm.h index c4d7164a4d8..fd2833ee687 100644 --- a/intern/cycles/kernel/svm/svm.h +++ b/intern/cycles/kernel/svm/svm.h @@ -311,7 +311,7 @@ ccl_device_noinline void svm_eval_nodes(KernelGlobals *kg, # endif /* NODES_FEATURE(NODE_FEATURE_BUMP) */ # ifdef __TEXTURES__ case NODE_TEX_IMAGE: - svm_node_tex_image(kg, sd, stack, node); + svm_node_tex_image(kg, sd, stack, node, &offset); break; case NODE_TEX_IMAGE_BOX: svm_node_tex_image_box(kg, sd, stack, node); diff --git a/intern/cycles/kernel/svm/svm_image.h b/intern/cycles/kernel/svm/svm_image.h index 64abdd2d8b3..90f1a7845c7 100644 --- a/intern/cycles/kernel/svm/svm_image.h +++ b/intern/cycles/kernel/svm/svm_image.h @@ -20,6 +20,11 @@ CCL_NAMESPACE_BEGIN ccl_device float4 svm_image_texture(KernelGlobals *kg, int id, float x, float y, uint flags) { + if (id == -1) { + return make_float4( + TEX_IMAGE_MISSING_R, TEX_IMAGE_MISSING_G, TEX_IMAGE_MISSING_B, TEX_IMAGE_MISSING_A); + } + float4 r = kernel_tex_image_interp(kg, id, x, y); const float alpha = r.w; @@ -45,9 +50,9 @@ ccl_device_inline float3 texco_remap_square(float3 co) return (co - make_float3(0.5f, 0.5f, 0.5f)) * 2.0f; } -ccl_device void svm_node_tex_image(KernelGlobals *kg, ShaderData *sd, float *stack, uint4 node) +ccl_device void svm_node_tex_image( + KernelGlobals *kg, ShaderData *sd, float *stack, uint4 node, int *offset) { - uint id = node.y; uint co_offset, out_offset, alpha_offset, flags; svm_unpack_node_uchar4(node.z, &co_offset, &out_offset, &alpha_offset, &flags); @@ -65,6 +70,50 @@ ccl_device void svm_node_tex_image(KernelGlobals *kg, ShaderData *sd, float *sta else { tex_co = make_float2(co.x, co.y); } + + /* TODO(lukas): Consider moving tile information out of the SVM node. + * TextureInfo seems a reasonable candidate. */ + int id = -1; + int num_nodes = (int)node.y; + if (num_nodes > 0) { + /* Remember the offset of the node following the tile nodes. */ + int next_offset = (*offset) + num_nodes; + + /* Find the tile that the UV lies in. */ + int tx = (int)tex_co.x; + int ty = (int)tex_co.y; + + /* Check that we're within a legitimate tile. */ + if (tx >= 0 && ty >= 0 && tx < 10) { + int tile = 1001 + 10 * ty + tx; + + /* Find the index of the tile. */ + for (int i = 0; i < num_nodes; i++) { + uint4 tile_node = read_node(kg, offset); + if (tile_node.x == tile) { + id = tile_node.y; + break; + } + if (tile_node.z == tile) { + id = tile_node.w; + break; + } + } + + /* If we found the tile, offset the UVs to be relative to it. */ + if (id != -1) { + tex_co.x -= tx; + tex_co.y -= ty; + } + } + + /* Skip over the remaining nodes. */ + *offset = next_offset; + } + else { + id = -num_nodes; + } + float4 f = svm_image_texture(kg, id, tex_co.x, tex_co.y, flags); if (stack_valid(out_offset)) diff --git a/intern/cycles/render/image.cpp b/intern/cycles/render/image.cpp index 03ecc9bce52..212a867f9cd 100644 --- a/intern/cycles/render/image.cpp +++ b/intern/cycles/render/image.cpp @@ -630,6 +630,7 @@ bool ImageManager::file_load_image(Image *img, if (FileFormat == TypeDesc::FLOAT) { builtin_image_float_pixels_cb(img->filename, img->builtin_data, + 0, /* TODO(lukas): Support tiles here? */ (float *)&pixels[0], num_pixels * components, image_associate_alpha(img), @@ -638,6 +639,7 @@ bool ImageManager::file_load_image(Image *img, else if (FileFormat == TypeDesc::UINT8) { builtin_image_pixels_cb(img->filename, img->builtin_data, + 0, /* TODO(lukas): Support tiles here? */ (uchar *)&pixels[0], num_pixels * components, image_associate_alpha(img), diff --git a/intern/cycles/render/image.h b/intern/cycles/render/image.h index 459cd8c056c..bc04a667953 100644 --- a/intern/cycles/render/image.h +++ b/intern/cycles/render/image.h @@ -130,6 +130,7 @@ class ImageManager { builtin_image_info_cb; function<bool(const string &filename, void *data, + int tile, unsigned char *pixels, const size_t pixels_size, const bool associate_alpha, @@ -137,6 +138,7 @@ class ImageManager { builtin_image_pixels_cb; function<bool(const string &filename, void *data, + int tile, float *pixels, const size_t pixels_size, const bool associate_alpha, diff --git a/intern/cycles/render/light.cpp b/intern/cycles/render/light.cpp index dc3f7c8f8ac..06304205dc9 100644 --- a/intern/cycles/render/light.cpp +++ b/intern/cycles/render/light.cpp @@ -575,7 +575,8 @@ void LightManager::device_update_background(Device *device, if (node->type == EnvironmentTextureNode::node_type) { EnvironmentTextureNode *env = (EnvironmentTextureNode *)node; ImageMetaData metadata; - if (env->image_manager && env->image_manager->get_image_metadata(env->slot, metadata)) { + if (env->image_manager && !env->slots.empty() && + env->image_manager->get_image_metadata(env->slots[0], metadata)) { res.x = max(res.x, metadata.width); res.y = max(res.y, metadata.height); } diff --git a/intern/cycles/render/mesh.cpp b/intern/cycles/render/mesh.cpp index cffe2bfa70a..2bf1040455f 100644 --- a/intern/cycles/render/mesh.cpp +++ b/intern/cycles/render/mesh.cpp @@ -637,6 +637,50 @@ void Mesh::add_subd_face(int *corners, int num_corners, int shader_, bool smooth subd_faces.push_back_reserved(face); } +static void get_uv_tiles_from_attribute(Attribute *attr, int num, unordered_set<int> &tiles) +{ + if (attr == NULL) { + return; + } + + const float2 *uv = attr->data_float2(); + for (int i = 0; i < num; i++, uv++) { + float u = uv->x, v = uv->y; + int x = (int)u, y = (int)v; + + if (x < 0 || y < 0 || x >= 10) { + continue; + } + + /* Be conservative in corners - precisely touching the right or upper edge of a tile + * should not load its right/upper neighbor as well. */ + if (x > 0 && (u < x + 1e-6f)) { + x--; + } + if (y > 0 && (v < y + 1e-6f)) { + y--; + } + + tiles.insert(1001 + 10 * y + x); + } +} + +void Mesh::get_uv_tiles(ustring map, unordered_set<int> &tiles) +{ + if (map.empty()) { + get_uv_tiles_from_attribute(attributes.find(ATTR_STD_UV), num_triangles() * 3, tiles); + get_uv_tiles_from_attribute( + subd_attributes.find(ATTR_STD_UV), subd_face_corners.size() + num_ngons, tiles); + get_uv_tiles_from_attribute(curve_attributes.find(ATTR_STD_UV), num_curves(), tiles); + } + else { + get_uv_tiles_from_attribute(attributes.find(map), num_triangles() * 3, tiles); + get_uv_tiles_from_attribute( + subd_attributes.find(map), subd_face_corners.size() + num_ngons, tiles); + get_uv_tiles_from_attribute(curve_attributes.find(map), num_curves(), tiles); + } +} + void Mesh::compute_bounds() { BoundBox bnds = BoundBox::empty; @@ -2085,8 +2129,7 @@ void MeshManager::device_update_displacement_images(Device *device, } ImageSlotTextureNode *image_node = static_cast<ImageSlotTextureNode *>(node); - int slot = image_node->slot; - if (slot != -1) { + foreach (int slot, image_node->slots) { bump_images.insert(slot); } } diff --git a/intern/cycles/render/mesh.h b/intern/cycles/render/mesh.h index 4a24a9c2656..c5be0ba60b9 100644 --- a/intern/cycles/render/mesh.h +++ b/intern/cycles/render/mesh.h @@ -28,6 +28,7 @@ #include "util/util_list.h" #include "util/util_map.h" #include "util/util_param.h" +#include "util/util_set.h" #include "util/util_transform.h" #include "util/util_types.h" #include "util/util_vector.h" @@ -314,6 +315,8 @@ class Mesh : public Node { void add_vertex_normals(); void add_undisplaced(); + void get_uv_tiles(ustring map, unordered_set<int> &tiles); + void pack_shaders(Scene *scene, uint *shader); void pack_normals(float4 *vnormal); void pack_verts(const vector<uint> &tri_prim_index, diff --git a/intern/cycles/render/nodes.cpp b/intern/cycles/render/nodes.cpp index 5e12d79bc6b..b8847f92153 100644 --- a/intern/cycles/render/nodes.cpp +++ b/intern/cycles/render/nodes.cpp @@ -19,6 +19,7 @@ #include "render/image.h" #include "render/integrator.h" #include "render/light.h" +#include "render/mesh.h" #include "render/nodes.h" #include "render/scene.h" #include "render/svm.h" @@ -204,6 +205,27 @@ void TextureMapping::compile(OSLCompiler &compiler) /* Image Texture */ +ImageSlotTextureNode::~ImageSlotTextureNode() +{ + if (image_manager) { + foreach (int slot, slots) { + if (slot != -1) { + image_manager->remove_image(slot); + } + } + } +} + +void ImageSlotTextureNode::add_image_user() const +{ + /* Increase image user count for new node. */ + foreach (int slot, slots) { + if (slot != -1) { + image_manager->add_image_user(slot); + } + } +} + NODE_DEFINE(ImageTextureNode) { NodeType *type = NodeType::add("image_texture", create, NodeType::SHADER); @@ -253,30 +275,71 @@ NODE_DEFINE(ImageTextureNode) ImageTextureNode::ImageTextureNode() : ImageSlotTextureNode(node_type) { - image_manager = NULL; - slot = -1; - is_float = -1; + is_float = false; compress_as_srgb = false; colorspace = u_colorspace_raw; builtin_data = NULL; animated = false; + tiles.push_back(1001); } -ImageTextureNode::~ImageTextureNode() +ShaderNode *ImageTextureNode::clone() const { - if (image_manager) { - image_manager->remove_image( - filename.string(), builtin_data, interpolation, extension, alpha_type, colorspace); - } + add_image_user(); + return new ImageTextureNode(*this); } -ShaderNode *ImageTextureNode::clone() const +void ImageTextureNode::cull_tiles(Scene *scene, ShaderGraph *graph) { - /* Increase image user count for new node. */ - if (slot != -1) { - image_manager->add_image_user(slot); + if (!scene->params.background) { + /* During interactive renders, all tiles are loaded. + * While we could support updating this when UVs change, that could lead + * to annoying interruptions when loading images while editing UVs. */ + return; } - return new ImageTextureNode(*this); + + /* Only check UVs for tile culling if there are multiple tiles. */ + if (tiles.size() < 2) { + return; + } + + ShaderInput *vector_in = input("Vector"); + ustring attribute; + if (vector_in->link) { + ShaderNode *node = vector_in->link->parent; + if (node->type == UVMapNode::node_type) { + UVMapNode *uvmap = (UVMapNode *)node; + attribute = uvmap->attribute; + } + else if (node->type == TextureCoordinateNode::node_type) { + if (vector_in->link != node->output("UV")) { + return; + } + } + else { + return; + } + } + + unordered_set<int> used_tiles; + /* TODO(lukas): This is quite inefficient. A fairly simple improvement would + * be to have a cache in each mesh that is indexed by attribute. + * Additionally, building a graph-to-meshes list once could help. */ + foreach (Mesh *mesh, scene->meshes) { + foreach (Shader *shader, mesh->used_shaders) { + if (shader->graph == graph) { + mesh->get_uv_tiles(attribute, used_tiles); + } + } + } + + ccl::vector<int> new_tiles; + foreach (int tile, tiles) { + if (used_tiles.count(tile)) { + new_tiles.push_back(tile); + } + } + tiles.swap(new_tiles); } void ImageTextureNode::attributes(Shader *shader, AttributeRequestSet *attributes) @@ -300,24 +363,61 @@ void ImageTextureNode::compile(SVMCompiler &compiler) ShaderOutput *color_out = output("Color"); ShaderOutput *alpha_out = output("Alpha"); - image_manager = compiler.image_manager; - if (is_float == -1) { - ImageMetaData metadata; - slot = image_manager->add_image(filename.string(), - builtin_data, - animated, - 0, - interpolation, - extension, - alpha_type, - colorspace, - metadata); - is_float = metadata.is_float; - compress_as_srgb = metadata.compress_as_srgb; - known_colorspace = metadata.colorspace; + image_manager = compiler.scene->image_manager; + if (slots.empty()) { + cull_tiles(compiler.scene, compiler.current_graph); } + if (slots.size() < tiles.size()) { + slots.clear(); + slots.reserve(tiles.size()); + + bool have_metadata = false; + foreach (int tile, tiles) { + string tile_name = filename.string(); + if (tiles.size() > 1) { + tile_name = string_printf(tile_name.c_str(), tile); + } + + ImageMetaData metadata; + int slot = image_manager->add_image(tile_name, + builtin_data, + animated, + 0, + interpolation, + extension, + alpha_type, + colorspace, + metadata); + slots.push_back(slot); + + /* We assume that all tiles have the same metadata. */ + if (!have_metadata) { + is_float = metadata.is_float; + compress_as_srgb = metadata.compress_as_srgb; + known_colorspace = metadata.colorspace; + have_metadata = true; + } + } + } + + bool has_image = false; + foreach (int slot, slots) { + if (slot != -1) { + has_image = true; + break; + } + } + + if (has_image) { + /* If there only is one image (a very common case), we encode it as a negative value. */ + int num_nodes; + if (slots.size() == 1) { + num_nodes = -slots[0]; + } + else { + num_nodes = divide_up(slots.size(), 2); + } - if (slot != -1) { int vector_offset = tex_mapping.compile_begin(compiler, vector_in); uint flags = 0; @@ -336,7 +436,7 @@ void ImageTextureNode::compile(SVMCompiler &compiler) if (projection != NODE_IMAGE_PROJ_BOX) { compiler.add_node(NODE_TEX_IMAGE, - slot, + num_nodes, compiler.encode_uchar4(vector_offset, compiler.stack_assign_if_linked(color_out), compiler.stack_assign_if_linked(alpha_out), @@ -345,7 +445,7 @@ void ImageTextureNode::compile(SVMCompiler &compiler) } else { compiler.add_node(NODE_TEX_IMAGE_BOX, - slot, + num_nodes, compiler.encode_uchar4(vector_offset, compiler.stack_assign_if_linked(color_out), compiler.stack_assign_if_linked(alpha_out), @@ -353,6 +453,23 @@ void ImageTextureNode::compile(SVMCompiler &compiler) __float_as_int(projection_blend)); } + if (num_nodes > 0) { + for (int i = 0; i < num_nodes; i++) { + int4 node; + node.x = tiles[2 * i]; + node.y = slots[2 * i]; + if (2 * i + 1 < slots.size()) { + node.z = tiles[2 * i + 1]; + node.w = slots[2 * i + 1]; + } + else { + node.z = -1; + node.w = -1; + } + compiler.add_node(node.x, node.y, node.z, node.w); + } + } + tex_mapping.compile_end(compiler, vector_in, vector_offset); } else { @@ -375,34 +492,37 @@ void ImageTextureNode::compile(OSLCompiler &compiler) tex_mapping.compile(compiler); - image_manager = compiler.image_manager; - if (is_float == -1) { + image_manager = compiler.scene->image_manager; + if (slots.size() == 0) { ImageMetaData metadata; if (builtin_data == NULL) { image_manager->get_image_metadata(filename.string(), NULL, colorspace, metadata); + slots.push_back(-1); } else { - slot = image_manager->add_image(filename.string(), - builtin_data, - animated, - 0, - interpolation, - extension, - alpha_type, - colorspace, - metadata); + /* TODO(lukas): OSL UDIMs */ + int slot = image_manager->add_image(filename.string(), + builtin_data, + animated, + 0, + interpolation, + extension, + alpha_type, + colorspace, + metadata); + slots.push_back(slot); } is_float = metadata.is_float; compress_as_srgb = metadata.compress_as_srgb; known_colorspace = metadata.colorspace; } - if (slot == -1) { + if (slots[0] == -1) { compiler.parameter_texture( "filename", filename, compress_as_srgb ? u_colorspace_raw : known_colorspace); } else { - compiler.parameter_texture("filename", slot); + compiler.parameter_texture("filename", slots[0]); } const bool unassociate_alpha = !(ColorSpaceManager::colorspace_is_data(colorspace) || @@ -462,29 +582,16 @@ NODE_DEFINE(EnvironmentTextureNode) EnvironmentTextureNode::EnvironmentTextureNode() : ImageSlotTextureNode(node_type) { - image_manager = NULL; - slot = -1; - is_float = -1; + is_float = false; compress_as_srgb = false; colorspace = u_colorspace_raw; builtin_data = NULL; animated = false; } -EnvironmentTextureNode::~EnvironmentTextureNode() -{ - if (image_manager) { - image_manager->remove_image( - filename.string(), builtin_data, interpolation, EXTENSION_REPEAT, alpha_type, colorspace); - } -} - ShaderNode *EnvironmentTextureNode::clone() const { - /* Increase image user count for new node. */ - if (slot != -1) { - image_manager->add_image_user(slot); - } + add_image_user(); return new EnvironmentTextureNode(*this); } @@ -507,24 +614,25 @@ void EnvironmentTextureNode::compile(SVMCompiler &compiler) ShaderOutput *color_out = output("Color"); ShaderOutput *alpha_out = output("Alpha"); - image_manager = compiler.image_manager; - if (slot == -1) { + image_manager = compiler.scene->image_manager; + if (slots.empty()) { ImageMetaData metadata; - slot = image_manager->add_image(filename.string(), - builtin_data, - animated, - 0, - interpolation, - EXTENSION_REPEAT, - alpha_type, - colorspace, - metadata); + int slot = image_manager->add_image(filename.string(), + builtin_data, + animated, + 0, + interpolation, + EXTENSION_REPEAT, + alpha_type, + colorspace, + metadata); + slots.push_back(slot); is_float = metadata.is_float; compress_as_srgb = metadata.compress_as_srgb; known_colorspace = metadata.colorspace; } - if (slot != -1) { + if (slots[0] != -1) { int vector_offset = tex_mapping.compile_begin(compiler, vector_in); uint flags = 0; @@ -533,7 +641,7 @@ void EnvironmentTextureNode::compile(SVMCompiler &compiler) } compiler.add_node(NODE_TEX_ENVIRONMENT, - slot, + slots[0], compiler.encode_uchar4(vector_offset, compiler.stack_assign_if_linked(color_out), compiler.stack_assign_if_linked(alpha_out), @@ -563,34 +671,36 @@ void EnvironmentTextureNode::compile(OSLCompiler &compiler) /* See comments in ImageTextureNode::compile about support * of builtin images. */ - image_manager = compiler.image_manager; - if (is_float == -1) { + image_manager = compiler.scene->image_manager; + if (slots.empty()) { ImageMetaData metadata; if (builtin_data == NULL) { image_manager->get_image_metadata(filename.string(), NULL, colorspace, metadata); + slots.push_back(-1); } else { - slot = image_manager->add_image(filename.string(), - builtin_data, - animated, - 0, - interpolation, - EXTENSION_REPEAT, - alpha_type, - colorspace, - metadata); + int slot = image_manager->add_image(filename.string(), + builtin_data, + animated, + 0, + interpolation, + EXTENSION_REPEAT, + alpha_type, + colorspace, + metadata); + slots.push_back(slot); } is_float = metadata.is_float; compress_as_srgb = metadata.compress_as_srgb; known_colorspace = metadata.colorspace; } - if (slot == -1) { + if (slots[0] == -1) { compiler.parameter_texture( "filename", filename, compress_as_srgb ? u_colorspace_raw : known_colorspace); } else { - compiler.parameter_texture("filename", slot); + compiler.parameter_texture("filename", slots[0]); } compiler.parameter(this, "projection"); @@ -1123,7 +1233,7 @@ void IESLightNode::get_slot() void IESLightNode::compile(SVMCompiler &compiler) { - light_manager = compiler.light_manager; + light_manager = compiler.scene->light_manager; get_slot(); ShaderInput *strength_in = input("Strength"); @@ -1145,7 +1255,7 @@ void IESLightNode::compile(SVMCompiler &compiler) void IESLightNode::compile(OSLCompiler &compiler) { - light_manager = compiler.light_manager; + light_manager = compiler.scene->light_manager; get_slot(); tex_mapping.compile(compiler); @@ -1663,7 +1773,7 @@ void PointDensityTextureNode::compile(SVMCompiler &compiler) const bool use_density = !density_out->links.empty(); const bool use_color = !color_out->links.empty(); - image_manager = compiler.image_manager; + image_manager = compiler.scene->image_manager; if (use_density || use_color) { add_image(); @@ -1704,7 +1814,7 @@ void PointDensityTextureNode::compile(OSLCompiler &compiler) const bool use_density = !density_out->links.empty(); const bool use_color = !color_out->links.empty(); - image_manager = compiler.image_manager; + image_manager = compiler.scene->image_manager; if (use_density || use_color) { add_image(); diff --git a/intern/cycles/render/nodes.h b/intern/cycles/render/nodes.h index 54124cd2175..a8fe7644957 100644 --- a/intern/cycles/render/nodes.h +++ b/intern/cycles/render/nodes.h @@ -77,14 +77,17 @@ class ImageSlotTextureNode : public TextureNode { explicit ImageSlotTextureNode(const NodeType *node_type) : TextureNode(node_type) { special_type = SHADER_SPECIAL_TYPE_IMAGE_SLOT; + image_manager = NULL; } - int slot; + ~ImageSlotTextureNode(); + void add_image_user() const; + ImageManager *image_manager; + vector<int> slots; }; class ImageTextureNode : public ImageSlotTextureNode { public: SHADER_NODE_NO_CLONE_CLASS(ImageTextureNode) - ~ImageTextureNode(); ShaderNode *clone() const; void attributes(Shader *shader, AttributeRequestSet *attributes); bool has_attribute_dependency() @@ -110,18 +113,20 @@ class ImageTextureNode : public ImageSlotTextureNode { float projection_blend; bool animated; float3 vector; + ccl::vector<int> tiles; /* Runtime. */ - ImageManager *image_manager; - int is_float; + bool is_float; bool compress_as_srgb; ustring known_colorspace; + + protected: + void cull_tiles(Scene *scene, ShaderGraph *graph); }; class EnvironmentTextureNode : public ImageSlotTextureNode { public: SHADER_NODE_NO_CLONE_CLASS(EnvironmentTextureNode) - ~EnvironmentTextureNode(); ShaderNode *clone() const; void attributes(Shader *shader, AttributeRequestSet *attributes); bool has_attribute_dependency() @@ -151,8 +156,7 @@ class EnvironmentTextureNode : public ImageSlotTextureNode { float3 vector; /* Runtime. */ - ImageManager *image_manager; - int is_float; + bool is_float; bool compress_as_srgb; ustring known_colorspace; }; diff --git a/intern/cycles/render/osl.cpp b/intern/cycles/render/osl.cpp index 889552f49cd..91f02e42071 100644 --- a/intern/cycles/render/osl.cpp +++ b/intern/cycles/render/osl.cpp @@ -118,9 +118,9 @@ void OSLShaderManager::device_update(Device *device, * compile shaders alternating */ thread_scoped_lock lock(ss_mutex); - OSLCompiler compiler(this, services, ss, scene->image_manager, scene->light_manager); + OSLCompiler compiler(this, services, ss, scene); compiler.background = (shader == scene->default_background); - compiler.compile(scene, og, shader); + compiler.compile(og, shader); if (shader->use_mis && shader->has_surface_emission) scene->light_manager->need_update = true; @@ -566,13 +566,8 @@ OSLNode *OSLShaderManager::osl_node(const std::string &filepath, OSLCompiler::OSLCompiler(OSLShaderManager *manager, OSLRenderServices *services, OSL::ShadingSystem *ss, - ImageManager *image_manager, - LightManager *light_manager) - : image_manager(image_manager), - light_manager(light_manager), - manager(manager), - services(services), - ss(ss) + Scene *scene) + : scene(scene), manager(manager), services(services), ss(ss) { current_type = SHADER_TYPE_SURFACE; current_shader = NULL; @@ -1114,7 +1109,7 @@ OSL::ShaderGroupRef OSLCompiler::compile_type(Shader *shader, ShaderGraph *graph return group; } -void OSLCompiler::compile(Scene *scene, OSLGlobals *og, Shader *shader) +void OSLCompiler::compile(OSLGlobals *og, Shader *shader) { if (shader->need_update) { ShaderGraph *graph = shader->graph; diff --git a/intern/cycles/render/osl.h b/intern/cycles/render/osl.h index 17bf98a3433..62cbfebf7eb 100644 --- a/intern/cycles/render/osl.h +++ b/intern/cycles/render/osl.h @@ -131,10 +131,9 @@ class OSLCompiler { OSLCompiler(OSLShaderManager *manager, OSLRenderServices *services, OSL::ShadingSystem *shadingsys, - ImageManager *image_manager, - LightManager *light_manager); + Scene *scene); #endif - void compile(Scene *scene, OSLGlobals *og, Shader *shader); + void compile(OSLGlobals *og, Shader *shader); void add(ShaderNode *node, const char *name, bool isfilepath = false); @@ -165,8 +164,7 @@ class OSLCompiler { } bool background; - ImageManager *image_manager; - LightManager *light_manager; + Scene *scene; private: #ifdef WITH_OSL diff --git a/intern/cycles/render/scene.h b/intern/cycles/render/scene.h index 45997bccf5d..f99510d2d42 100644 --- a/intern/cycles/render/scene.h +++ b/intern/cycles/render/scene.h @@ -170,6 +170,8 @@ class SceneParams { bool persistent_data; int texture_limit; + bool background; + SceneParams() { shadingsystem = SHADINGSYSTEM_SVM; @@ -180,6 +182,7 @@ class SceneParams { num_bvh_time_steps = 0; persistent_data = false; texture_limit = 0; + background = true; } bool modified(const SceneParams ¶ms) diff --git a/intern/cycles/render/svm.cpp b/intern/cycles/render/svm.cpp index 8466742ae38..f42a2ea818d 100644 --- a/intern/cycles/render/svm.cpp +++ b/intern/cycles/render/svm.cpp @@ -57,9 +57,9 @@ void SVMShaderManager::device_update_shader(Scene *scene, svm_nodes->push_back_slow(make_int4(NODE_SHADER_JUMP, 0, 0, 0)); SVMCompiler::Summary summary; - SVMCompiler compiler(scene->shader_manager, scene->image_manager, scene->light_manager); + SVMCompiler compiler(scene); compiler.background = (shader == scene->default_background); - compiler.compile(scene, shader, *svm_nodes, 0, &summary); + compiler.compile(shader, *svm_nodes, 0, &summary); VLOG(2) << "Compilation summary:\n" << "Shader name: " << shader->name << "\n" @@ -169,13 +169,8 @@ void SVMShaderManager::device_free(Device *device, DeviceScene *dscene, Scene *s /* Graph Compiler */ -SVMCompiler::SVMCompiler(ShaderManager *shader_manager_, - ImageManager *image_manager_, - LightManager *light_manager_) +SVMCompiler::SVMCompiler(Scene *scene) : scene(scene) { - shader_manager = shader_manager_; - image_manager = image_manager_; - light_manager = light_manager_; max_stack_use = 0; current_type = SHADER_TYPE_SURFACE; current_shader = NULL; @@ -408,12 +403,12 @@ void SVMCompiler::add_node(const float4 &f) uint SVMCompiler::attribute(ustring name) { - return shader_manager->get_attribute_id(name); + return scene->shader_manager->get_attribute_id(name); } uint SVMCompiler::attribute(AttributeStandard std) { - return shader_manager->get_attribute_id(std); + return scene->shader_manager->get_attribute_id(std); } uint SVMCompiler::attribute_standard(ustring name) @@ -838,8 +833,7 @@ void SVMCompiler::compile_type(Shader *shader, ShaderGraph *graph, ShaderType ty } } -void SVMCompiler::compile( - Scene *scene, Shader *shader, array<int4> &svm_nodes, int index, Summary *summary) +void SVMCompiler::compile(Shader *shader, array<int4> &svm_nodes, int index, Summary *summary) { /* copy graph for shader with bump mapping */ ShaderNode *output = shader->graph->output(); diff --git a/intern/cycles/render/svm.h b/intern/cycles/render/svm.h index d1534567bea..61923fc40ac 100644 --- a/intern/cycles/render/svm.h +++ b/intern/cycles/render/svm.h @@ -93,11 +93,8 @@ class SVMCompiler { string full_report() const; }; - SVMCompiler(ShaderManager *shader_manager, - ImageManager *image_manager, - LightManager *light_manager); - void compile( - Scene *scene, Shader *shader, array<int4> &svm_nodes, int index, Summary *summary = NULL); + SVMCompiler(Scene *scene); + void compile(Shader *shader, array<int4> &svm_nodes, int index, Summary *summary = NULL); int stack_assign(ShaderOutput *output); int stack_assign(ShaderInput *input); @@ -126,9 +123,8 @@ class SVMCompiler { return current_type; } - ImageManager *image_manager; - ShaderManager *shader_manager; - LightManager *light_manager; + Scene *scene; + ShaderGraph *current_graph; bool background; protected: @@ -221,7 +217,6 @@ class SVMCompiler { array<int4> current_svm_nodes; ShaderType current_type; Shader *current_shader; - ShaderGraph *current_graph; Stack active_stack; int max_stack_use; uint mix_weight_offset; diff --git a/intern/cycles/test/render_graph_finalize_test.cpp b/intern/cycles/test/render_graph_finalize_test.cpp index ca93f8b02d0..ace4f29913b 100644 --- a/intern/cycles/test/render_graph_finalize_test.cpp +++ b/intern/cycles/test/render_graph_finalize_test.cpp @@ -158,10 +158,11 @@ class RenderGraph : public testing::Test { Device *device_cpu; SceneParams scene_params; Scene *scene; + Shader shader; ShaderGraph graph; ShaderGraphBuilder builder; - RenderGraph() : testing::Test(), builder(&graph) + RenderGraph() : testing::Test(), graph(&shader), builder(&graph) { } |