diff options
author | Brecht Van Lommel <brechtvanlommel@gmail.com> | 2020-03-08 12:42:11 +0300 |
---|---|---|
committer | Brecht Van Lommel <brecht@blender.org> | 2020-03-11 22:35:38 +0300 |
commit | d8aa613d94caf6a3d82a8f4e9e90b9b8f5c61a7d (patch) | |
tree | 7f85577ae4f37c9bdeba31fd65411b718b19b035 /intern | |
parent | ec3eeee46b4885b9167b0dc28d273993d77b8ce6 (diff) |
Cleanup: add ImageHandle to centralize image ownership logic
Diffstat (limited to 'intern')
-rw-r--r-- | intern/cycles/blender/blender_shader.cpp | 25 | ||||
-rw-r--r-- | intern/cycles/blender/blender_volume.cpp | 5 | ||||
-rw-r--r-- | intern/cycles/render/attribute.cpp | 23 | ||||
-rw-r--r-- | intern/cycles/render/attribute.h | 29 | ||||
-rw-r--r-- | intern/cycles/render/geometry.cpp | 17 | ||||
-rw-r--r-- | intern/cycles/render/geometry.h | 2 | ||||
-rw-r--r-- | intern/cycles/render/image.cpp | 201 | ||||
-rw-r--r-- | intern/cycles/render/image.h | 63 | ||||
-rw-r--r-- | intern/cycles/render/light.cpp | 4 | ||||
-rw-r--r-- | intern/cycles/render/mesh_volume.cpp | 6 | ||||
-rw-r--r-- | intern/cycles/render/nodes.cpp | 334 | ||||
-rw-r--r-- | intern/cycles/render/nodes.h | 26 |
12 files changed, 340 insertions, 395 deletions
diff --git a/intern/cycles/blender/blender_shader.cpp b/intern/cycles/blender/blender_shader.cpp index 25e1d60f84d..64367d5fcd0 100644 --- a/intern/cycles/blender/blender_shader.cpp +++ b/intern/cycles/blender/blender_shader.cpp @@ -686,14 +686,6 @@ static ShaderNode *add_node(Scene *scene, 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 - if (b_image.is_updated()) { - scene->image_manager->tag_reload_image(image->image_key()); - } -#endif } node = image; } @@ -730,14 +722,6 @@ static ShaderNode *add_node(Scene *scene, env->animated = b_env_node.image_user().use_auto_refresh(); env->alpha_type = get_image_alpha_type(b_image); - - /* TODO: restore */ - /* TODO(sergey): Does not work properly when we change builtin type. */ -#if 0 - if (b_image.is_updated()) { - scene->image_manager->tag_reload_image(env->image_key()); - } -#endif } node = env; } @@ -885,14 +869,9 @@ static ShaderNode *add_node(Scene *scene, point_density->space = (NodeTexVoxelSpace)b_point_density_node.space(); point_density->interpolation = get_image_interpolation(b_point_density_node); point_density->builtin_data = b_point_density_node.ptr.data; - point_density->image_manager = scene->image_manager; - /* TODO(sergey): Use more proper update flag. */ - if (true) { - point_density->add_image(); - b_point_density_node.cache_point_density(b_depsgraph); - scene->image_manager->tag_reload_image(point_density->image_key()); - } + point_density->add_image(scene->image_manager); + b_point_density_node.cache_point_density(b_depsgraph); node = point_density; /* Transformation form world space to texture space. diff --git a/intern/cycles/blender/blender_volume.cpp b/intern/cycles/blender/blender_volume.cpp index 4dab60088bb..e11cc4ab18f 100644 --- a/intern/cycles/blender/blender_volume.cpp +++ b/intern/cycles/blender/blender_volume.cpp @@ -48,15 +48,12 @@ static void sync_smoke_volume(Scene *scene, BL::Object &b_ob, Mesh *mesh, float mesh->volume_isovalue = b_domain.clipping(); Attribute *attr = mesh->attributes.add(std); - VoxelAttribute *volume_data = attr->data_voxel(); - ImageMetaData metadata; ImageKey key; key.filename = Attribute::standard_name(std); key.builtin_data = b_ob.ptr.data; - volume_data->manager = image_manager; - volume_data->slot = image_manager->add_image(key, frame, metadata); + attr->add(image_manager->add_image(key, frame)); } /* Create a matrix to transform from object space to mesh texture space. diff --git a/intern/cycles/render/attribute.cpp b/intern/cycles/render/attribute.cpp index 1e293f1aa16..fffd26f906a 100644 --- a/intern/cycles/render/attribute.cpp +++ b/intern/cycles/render/attribute.cpp @@ -28,13 +28,10 @@ CCL_NAMESPACE_BEGIN Attribute::~Attribute() { - /* for voxel data, we need to remove the image from the image manager */ + /* For voxel data, we need to free the image handle. */ if (element == ATTR_ELEMENT_VOXEL) { - VoxelAttribute *voxel_data = data_voxel(); - - if (voxel_data && voxel_data->slot != -1) { - voxel_data->manager->remove_image(voxel_data->slot); - } + ImageHandle &handle = data_voxel(); + handle.~ImageHandle(); } } @@ -123,15 +120,13 @@ void Attribute::add(const Transform &f) buffer.push_back(data[i]); } -void Attribute::add(const VoxelAttribute &f) +void Attribute::add(const ImageHandle &handle) { - assert(data_sizeof() == sizeof(VoxelAttribute)); + assert(data_sizeof() == sizeof(ImageHandle)); + assert(buffer.size() == 0); - char *data = (char *)&f; - size_t size = sizeof(f); - - for (size_t i = 0; i < size; i++) - buffer.push_back(data[i]); + buffer.resize(sizeof(ImageHandle)); + new (buffer.data()) ImageHandle(handle); } void Attribute::add(const char *data) @@ -145,7 +140,7 @@ void Attribute::add(const char *data) size_t Attribute::data_sizeof() const { if (element == ATTR_ELEMENT_VOXEL) - return sizeof(VoxelAttribute); + return sizeof(ImageHandle); else if (element == ATTR_ELEMENT_CORNER_BYTE) return sizeof(uchar4); else if (type == TypeDesc::TypeFloat) diff --git a/intern/cycles/render/attribute.h b/intern/cycles/render/attribute.h index f1fd30fd85a..23626410ac1 100644 --- a/intern/cycles/render/attribute.h +++ b/intern/cycles/render/attribute.h @@ -17,6 +17,8 @@ #ifndef __ATTRIBUTE_H__ #define __ATTRIBUTE_H__ +#include "render/image.h" + #include "kernel/kernel_types.h" #include "util/util_list.h" @@ -31,19 +33,12 @@ class Attribute; class AttributeRequest; class AttributeRequestSet; class AttributeSet; -class ImageManager; +class ImageHandle; class Geometry; class Hair; class Mesh; struct Transform; -/* Attributes for voxels are images */ - -struct VoxelAttribute { - ImageManager *manager; - int slot; -}; - /* Attribute * * Arbitrary data layers on meshes. @@ -105,10 +100,12 @@ class Attribute { assert(data_sizeof() == sizeof(Transform)); return (Transform *)data(); } - VoxelAttribute *data_voxel() + + /* Attributes for voxels are images */ + ImageHandle &data_voxel() { - assert(data_sizeof() == sizeof(VoxelAttribute)); - return (VoxelAttribute *)data(); + assert(data_sizeof() == sizeof(ImageHandle)); + return *(ImageHandle *)data(); } const char *data() const @@ -140,10 +137,10 @@ class Attribute { assert(data_sizeof() == sizeof(Transform)); return (const Transform *)data(); } - const VoxelAttribute *data_voxel() const + const ImageHandle &data_voxel() const { - assert(data_sizeof() == sizeof(VoxelAttribute)); - return (const VoxelAttribute *)data(); + assert(data_sizeof() == sizeof(ImageHandle)); + return *(const ImageHandle *)data(); } void zero_data(void *dst); @@ -153,8 +150,8 @@ class Attribute { void add(const float2 &f); void add(const float3 &f); void add(const uchar4 &f); - void add(const Transform &f); - void add(const VoxelAttribute &f); + void add(const Transform &tfm); + void add(const ImageHandle &handle); void add(const char *data); static bool same_storage(TypeDesc a, TypeDesc b); diff --git a/intern/cycles/render/geometry.cpp b/intern/cycles/render/geometry.cpp index 880fb7b4c7d..748a8f7cf67 100644 --- a/intern/cycles/render/geometry.cpp +++ b/intern/cycles/render/geometry.cpp @@ -534,8 +534,8 @@ static void update_attribute_element_offset(Geometry *geom, if (mattr->element == ATTR_ELEMENT_VOXEL) { /* store slot in offset value */ - VoxelAttribute *voxel_data = mattr->data_voxel(); - offset = voxel_data->slot; + ImageHandle &handle = mattr->data_voxel(); + offset = handle.svm_slot(); } else if (mattr->element == ATTR_ELEMENT_CORNER_BYTE) { uchar4 *data = mattr->data_uchar4(); @@ -1143,7 +1143,7 @@ void GeometryManager::device_update_preprocess(Device *device, Scene *scene, Pro } Mesh *mesh = static_cast<Mesh *>(geom); - create_volume_mesh(scene, mesh, progress); + create_volume_mesh(mesh, progress); } } } @@ -1171,7 +1171,8 @@ void GeometryManager::device_update_displacement_images(Device *device, } ImageSlotTextureNode *image_node = static_cast<ImageSlotTextureNode *>(node); - foreach (int slot, image_node->slots) { + for (int i = 0; i < image_node->handle.num_tiles(); i++) { + const int slot = image_node->handle.svm_slot(i); if (slot != -1) { bump_images.insert(slot); } @@ -1204,10 +1205,10 @@ void GeometryManager::device_update_volume_images(Device *device, Scene *scene, continue; } - VoxelAttribute *voxel = attr.data_voxel(); - - if (voxel->slot != -1) { - volume_images.insert(voxel->slot); + ImageHandle &handle = attr.data_voxel(); + const int slot = handle.svm_slot(); + if (slot != -1) { + volume_images.insert(slot); } } } diff --git a/intern/cycles/render/geometry.h b/intern/cycles/render/geometry.h index 66ae8472102..82f539d391d 100644 --- a/intern/cycles/render/geometry.h +++ b/intern/cycles/render/geometry.h @@ -166,7 +166,7 @@ class GeometryManager { protected: bool displace(Device *device, DeviceScene *dscene, Scene *scene, Mesh *mesh, Progress &progress); - void create_volume_mesh(Scene *scene, Mesh *mesh, Progress &progress); + void create_volume_mesh(Mesh *mesh, Progress &progress); /* Attributes */ void update_osl_attributes(Device *device, diff --git a/intern/cycles/render/image.cpp b/intern/cycles/render/image.cpp index 7053d992621..123bb129466 100644 --- a/intern/cycles/render/image.cpp +++ b/intern/cycles/render/image.cpp @@ -79,6 +79,92 @@ const char *name_from_type(ImageDataType type) } // namespace +/* Image Handle */ + +ImageHandle::ImageHandle() : manager(NULL) +{ +} + +ImageHandle::ImageHandle(const ImageHandle &other) : slots(other.slots), manager(other.manager) +{ + /* Increase image user count. */ + foreach (const int slot, slots) { + manager->add_image_user(slot); + } +} + +ImageHandle &ImageHandle::operator=(const ImageHandle &other) +{ + clear(); + manager = other.manager; + slots = other.slots; + + foreach (const int slot, slots) { + manager->add_image_user(slot); + } + + return *this; +} + +ImageHandle::~ImageHandle() +{ + clear(); +} + +void ImageHandle::clear() +{ + foreach (const int slot, slots) { + manager->remove_image_user(slot); + } +} + +bool ImageHandle::empty() +{ + return slots.empty(); +} + +int ImageHandle::num_tiles() +{ + return slots.size(); +} + +ImageMetaData ImageHandle::metadata() +{ + if (slots.empty()) { + return ImageMetaData(); + } + + return manager->images[slots.front()]->metadata; +} + +int ImageHandle::svm_slot(const int tile_index) +{ + if (tile_index >= slots.size()) { + return -1; + } + + if (manager->osl_texture_system) { + ImageManager::Image *img = manager->images[slots[tile_index]]; + if (!img->key.builtin_data) { + return -1; + } + } + + return slots[tile_index]; +} + +device_memory *ImageHandle::image_memory(const int tile_index) +{ + if (tile_index >= slots.size()) { + return NULL; + } + + ImageManager::Image *img = manager->images[slots[tile_index]]; + return img ? img->mem : NULL; +} + +/* Image Manager */ + ImageManager::ImageManager(const DeviceInfo &info) { need_update = true; @@ -86,10 +172,7 @@ ImageManager::ImageManager(const DeviceInfo &info) animation_frame = 0; /* Set image limits */ - max_num_images = TEX_NUM_MAX; has_half_images = info.has_half_images; - - tex_num_images = 0; } ImageManager::~ImageManager() @@ -117,31 +200,6 @@ bool ImageManager::set_animation_frame_update(int frame) return false; } -device_memory *ImageManager::image_memory(int slot) -{ - if (slot == -1) { - return NULL; - } - - Image *img = images[slot]; - return img ? img->mem : NULL; -} - -bool ImageManager::get_image_metadata(int slot, ImageMetaData &metadata) -{ - if (slot == -1) { - return false; - } - - Image *img = images[slot]; - if (img) { - metadata = img->metadata; - return true; - } - - return false; -} - void ImageManager::metadata_detect_colorspace(ImageMetaData &metadata, const char *file_format) { /* Convert used specified color spaces to one we know how to handle. */ @@ -174,7 +232,7 @@ void ImageManager::metadata_detect_colorspace(ImageMetaData &metadata, const cha } } -bool ImageManager::get_image_metadata(const ImageKey &key, ImageMetaData &metadata) +bool ImageManager::load_image_metadata(const ImageKey &key, ImageMetaData &metadata) { metadata = ImageMetaData(); metadata.colorspace = key.colorspace; @@ -267,12 +325,37 @@ bool ImageManager::get_image_metadata(const ImageKey &key, ImageMetaData &metada return true; } -int ImageManager::add_image(const ImageKey &key, float frame, ImageMetaData &metadata) +ImageHandle ImageManager::add_image(const ImageKey &key, float frame) +{ + ImageHandle handle; + handle.slots.push_back(add_image_slot(key, frame)); + handle.manager = this; + return handle; +} + +ImageHandle ImageManager::add_image(const ImageKey &key, float frame, const vector<int> &tiles) +{ + ImageHandle handle; + handle.manager = this; + + foreach (int tile, tiles) { + ImageKey tile_key = key; + if (tile != 0) { + string_replace(tile_key.filename, "<UDIM>", string_printf("%04d", tile)); + } + handle.slots.push_back(add_image_slot(tile_key, frame)); + } + + return handle; +} + +int ImageManager::add_image_slot(const ImageKey &key, float frame) { Image *img; size_t slot; - get_image_metadata(key, metadata); + ImageMetaData metadata; + load_image_metadata(key, metadata); thread_scoped_lock device_lock(device_mutex); @@ -309,19 +392,6 @@ int ImageManager::add_image(const ImageKey &key, float frame, ImageMetaData &met break; } - /* Count if we're over the limit. - * Very unlikely, since max_num_images is insanely big. But better safe - * than sorry. - */ - if (tex_num_images > max_num_images) { - printf( - "ImageManager::add_image: Reached image limit (%d), " - "skipping '%s'\n", - max_num_images, - key.filename.c_str()); - return -1; - } - if (slot == images.size()) { images.resize(images.size() + 1); } @@ -337,8 +407,6 @@ int ImageManager::add_image(const ImageKey &key, float frame, ImageMetaData &met images[slot] = img; - ++tex_num_images; - need_update = true; return slot; @@ -352,7 +420,7 @@ void ImageManager::add_image_user(int slot) image->users++; } -void ImageManager::remove_image(int slot) +void ImageManager::remove_image_user(int slot) { Image *image = images[slot]; assert(image && image->users >= 1); @@ -367,32 +435,6 @@ void ImageManager::remove_image(int slot) need_update = true; } -void ImageManager::remove_image(const ImageKey &key) -{ - size_t slot; - - for (slot = 0; slot < images.size(); slot++) { - if (images[slot] && images[slot]->key == key) { - remove_image(slot); - return; - } - } -} - -/* TODO(sergey): Deduplicate with the iteration above, but make it pretty, - * without bunch of arguments passing around making code readability even - * more cluttered. - */ -void ImageManager::tag_reload_image(const ImageKey &key) -{ - for (size_t slot = 0; slot < images.size(); slot++) { - if (images[slot] && images[slot]->key == key) { - images[slot]->need_load = true; - break; - } - } -} - static bool image_associate_alpha(ImageManager::Image *img) { /* For typical RGBA images we let OIIO convert to associated alpha, @@ -881,7 +923,6 @@ void ImageManager::device_free_image(Device *, int slot) delete img; images[slot] = NULL; - --tex_num_images; } } @@ -900,9 +941,13 @@ void ImageManager::device_update(Device *device, Scene *scene, Progress &progres device_free_image(device, slot); } else if (images[slot]->need_load) { - if (!osl_texture_system || images[slot]->key.builtin_data) + if (osl_texture_system && !images[slot]->key.builtin_data) { + images[slot]->need_load = false; + } + else { pool.push( function_bind(&ImageManager::device_load_image, this, device, scene, slot, &progress)); + } } } @@ -920,8 +965,12 @@ void ImageManager::device_update_slot(Device *device, Scene *scene, int slot, Pr device_free_image(device, slot); } else if (image->need_load) { - if (!osl_texture_system || image->key.builtin_data) + if (osl_texture_system && !image->key.builtin_data) { + images[slot]->need_load = false; + } + else { device_load_image(device, scene, slot, progress); + } } } diff --git a/intern/cycles/render/image.h b/intern/cycles/render/image.h index 49fef9f0de3..b23bb7bed63 100644 --- a/intern/cycles/render/image.h +++ b/intern/cycles/render/image.h @@ -31,11 +31,18 @@ CCL_NAMESPACE_BEGIN class Device; +class ImageHandle; +class ImageKey; +class ImageMetaData; +class ImageManager; class Progress; class RenderStats; class Scene; class ColorSpaceProcessor; +/* Image MetaData + * + * Information about the image that is available before the image pxeisl are loaded. */ class ImageMetaData { public: /* Must be set by image file or builtin callback. */ @@ -72,6 +79,10 @@ class ImageMetaData { } }; +/* Image Key + * + * Image description that uniquely identifies and images. When adding images + * with the same key, they will be internally deduplicated. */ class ImageKey { public: string filename; @@ -101,18 +112,44 @@ class ImageKey { } }; +/* Image Handle + * + * Access handle for image in the image manager. Multiple shader nodes may + * share the same image, and this class handles reference counting for that. */ +class ImageHandle { + public: + ImageHandle(); + ImageHandle(const ImageHandle &other); + ImageHandle &operator=(const ImageHandle &other); + ~ImageHandle(); + + void clear(); + + bool empty(); + int num_tiles(); + + ImageMetaData metadata(); + int svm_slot(const int tile_index = 0); + device_memory *image_memory(const int tile_index = 0); + + protected: + vector<int> slots; + ImageManager *manager; + + friend class ImageManager; +}; + +/* Image Manager + * + * Handles loading and storage of all images in the scene. This includes 2D + * texture images and 3D volume images. */ class ImageManager { public: explicit ImageManager(const DeviceInfo &info); ~ImageManager(); - int add_image(const ImageKey &key, float frame, ImageMetaData &metadata); - void add_image_user(int slot); - void remove_image(int slot); - void remove_image(const ImageKey &key); - void tag_reload_image(const ImageKey &key); - bool get_image_metadata(const ImageKey &key, ImageMetaData &metadata); - bool get_image_metadata(int slot, ImageMetaData &metadata); + ImageHandle add_image(const ImageKey &key, float frame); + ImageHandle add_image(const ImageKey &key, float frame, const vector<int> &tiles); void device_update(Device *device, Scene *scene, Progress &progress); void device_update_slot(Device *device, Scene *scene, int slot, Progress *progress); @@ -124,8 +161,6 @@ class ImageManager { void set_osl_texture_system(void *texture_system); bool set_animation_frame_update(int frame); - device_memory *image_memory(int slot); - void collect_statistics(RenderStats *stats); bool need_update; @@ -167,8 +202,6 @@ class ImageManager { }; private: - int tex_num_images; - int max_num_images; bool has_half_images; thread_mutex device_mutex; @@ -177,6 +210,12 @@ class ImageManager { vector<Image *> images; void *osl_texture_system; + int add_image_slot(const ImageKey &key, float frame); + void add_image_user(int slot); + void remove_image_user(int slot); + + bool load_image_metadata(const ImageKey &key, ImageMetaData &metadata); + bool file_load_image_generic(Image *img, unique_ptr<ImageInput> *in); template<TypeDesc::BASETYPE FileFormat, typename StorageType, typename DeviceType> @@ -186,6 +225,8 @@ class ImageManager { void device_load_image(Device *device, Scene *scene, int slot, Progress *progress); void device_free_image(Device *device, int slot); + + friend class ImageHandle; }; CCL_NAMESPACE_END diff --git a/intern/cycles/render/light.cpp b/intern/cycles/render/light.cpp index 509637aedd9..8263f68fa9c 100644 --- a/intern/cycles/render/light.cpp +++ b/intern/cycles/render/light.cpp @@ -577,8 +577,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->slots.empty() && - env->image_manager->get_image_metadata(env->slots[0], metadata)) { + if (!env->handle.empty()) { + ImageMetaData metadata = env->handle.metadata(); res.x = max(res.x, metadata.width); res.y = max(res.y, metadata.height); } diff --git a/intern/cycles/render/mesh_volume.cpp b/intern/cycles/render/mesh_volume.cpp index 74c6a7759a6..3c91aba511d 100644 --- a/intern/cycles/render/mesh_volume.cpp +++ b/intern/cycles/render/mesh_volume.cpp @@ -362,7 +362,7 @@ struct VoxelAttributeGrid { int channels; }; -void GeometryManager::create_volume_mesh(Scene *scene, Mesh *mesh, Progress &progress) +void GeometryManager::create_volume_mesh(Mesh *mesh, Progress &progress) { string msg = string_printf("Computing Volume Mesh %s", mesh->name.c_str()); progress.set_status("Updating Mesh", msg); @@ -378,8 +378,8 @@ void GeometryManager::create_volume_mesh(Scene *scene, Mesh *mesh, Progress &pro continue; } - VoxelAttribute *voxel = attr.data_voxel(); - device_memory *image_memory = scene->image_manager->image_memory(voxel->slot); + ImageHandle &handle = attr.data_voxel(); + device_memory *image_memory = handle.image_memory(); int3 resolution = make_int3( image_memory->data_width, image_memory->data_height, image_memory->data_depth); diff --git a/intern/cycles/render/nodes.cpp b/intern/cycles/render/nodes.cpp index e90b846f7e5..bbdb2572392 100644 --- a/intern/cycles/render/nodes.cpp +++ b/intern/cycles/render/nodes.cpp @@ -206,27 +206,6 @@ 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); @@ -276,8 +255,6 @@ NODE_DEFINE(ImageTextureNode) ImageTextureNode::ImageTextureNode() : ImageSlotTextureNode(node_type) { - is_float = false; - compress_as_srgb = false; colorspace = u_colorspace_raw; builtin_data = NULL; animated = false; @@ -286,17 +263,15 @@ ImageTextureNode::ImageTextureNode() : ImageSlotTextureNode(node_type) ShaderNode *ImageTextureNode::clone() const { - add_image_user(); - return new ImageTextureNode(*this); + ImageTextureNode *node = new ImageTextureNode(*this); + node->handle = handle; + return node; } -ImageKey ImageTextureNode::image_key(const int tile) const +ImageKey ImageTextureNode::image_key() const { ImageKey key; key.filename = filename.string(); - if (tile != 0) { - string_replace(key.filename, "<UDIM>", string_printf("%04d", tile)); - } key.builtin_data = builtin_data; key.animated = animated; key.interpolation = interpolation; @@ -388,113 +363,81 @@ void ImageTextureNode::compile(SVMCompiler &compiler) ShaderOutput *color_out = output("Color"); ShaderOutput *alpha_out = output("Alpha"); - image_manager = compiler.scene->image_manager; - if (slots.empty()) { + if (handle.empty()) { cull_tiles(compiler.scene, compiler.current_graph); - slots.reserve(tiles.size()); - - bool have_metadata = false; - foreach (int tile, tiles) { - ImageKey key = image_key(tile); - ImageMetaData metadata; - int slot = image_manager->add_image(key, 0, 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; - } + ImageManager *image_manager = compiler.scene->image_manager; + handle = image_manager->add_image(image_key(), 0, tiles); } - if (has_image) { - int vector_offset = tex_mapping.compile_begin(compiler, vector_in); - uint flags = 0; + /* All tiles have the same metadata. */ + const ImageMetaData metadata = handle.metadata(); + const bool compress_as_srgb = metadata.compress_as_srgb; + const ustring known_colorspace = metadata.colorspace; + + int vector_offset = tex_mapping.compile_begin(compiler, vector_in); + uint flags = 0; + + if (compress_as_srgb) { + flags |= NODE_IMAGE_COMPRESS_AS_SRGB; + } + if (!alpha_out->links.empty()) { + const bool unassociate_alpha = !(ColorSpaceManager::colorspace_is_data(colorspace) || + alpha_type == IMAGE_ALPHA_CHANNEL_PACKED || + alpha_type == IMAGE_ALPHA_IGNORE); - if (compress_as_srgb) { - flags |= NODE_IMAGE_COMPRESS_AS_SRGB; + if (unassociate_alpha) { + flags |= NODE_IMAGE_ALPHA_UNASSOCIATE; } - if (!alpha_out->links.empty()) { - const bool unassociate_alpha = !(ColorSpaceManager::colorspace_is_data(colorspace) || - alpha_type == IMAGE_ALPHA_CHANNEL_PACKED || - alpha_type == IMAGE_ALPHA_IGNORE); + } - if (unassociate_alpha) { - flags |= NODE_IMAGE_ALPHA_UNASSOCIATE; - } + if (projection != NODE_IMAGE_PROJ_BOX) { + /* If there only is one image (a very common case), we encode it as a negative value. */ + int num_nodes; + if (handle.num_tiles() == 1) { + num_nodes = -handle.svm_slot(); + } + else { + num_nodes = divide_up(handle.num_tiles(), 2); } - if (projection != NODE_IMAGE_PROJ_BOX) { - /* 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); - } + compiler.add_node(NODE_TEX_IMAGE, + num_nodes, + compiler.encode_uchar4(vector_offset, + compiler.stack_assign_if_linked(color_out), + compiler.stack_assign_if_linked(alpha_out), + flags), + projection); - compiler.add_node(NODE_TEX_IMAGE, - num_nodes, - compiler.encode_uchar4(vector_offset, - compiler.stack_assign_if_linked(color_out), - compiler.stack_assign_if_linked(alpha_out), - flags), - projection); - - 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); + if (num_nodes > 0) { + for (int i = 0; i < num_nodes; i++) { + int4 node; + node.x = tiles[2 * i]; + node.y = handle.svm_slot(2 * i); + if (2 * i + 1 < tiles.size()) { + node.z = tiles[2 * i + 1]; + node.w = handle.svm_slot(2 * i + 1); + } + else { + node.z = -1; + node.w = -1; } + compiler.add_node(node.x, node.y, node.z, node.w); } } - else { - assert(slots.size() == 1); - compiler.add_node(NODE_TEX_IMAGE_BOX, - slots[0], - compiler.encode_uchar4(vector_offset, - compiler.stack_assign_if_linked(color_out), - compiler.stack_assign_if_linked(alpha_out), - flags), - __float_as_int(projection_blend)); - } - - tex_mapping.compile_end(compiler, vector_in, vector_offset); } else { - /* image not found */ - if (!color_out->links.empty()) { - compiler.add_node(NODE_VALUE_V, compiler.stack_assign(color_out)); - compiler.add_node( - NODE_VALUE_V, - make_float3(TEX_IMAGE_MISSING_R, TEX_IMAGE_MISSING_G, TEX_IMAGE_MISSING_B)); - } - if (!alpha_out->links.empty()) - compiler.add_node( - NODE_VALUE_F, __float_as_int(TEX_IMAGE_MISSING_A), compiler.stack_assign(alpha_out)); + assert(handle.num_tiles() == 1); + compiler.add_node(NODE_TEX_IMAGE_BOX, + handle.svm_slot(), + compiler.encode_uchar4(vector_offset, + compiler.stack_assign_if_linked(color_out), + compiler.stack_assign_if_linked(alpha_out), + flags), + __float_as_int(projection_blend)); } + + tex_mapping.compile_end(compiler, vector_in, vector_offset); } void ImageTextureNode::compile(OSLCompiler &compiler) @@ -503,29 +446,22 @@ void ImageTextureNode::compile(OSLCompiler &compiler) tex_mapping.compile(compiler); - image_manager = compiler.scene->image_manager; - if (slots.size() == 0) { - ImageMetaData metadata; - if (builtin_data == NULL) { - ImageKey key = image_key(1001); - image_manager->get_image_metadata(key, metadata); - slots.push_back(-1); - } - else { - int slot = image_manager->add_image(image_key(), 0, metadata); - slots.push_back(slot); - } - is_float = metadata.is_float; - compress_as_srgb = metadata.compress_as_srgb; - known_colorspace = metadata.colorspace; + if (handle.empty()) { + ImageManager *image_manager = compiler.scene->image_manager; + handle = image_manager->add_image(image_key(), 0); } - if (slots[0] == -1) { + const ImageMetaData metadata = handle.metadata(); + const bool is_float = metadata.is_float; + const bool compress_as_srgb = metadata.compress_as_srgb; + const ustring known_colorspace = metadata.colorspace; + + if (handle.svm_slot() == -1) { compiler.parameter_texture( "filename", filename, compress_as_srgb ? u_colorspace_raw : known_colorspace); } else { - compiler.parameter_texture("filename", slots[0]); + compiler.parameter_texture("filename", handle.svm_slot()); } const bool unassociate_alpha = !(ColorSpaceManager::colorspace_is_data(colorspace) || @@ -587,8 +523,6 @@ NODE_DEFINE(EnvironmentTextureNode) EnvironmentTextureNode::EnvironmentTextureNode() : ImageSlotTextureNode(node_type) { - is_float = false; - compress_as_srgb = false; colorspace = u_colorspace_raw; builtin_data = NULL; animated = false; @@ -596,8 +530,9 @@ EnvironmentTextureNode::EnvironmentTextureNode() : ImageSlotTextureNode(node_typ ShaderNode *EnvironmentTextureNode::clone() const { - add_image_user(); - return new EnvironmentTextureNode(*this); + EnvironmentTextureNode *node = new EnvironmentTextureNode(*this); + node->handle = handle; + return node; } ImageKey EnvironmentTextureNode::image_key() const @@ -632,46 +567,31 @@ void EnvironmentTextureNode::compile(SVMCompiler &compiler) ShaderOutput *color_out = output("Color"); ShaderOutput *alpha_out = output("Alpha"); - image_manager = compiler.scene->image_manager; - if (slots.empty()) { - ImageMetaData metadata; - int slot = image_manager->add_image(image_key(), 0, metadata); - slots.push_back(slot); - is_float = metadata.is_float; - compress_as_srgb = metadata.compress_as_srgb; - known_colorspace = metadata.colorspace; + if (handle.empty()) { + ImageManager *image_manager = compiler.scene->image_manager; + handle = image_manager->add_image(image_key(), 0); } - if (slots[0] != -1) { - int vector_offset = tex_mapping.compile_begin(compiler, vector_in); - uint flags = 0; + const ImageMetaData metadata = handle.metadata(); + const bool compress_as_srgb = metadata.compress_as_srgb; + const ustring known_colorspace = metadata.colorspace; - if (compress_as_srgb) { - flags |= NODE_IMAGE_COMPRESS_AS_SRGB; - } - - compiler.add_node(NODE_TEX_ENVIRONMENT, - slots[0], - compiler.encode_uchar4(vector_offset, - compiler.stack_assign_if_linked(color_out), - compiler.stack_assign_if_linked(alpha_out), - flags), - projection); + int vector_offset = tex_mapping.compile_begin(compiler, vector_in); + uint flags = 0; - tex_mapping.compile_end(compiler, vector_in, vector_offset); - } - else { - /* image not found */ - if (!color_out->links.empty()) { - compiler.add_node(NODE_VALUE_V, compiler.stack_assign(color_out)); - compiler.add_node( - NODE_VALUE_V, - make_float3(TEX_IMAGE_MISSING_R, TEX_IMAGE_MISSING_G, TEX_IMAGE_MISSING_B)); - } - if (!alpha_out->links.empty()) - compiler.add_node( - NODE_VALUE_F, __float_as_int(TEX_IMAGE_MISSING_A), compiler.stack_assign(alpha_out)); + if (compress_as_srgb) { + flags |= NODE_IMAGE_COMPRESS_AS_SRGB; } + + compiler.add_node(NODE_TEX_ENVIRONMENT, + handle.svm_slot(), + compiler.encode_uchar4(vector_offset, + compiler.stack_assign_if_linked(color_out), + compiler.stack_assign_if_linked(alpha_out), + flags), + projection); + + tex_mapping.compile_end(compiler, vector_in, vector_offset); } void EnvironmentTextureNode::compile(OSLCompiler &compiler) @@ -681,28 +601,22 @@ void EnvironmentTextureNode::compile(OSLCompiler &compiler) /* See comments in ImageTextureNode::compile about support * of builtin images. */ - image_manager = compiler.scene->image_manager; - if (slots.empty()) { - ImageMetaData metadata; - if (builtin_data == NULL) { - image_manager->get_image_metadata(image_key(), metadata); - slots.push_back(-1); - } - else { - int slot = image_manager->add_image(image_key(), 0, metadata); - slots.push_back(slot); - } - is_float = metadata.is_float; - compress_as_srgb = metadata.compress_as_srgb; - known_colorspace = metadata.colorspace; + if (handle.empty()) { + ImageManager *image_manager = compiler.scene->image_manager; + handle = image_manager->add_image(image_key(), 0); } - if (slots[0] == -1) { + const ImageMetaData metadata = handle.metadata(); + const bool is_float = metadata.is_float; + const bool compress_as_srgb = metadata.compress_as_srgb; + const ustring known_colorspace = metadata.colorspace; + + if (handle.svm_slot() == -1) { compiler.parameter_texture( "filename", filename, compress_as_srgb ? u_colorspace_raw : known_colorspace); } else { - compiler.parameter_texture("filename", slots[0]); + compiler.parameter_texture("filename", handle.svm_slot()); } compiler.parameter(this, "projection"); @@ -1741,16 +1655,11 @@ NODE_DEFINE(PointDensityTextureNode) PointDensityTextureNode::PointDensityTextureNode() : ShaderNode(node_type) { - image_manager = NULL; - slot = -1; builtin_data = NULL; } PointDensityTextureNode::~PointDensityTextureNode() { - if (image_manager) { - image_manager->remove_image(image_key()); - } } ShaderNode *PointDensityTextureNode::clone() const @@ -1758,10 +1667,9 @@ ShaderNode *PointDensityTextureNode::clone() const /* Increase image user count for new node. We need to ensure to not call * add_image again, to work around access of freed data on the Blender * side. A better solution should be found to avoid this. */ - if (slot != -1) { - image_manager->add_image_user(slot); - } - return new PointDensityTextureNode(*this); + PointDensityTextureNode *node = new PointDensityTextureNode(*this); + node->handle = handle; + return node; } void PointDensityTextureNode::attributes(Shader *shader, AttributeRequestSet *attributes) @@ -1772,21 +1680,18 @@ void PointDensityTextureNode::attributes(Shader *shader, AttributeRequestSet *at ShaderNode::attributes(shader, attributes); } -void PointDensityTextureNode::add_image() +void PointDensityTextureNode::add_image(ImageManager *image_manager) { - if (slot == -1) { - ImageMetaData metadata; - slot = image_manager->add_image(image_key(), 0, metadata); + if (!handle.empty()) { + return; } -} -ImageKey PointDensityTextureNode::image_key() const -{ ImageKey key; key.filename = filename.string(); key.builtin_data = builtin_data; key.interpolation = interpolation; - return key; + + handle = image_manager->add_image(key, 0); } void PointDensityTextureNode::compile(SVMCompiler &compiler) @@ -1798,11 +1703,10 @@ void PointDensityTextureNode::compile(SVMCompiler &compiler) const bool use_density = !density_out->links.empty(); const bool use_color = !color_out->links.empty(); - image_manager = compiler.scene->image_manager; - if (use_density || use_color) { - add_image(); + add_image(compiler.scene->image_manager); + const int slot = handle.svm_slot(); if (slot != -1) { compiler.stack_assign(vector_in); compiler.add_node(NODE_TEX_VOXEL, @@ -1839,12 +1743,10 @@ void PointDensityTextureNode::compile(OSLCompiler &compiler) const bool use_density = !density_out->links.empty(); const bool use_color = !color_out->links.empty(); - image_manager = compiler.scene->image_manager; - if (use_density || use_color) { - add_image(); + add_image(compiler.scene->image_manager); - compiler.parameter_texture("filename", slot); + compiler.parameter_texture("filename", handle.svm_slot()); if (space == NODE_TEX_VOXEL_SPACE_WORLD) { compiler.parameter("mapping", tfm); compiler.parameter("use_mapping", 1); diff --git a/intern/cycles/render/nodes.h b/intern/cycles/render/nodes.h index 1d76cb5e828..99e676fc8cb 100644 --- a/intern/cycles/render/nodes.h +++ b/intern/cycles/render/nodes.h @@ -78,12 +78,9 @@ class ImageSlotTextureNode : public TextureNode { explicit ImageSlotTextureNode(const NodeType *node_type) : TextureNode(node_type) { special_type = SHADER_SPECIAL_TYPE_IMAGE_SLOT; - image_manager = NULL; } - ~ImageSlotTextureNode(); - void add_image_user() const; - ImageManager *image_manager; - vector<int> slots; + + ImageHandle handle; }; class ImageTextureNode : public ImageSlotTextureNode { @@ -103,7 +100,7 @@ class ImageTextureNode : public ImageSlotTextureNode { animated == image_node.animated; } - ImageKey image_key(const int tile = 0) const; + ImageKey image_key() const; /* Parameters. */ ustring filename; @@ -118,11 +115,6 @@ class ImageTextureNode : public ImageSlotTextureNode { float3 vector; ccl::vector<int> tiles; - /* Runtime. */ - bool is_float; - bool compress_as_srgb; - ustring known_colorspace; - protected: void cull_tiles(Scene *scene, ShaderGraph *graph); }; @@ -159,11 +151,6 @@ class EnvironmentTextureNode : public ImageSlotTextureNode { InterpolationType interpolation; bool animated; float3 vector; - - /* Runtime. */ - bool is_float; - bool compress_as_srgb; - ustring known_colorspace; }; class SkyTextureNode : public TextureNode { @@ -370,9 +357,7 @@ class PointDensityTextureNode : public ShaderNode { return true; } - void add_image(); - - ImageKey image_key() const; + void add_image(ImageManager *image_manager); /* Parameters. */ ustring filename; @@ -383,8 +368,7 @@ class PointDensityTextureNode : public ShaderNode { void *builtin_data; /* Runtime. */ - ImageManager *image_manager; - int slot; + ImageHandle handle; virtual bool equals(const ShaderNode &other) { |