From e977fe985f019b7b28c022ffb0ca8fb37f6418ee Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Fri, 27 Jul 2018 10:16:30 +0200 Subject: Cycles: Cleanup in image manager, switch statement instead of if-else Allows to catch enumerator values which are missing from being handled. Also use `const char*`, no need to construct string just to throw it away. --- intern/cycles/render/image.cpp | 36 ++++++++++++++++++------------------ intern/cycles/render/image.h | 2 +- 2 files changed, 19 insertions(+), 19 deletions(-) diff --git a/intern/cycles/render/image.cpp b/intern/cycles/render/image.cpp index 27d6ae78289..854eddac716 100644 --- a/intern/cycles/render/image.cpp +++ b/intern/cycles/render/image.cpp @@ -253,24 +253,23 @@ int ImageManager::flattened_slot_to_type_index(int flat_slot, ImageDataType *typ return flat_slot >> IMAGE_DATA_TYPE_SHIFT; } -string ImageManager::name_from_type(int type) +const char* ImageManager::name_from_type(ImageDataType type) { - if(type == IMAGE_DATA_TYPE_FLOAT4) - return "float4"; - else if(type == IMAGE_DATA_TYPE_FLOAT) - return "float"; - else if(type == IMAGE_DATA_TYPE_BYTE) - return "byte"; - else if(type == IMAGE_DATA_TYPE_HALF4) - return "half4"; - else if(type == IMAGE_DATA_TYPE_HALF) - return "half"; - else if(type == IMAGE_DATA_TYPE_USHORT) - return "ushort"; - else if(type == IMAGE_DATA_TYPE_USHORT4) - return "ushort4"; - else - return "byte4"; + switch(type) { + case IMAGE_DATA_TYPE_FLOAT4: return "float4"; + case IMAGE_DATA_TYPE_BYTE4: return "byte4"; + case IMAGE_DATA_TYPE_HALF4: return "half4"; + case IMAGE_DATA_TYPE_FLOAT: return "float"; + case IMAGE_DATA_TYPE_BYTE: return "byte"; + case IMAGE_DATA_TYPE_HALF: return "half"; + case IMAGE_DATA_TYPE_USHORT4: return "ushort4"; + case IMAGE_DATA_TYPE_USHORT: return "ushort"; + case IMAGE_DATA_NUM_TYPES: + assert(!"System enumerator type, should never be used"); + return ""; + } + assert(!"Unhandled image data type"); + return ""; } static bool image_equals(ImageManager::Image *image, @@ -732,7 +731,8 @@ void ImageManager::device_load_image(Device *device, /* Slot assignment */ int flat_slot = type_index_to_flattened_slot(slot, type); - img->mem_name = string_printf("__tex_image_%s_%03d", name_from_type(type).c_str(), flat_slot); + img->mem_name = string_printf("__tex_image_%s_%03d", + name_from_type(type), flat_slot); /* Free previous texture in slot. */ if(img->mem) { diff --git a/intern/cycles/render/image.h b/intern/cycles/render/image.h index 5932c24cb74..627ad3ce6aa 100644 --- a/intern/cycles/render/image.h +++ b/intern/cycles/render/image.h @@ -152,7 +152,7 @@ private: int max_flattened_slot(ImageDataType type); int type_index_to_flattened_slot(int slot, ImageDataType type); int flattened_slot_to_type_index(int flat_slot, ImageDataType *type); - string name_from_type(int type); + const char* name_from_type(ImageDataType type); void device_load_image(Device *device, Scene *scene, -- cgit v1.2.3 From de80b928a33bb753bec360e0d4cfeafd0bf23b0c Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Fri, 27 Jul 2018 10:22:45 +0200 Subject: Cycles: Cleanup, remove unused function --- intern/cycles/render/image.cpp | 9 --------- intern/cycles/render/image.h | 1 - 2 files changed, 10 deletions(-) diff --git a/intern/cycles/render/image.cpp b/intern/cycles/render/image.cpp index 854eddac716..b8892a5329d 100644 --- a/intern/cycles/render/image.cpp +++ b/intern/cycles/render/image.cpp @@ -229,15 +229,6 @@ bool ImageManager::get_image_metadata(const string& filename, return true; } -int ImageManager::max_flattened_slot(ImageDataType type) -{ - if(tex_num_images[type] == 0) { - /* No textures for the type, no slots needs allocation. */ - return 0; - } - return type_index_to_flattened_slot(tex_num_images[type], type); -} - /* The lower three bits of a device texture slot number indicate its type. * These functions convert the slot ids from ImageManager "images" ones * to device ones and vice verse. diff --git a/intern/cycles/render/image.h b/intern/cycles/render/image.h index 627ad3ce6aa..40b8629d549 100644 --- a/intern/cycles/render/image.h +++ b/intern/cycles/render/image.h @@ -149,7 +149,6 @@ private: int texture_limit, device_vector& tex_img); - int max_flattened_slot(ImageDataType type); int type_index_to_flattened_slot(int slot, ImageDataType type); int flattened_slot_to_type_index(int flat_slot, ImageDataType *type); const char* name_from_type(ImageDataType type); -- cgit v1.2.3 From ca359461a803808a832ff603e2d01468a252c90f Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Fri, 27 Jul 2018 10:24:03 +0200 Subject: Cycles: Cleanup, move functions outside of class methods There is no reason or justification to have helper functions as class methods: they do not depend on anything in the class itself. There are probably more cases like that. --- intern/cycles/render/image.cpp | 78 ++++++++++++++++++++++-------------------- intern/cycles/render/image.h | 4 --- 2 files changed, 41 insertions(+), 41 deletions(-) diff --git a/intern/cycles/render/image.cpp b/intern/cycles/render/image.cpp index b8892a5329d..78451658764 100644 --- a/intern/cycles/render/image.cpp +++ b/intern/cycles/render/image.cpp @@ -30,20 +30,58 @@ CCL_NAMESPACE_BEGIN +namespace { + /* Some helpers to silence warning in templated function. */ -static bool isfinite(uchar /*value*/) +bool isfinite(uchar /*value*/) { return true; } -static bool isfinite(half /*value*/) +bool isfinite(half /*value*/) { return true; } -static bool isfinite(uint16_t /*value*/) +bool isfinite(uint16_t /*value*/) { return true; } +/* The lower three bits of a device texture slot number indicate its type. + * These functions convert the slot ids from ImageManager "images" ones + * to device ones and vice verse. + */ +int type_index_to_flattened_slot(int slot, ImageDataType type) +{ + return (slot << IMAGE_DATA_TYPE_SHIFT) | (type); +} + +int flattened_slot_to_type_index(int flat_slot, ImageDataType *type) +{ + *type = (ImageDataType)(flat_slot & IMAGE_DATA_TYPE_MASK); + return flat_slot >> IMAGE_DATA_TYPE_SHIFT; +} + +const char* name_from_type(ImageDataType type) +{ + switch(type) { + case IMAGE_DATA_TYPE_FLOAT4: return "float4"; + case IMAGE_DATA_TYPE_BYTE4: return "byte4"; + case IMAGE_DATA_TYPE_HALF4: return "half4"; + case IMAGE_DATA_TYPE_FLOAT: return "float"; + case IMAGE_DATA_TYPE_BYTE: return "byte"; + case IMAGE_DATA_TYPE_HALF: return "half"; + case IMAGE_DATA_TYPE_USHORT4: return "ushort4"; + case IMAGE_DATA_TYPE_USHORT: return "ushort"; + case IMAGE_DATA_NUM_TYPES: + assert(!"System enumerator type, should never be used"); + return ""; + } + assert(!"Unhandled image data type"); + return ""; +} + +} // namespace + ImageManager::ImageManager(const DeviceInfo& info) { need_update = true; @@ -229,40 +267,6 @@ bool ImageManager::get_image_metadata(const string& filename, return true; } -/* The lower three bits of a device texture slot number indicate its type. - * These functions convert the slot ids from ImageManager "images" ones - * to device ones and vice verse. - */ -int ImageManager::type_index_to_flattened_slot(int slot, ImageDataType type) -{ - return (slot << IMAGE_DATA_TYPE_SHIFT) | (type); -} - -int ImageManager::flattened_slot_to_type_index(int flat_slot, ImageDataType *type) -{ - *type = (ImageDataType)(flat_slot & IMAGE_DATA_TYPE_MASK); - return flat_slot >> IMAGE_DATA_TYPE_SHIFT; -} - -const char* ImageManager::name_from_type(ImageDataType type) -{ - switch(type) { - case IMAGE_DATA_TYPE_FLOAT4: return "float4"; - case IMAGE_DATA_TYPE_BYTE4: return "byte4"; - case IMAGE_DATA_TYPE_HALF4: return "half4"; - case IMAGE_DATA_TYPE_FLOAT: return "float"; - case IMAGE_DATA_TYPE_BYTE: return "byte"; - case IMAGE_DATA_TYPE_HALF: return "half"; - case IMAGE_DATA_TYPE_USHORT4: return "ushort4"; - case IMAGE_DATA_TYPE_USHORT: return "ushort"; - case IMAGE_DATA_NUM_TYPES: - assert(!"System enumerator type, should never be used"); - return ""; - } - assert(!"Unhandled image data type"); - return ""; -} - static bool image_equals(ImageManager::Image *image, const string& filename, void *builtin_data, diff --git a/intern/cycles/render/image.h b/intern/cycles/render/image.h index 40b8629d549..67af4ba886c 100644 --- a/intern/cycles/render/image.h +++ b/intern/cycles/render/image.h @@ -149,10 +149,6 @@ private: int texture_limit, device_vector& tex_img); - int type_index_to_flattened_slot(int slot, ImageDataType type); - int flattened_slot_to_type_index(int flat_slot, ImageDataType *type); - const char* name_from_type(ImageDataType type); - void device_load_image(Device *device, Scene *scene, ImageDataType type, -- cgit v1.2.3 From 46b85d195cd539d61673a6cf1ffa3704788912ce Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Fri, 27 Jul 2018 10:28:06 +0200 Subject: Cycles: Cleanup, line length --- intern/cycles/render/image.cpp | 29 +++++++++++++++++++---------- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/intern/cycles/render/image.cpp b/intern/cycles/render/image.cpp index 78451658764..7f090b7a752 100644 --- a/intern/cycles/render/image.cpp +++ b/intern/cycles/render/image.cpp @@ -171,10 +171,12 @@ bool ImageManager::get_image_metadata(const string& filename, if(metadata.is_float) { metadata.is_linear = true; - metadata.type = (metadata.channels > 1) ? IMAGE_DATA_TYPE_FLOAT4 : IMAGE_DATA_TYPE_FLOAT; + metadata.type = (metadata.channels > 1) ? IMAGE_DATA_TYPE_FLOAT4 + : IMAGE_DATA_TYPE_FLOAT; } else { - metadata.type = (metadata.channels > 1) ? IMAGE_DATA_TYPE_BYTE4 : IMAGE_DATA_TYPE_BYTE; + metadata.type = (metadata.channels > 1) ? IMAGE_DATA_TYPE_BYTE4 + : IMAGE_DATA_TYPE_BYTE; } return true; @@ -186,7 +188,8 @@ bool ImageManager::get_image_metadata(const string& filename, return false; } if(path_is_directory(filename)) { - VLOG(1) << "File '" << filename << "' is a directory, can't use as image."; + VLOG(1) << "File '" << filename + << "' is a directory, can't use as image."; return false; } @@ -249,16 +252,20 @@ bool ImageManager::get_image_metadata(const string& filename, metadata.channels = spec.nchannels; if(metadata.is_half) { - metadata.type = (metadata.channels > 1) ? IMAGE_DATA_TYPE_HALF4 : IMAGE_DATA_TYPE_HALF; + metadata.type = (metadata.channels > 1) ? IMAGE_DATA_TYPE_HALF4 + : IMAGE_DATA_TYPE_HALF; } else if(metadata.is_float) { - metadata.type = (metadata.channels > 1) ? IMAGE_DATA_TYPE_FLOAT4 : IMAGE_DATA_TYPE_FLOAT; + metadata.type = (metadata.channels > 1) ? IMAGE_DATA_TYPE_FLOAT4 + : IMAGE_DATA_TYPE_FLOAT; } else if(spec.format == TypeDesc::USHORT) { - metadata.type = (metadata.channels > 1) ? IMAGE_DATA_TYPE_USHORT4 : IMAGE_DATA_TYPE_USHORT; + metadata.type = (metadata.channels > 1) ? IMAGE_DATA_TYPE_USHORT4 + : IMAGE_DATA_TYPE_USHORT; } else { - metadata.type = (metadata.channels > 1) ? IMAGE_DATA_TYPE_BYTE4 : IMAGE_DATA_TYPE_BYTE; + metadata.type = (metadata.channels > 1) ? IMAGE_DATA_TYPE_BYTE4 + : IMAGE_DATA_TYPE_BYTE; } in->close(); @@ -338,14 +345,16 @@ int ImageManager::add_image(const string& filename, } /* Count if we're over the limit. - * Very unlikely, since max_num_images is insanely big. But better safe than sorry. */ + * Very unlikely, since max_num_images is insanely big. But better safe + * than sorry. + */ int tex_count = 0; for(int type = 0; type < IMAGE_DATA_NUM_TYPES; type++) { tex_count += tex_num_images[type]; } if(tex_count > max_num_images) { - printf("ImageManager::add_image: Reached image limit (%d), skipping '%s'\n", - max_num_images, filename.c_str()); + printf("ImageManager::add_image: Reached image limit (%d), " + "skipping '%s'\n", max_num_images, filename.c_str()); return -1; } -- cgit v1.2.3 From fcea94489cb181504435868472a74d4887bba947 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Fri, 27 Jul 2018 10:28:28 +0200 Subject: Cycles: Cleanup, indentation --- intern/cycles/render/image.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/intern/cycles/render/image.cpp b/intern/cycles/render/image.cpp index 7f090b7a752..741dfb0717a 100644 --- a/intern/cycles/render/image.cpp +++ b/intern/cycles/render/image.cpp @@ -128,12 +128,12 @@ bool ImageManager::set_animation_frame_update(int frame) device_memory *ImageManager::image_memory(int flat_slot) { - ImageDataType type; - int slot = flattened_slot_to_type_index(flat_slot, &type); + ImageDataType type; + int slot = flattened_slot_to_type_index(flat_slot, &type); - Image *img = images[type][slot]; + Image *img = images[type][slot]; - return img->mem; + return img->mem; } bool ImageManager::get_image_metadata(int flat_slot, -- cgit v1.2.3 From b517b310853cc752ca1bb92b4219b257f5a94e30 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Fri, 27 Jul 2018 10:30:10 +0200 Subject: Cycles: Cleanup, spelling --- intern/cycles/render/image.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/intern/cycles/render/image.h b/intern/cycles/render/image.h index 67af4ba886c..9a2b373d016 100644 --- a/intern/cycles/render/image.h +++ b/intern/cycles/render/image.h @@ -153,7 +153,7 @@ private: Scene *scene, ImageDataType type, int slot, - Progress *progess); + Progress *progress); void device_free_image(Device *device, ImageDataType type, int slot); -- cgit v1.2.3 From 75c47542d787c91293572b007bbf6787f903522a Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Fri, 27 Jul 2018 11:09:10 +0200 Subject: Cycles: Cleanup, indentation --- intern/cycles/render/mesh.cpp | 14 +++++++------- intern/cycles/render/mesh.h | 4 ++-- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/intern/cycles/render/mesh.cpp b/intern/cycles/render/mesh.cpp index 7a9d604244d..df408b478b2 100644 --- a/intern/cycles/render/mesh.cpp +++ b/intern/cycles/render/mesh.cpp @@ -2015,8 +2015,8 @@ void MeshManager::device_update_displacement_images(Device *device, } void MeshManager::device_update_volume_images(Device *device, - Scene *scene, - Progress& progress) + Scene *scene, + Progress& progress) { progress.set_status("Updating Volume Images"); TaskPool pool; @@ -2043,11 +2043,11 @@ void MeshManager::device_update_volume_images(Device *device, foreach(int slot, volume_images) { pool.push(function_bind(&ImageManager::device_update_slot, - image_manager, - device, - scene, - slot, - &progress)); + image_manager, + device, + scene, + slot, + &progress)); } pool.wait_work(); } diff --git a/intern/cycles/render/mesh.h b/intern/cycles/render/mesh.h index e7dc1c8e5cf..fc7d0b40273 100644 --- a/intern/cycles/render/mesh.h +++ b/intern/cycles/render/mesh.h @@ -381,8 +381,8 @@ protected: Progress& progress); void device_update_volume_images(Device *device, - Scene *scene, - Progress& progress); + Scene *scene, + Progress& progress); }; CCL_NAMESPACE_END -- cgit v1.2.3 From 67e690f5fcc084fbd949240f2c7733854079efc5 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Fri, 27 Jul 2018 11:19:29 +0200 Subject: Cycles: Cleanup, indentation --- intern/cycles/graph/node_type.cpp | 2 +- intern/cycles/graph/node_type.h | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/intern/cycles/graph/node_type.cpp b/intern/cycles/graph/node_type.cpp index 671ae2d815a..e045777e969 100644 --- a/intern/cycles/graph/node_type.cpp +++ b/intern/cycles/graph/node_type.cpp @@ -134,7 +134,7 @@ NodeType::~NodeType() void NodeType::register_input(ustring name, ustring ui_name, SocketType::Type type, int struct_offset, const void *default_value, const NodeEnum *enum_values, - const NodeType **node_type, int flags, int extra_flags) + const NodeType **node_type, int flags, int extra_flags) { SocketType socket; socket.name = name; diff --git a/intern/cycles/graph/node_type.h b/intern/cycles/graph/node_type.h index d4e2dbceff6..1d565794b27 100644 --- a/intern/cycles/graph/node_type.h +++ b/intern/cycles/graph/node_type.h @@ -114,9 +114,9 @@ struct NodeType void register_input(ustring name, ustring ui_name, SocketType::Type type, int struct_offset, const void *default_value, - const NodeEnum *enum_values = NULL, - const NodeType **node_type = NULL, - int flags = 0, int extra_flags = 0); + const NodeEnum *enum_values = NULL, + const NodeType **node_type = NULL, + int flags = 0, int extra_flags = 0); void register_output(ustring name, ustring ui_name, SocketType::Type type); const SocketType *find_input(ustring name) const; -- cgit v1.2.3 From 9a080d2ea6065b3686089c156cfa72d29744c953 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Fri, 27 Jul 2018 11:34:52 +0200 Subject: Fix T56092: command line arguments after -- beginning with -h don't work. --- intern/cycles/blender/addon/engine.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/intern/cycles/blender/addon/engine.py b/intern/cycles/blender/addon/engine.py index 08c6a65e5ad..7e06b15afdd 100644 --- a/intern/cycles/blender/addon/engine.py +++ b/intern/cycles/blender/addon/engine.py @@ -52,7 +52,9 @@ def _workaround_buggy_drivers(): def _configure_argument_parser(): import argparse - parser = argparse.ArgumentParser(description="Cycles Addon argument parser") + # No help because it conflicts with general Python scripts argument parsing + parser = argparse.ArgumentParser(description="Cycles Addon argument parser", + add_help=False) parser.add_argument("--cycles-resumable-num-chunks", help="Number of chunks to split sample range into", default=None) -- cgit v1.2.3 From 709b36e43b94678b18fec20a92d7d34f9b5aa78b Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Fri, 27 Jul 2018 11:40:44 +0200 Subject: Cycles: Add utility function to query graph node size in bytes --- intern/cycles/graph/node.cpp | 85 +++++++++++++++++++++++++++++++++++++++++--- intern/cycles/graph/node.h | 3 ++ 2 files changed, 84 insertions(+), 4 deletions(-) diff --git a/intern/cycles/graph/node.cpp b/intern/cycles/graph/node.cpp index 45ffc8d7d6b..5960d9aa7d5 100644 --- a/intern/cycles/graph/node.cpp +++ b/intern/cycles/graph/node.cpp @@ -425,20 +425,22 @@ bool Node::equals(const Node& other) const /* Hash */ +namespace { + template -static void value_hash(const Node *node, const SocketType& socket, MD5Hash& md5) +void value_hash(const Node *node, const SocketType& socket, MD5Hash& md5) { md5.append(((uint8_t*)node) + socket.struct_offset, socket.size()); } -static void float3_hash(const Node *node, const SocketType& socket, MD5Hash& md5) +void float3_hash(const Node *node, const SocketType& socket, MD5Hash& md5) { /* Don't compare 4th element used for padding. */ md5.append(((uint8_t*)node) + socket.struct_offset, sizeof(float) * 3); } template -static void array_hash(const Node *node, const SocketType& socket, MD5Hash& md5) +void array_hash(const Node *node, const SocketType& socket, MD5Hash& md5) { const array& a = *(const array*)(((char*)node) + socket.struct_offset); for (size_t i = 0; i < a.size(); i++) { @@ -446,7 +448,7 @@ static void array_hash(const Node *node, const SocketType& socket, MD5Hash& md5) } } -static void float3_array_hash(const Node *node, const SocketType& socket, MD5Hash& md5) +void float3_array_hash(const Node *node, const SocketType& socket, MD5Hash& md5) { /* Don't compare 4th element used for padding. */ const array& a = *(const array*)(((char*)node) + socket.struct_offset); @@ -455,6 +457,8 @@ static void float3_array_hash(const Node *node, const SocketType& socket, MD5Has } } +} // namespace + void Node::hash(MD5Hash& md5) { md5.append(type->name.string()); @@ -495,4 +499,77 @@ void Node::hash(MD5Hash& md5) } } +namespace { + +template +size_t array_size_in_bytes(const Node *node, const SocketType& socket) +{ + const array& a = *(const array*)(((char*)node) + socket.struct_offset); + return a.size() * sizeof(T); +} + +} // namespace + +size_t Node::get_total_size_in_bytes() const +{ + size_t total_size = 0; + foreach(const SocketType& socket, type->inputs) { + switch(socket.type) { + case SocketType::BOOLEAN: + case SocketType::FLOAT: + case SocketType::INT: + case SocketType::UINT: + case SocketType::COLOR: + case SocketType::VECTOR: + case SocketType::POINT: + case SocketType::NORMAL: + case SocketType::POINT2: + case SocketType::CLOSURE: + case SocketType::STRING: + case SocketType::ENUM: + case SocketType::TRANSFORM: + case SocketType::NODE: + total_size += socket.size(); + break; + + case SocketType::BOOLEAN_ARRAY: + total_size += array_size_in_bytes(this, socket); + break; + case SocketType::FLOAT_ARRAY: + total_size += array_size_in_bytes(this, socket); + break; + case SocketType::INT_ARRAY: + total_size += array_size_in_bytes(this, socket); + break; + case SocketType::COLOR_ARRAY: + total_size += array_size_in_bytes(this, socket); + break; + case SocketType::VECTOR_ARRAY: + total_size += array_size_in_bytes(this, socket); + break; + case SocketType::POINT_ARRAY: + total_size += array_size_in_bytes(this, socket); + break; + case SocketType::NORMAL_ARRAY: + total_size += array_size_in_bytes(this, socket); + break; + case SocketType::POINT2_ARRAY: + total_size += array_size_in_bytes(this, socket); + break; + case SocketType::STRING_ARRAY: + total_size += array_size_in_bytes(this, socket); + break; + case SocketType::TRANSFORM_ARRAY: + total_size += array_size_in_bytes(this, socket); + break; + case SocketType::NODE_ARRAY: + total_size += array_size_in_bytes(this, socket); + break; + + case SocketType::UNDEFINED: break; + } + } + return total_size; +} + CCL_NAMESPACE_END diff --git a/intern/cycles/graph/node.h b/intern/cycles/graph/node.h index a738bfe197e..11695a8631d 100644 --- a/intern/cycles/graph/node.h +++ b/intern/cycles/graph/node.h @@ -92,6 +92,9 @@ struct Node /* compute hash of node and its socket values */ void hash(MD5Hash& md5); + /* Get total size of this node. */ + size_t get_total_size_in_bytes() const; + ustring name; const NodeType *type; }; -- cgit v1.2.3 From 84d47e3685c7ccfeaf2dd41ab64d1b642f157add Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Fri, 27 Jul 2018 15:46:13 +0200 Subject: Cycles: Initial implementation of detailed statistics Gathers information about object geometry and textures. Very basic at this moment, but need to start somewhere. Things which needs to be included still: - "Runtime" information, like BVH. While it is not directly controllable by artists, it's still important to know. - Device array sizes. Again, not under artists control, but is added to the overall size. - Memory peak at different synchronization stages. At this point it simply prints info to the stdout after F12 is done, need better control over that too. Reviewers: brecht Differential Revision: https://developer.blender.org/D3566 --- intern/cycles/blender/addon/engine.py | 6 ++ intern/cycles/blender/blender_python.cpp | 9 +++ intern/cycles/blender/blender_session.cpp | 8 ++ intern/cycles/blender/blender_session.h | 2 + intern/cycles/render/CMakeLists.txt | 2 + intern/cycles/render/image.cpp | 12 +++ intern/cycles/render/image.h | 3 + intern/cycles/render/mesh.cpp | 10 +++ intern/cycles/render/mesh.h | 3 + intern/cycles/render/scene.cpp | 6 ++ intern/cycles/render/scene.h | 3 + intern/cycles/render/stats.cpp | 119 ++++++++++++++++++++++++++++++ intern/cycles/render/stats.h | 104 ++++++++++++++++++++++++++ 13 files changed, 287 insertions(+) create mode 100644 intern/cycles/render/stats.cpp create mode 100644 intern/cycles/render/stats.h diff --git a/intern/cycles/blender/addon/engine.py b/intern/cycles/blender/addon/engine.py index 7e06b15afdd..c30d199ede8 100644 --- a/intern/cycles/blender/addon/engine.py +++ b/intern/cycles/blender/addon/engine.py @@ -67,6 +67,9 @@ def _configure_argument_parser(): parser.add_argument("--cycles-resumable-end-chunk", help="End chunk to render", default=None) + parser.add_argument("--cycles-print-stats", + help="Print rendering statistics to stderr", + action='store_true') return parser @@ -95,6 +98,9 @@ def _parse_command_line(): int(args.cycles_resumable_start_chunk), int(args.cycles_resumable_end_chunk), ) + if args.cycles_print_stats: + import _cycles + _cycles.enable_print_stats() def init(): diff --git a/intern/cycles/blender/blender_python.cpp b/intern/cycles/blender/blender_python.cpp index 3eccecb8850..4b01eb5f2d4 100644 --- a/intern/cycles/blender/blender_python.cpp +++ b/intern/cycles/blender/blender_python.cpp @@ -734,6 +734,12 @@ static PyObject *set_resumable_chunk_range_func(PyObject * /*self*/, PyObject *a Py_RETURN_NONE; } +static PyObject *enable_print_stats_func(PyObject * /*self*/, PyObject * /*args*/) +{ + BlenderSession::print_render_stats = true; + Py_RETURN_NONE; +} + static PyObject *get_device_types_func(PyObject * /*self*/, PyObject * /*args*/) { vector& devices = Device::available_devices(); @@ -772,6 +778,9 @@ static PyMethodDef methods[] = { {"debug_flags_update", debug_flags_update_func, METH_VARARGS, ""}, {"debug_flags_reset", debug_flags_reset_func, METH_NOARGS, ""}, + /* Statistics. */ + {"enable_print_stats", enable_print_stats_func, METH_NOARGS, ""}, + /* Resumable render */ {"set_resumable_chunk", set_resumable_chunk_func, METH_VARARGS, ""}, {"set_resumable_chunk_range", set_resumable_chunk_range_func, METH_VARARGS, ""}, diff --git a/intern/cycles/blender/blender_session.cpp b/intern/cycles/blender/blender_session.cpp index 00d23b9095e..e11b8e0c70d 100644 --- a/intern/cycles/blender/blender_session.cpp +++ b/intern/cycles/blender/blender_session.cpp @@ -28,6 +28,7 @@ #include "render/scene.h" #include "render/session.h" #include "render/shader.h" +#include "render/stats.h" #include "util/util_color.h" #include "util/util_foreach.h" @@ -48,6 +49,7 @@ int BlenderSession::num_resumable_chunks = 0; int BlenderSession::current_resumable_chunk = 0; int BlenderSession::start_resumable_chunk = 0; int BlenderSession::end_resumable_chunk = 0; +bool BlenderSession::print_render_stats = false; BlenderSession::BlenderSession(BL::RenderEngine& b_engine, BL::UserPreferences& b_userpref, @@ -492,6 +494,12 @@ void BlenderSession::render() /* free result without merging */ end_render_result(b_engine, b_rr, true, true, false); + if(!b_engine.is_preview() && background && print_render_stats) { + RenderStats stats; + session->scene->collect_statistics(&stats); + printf("Render statistics:\n%s\n", stats.full_report().c_str()); + } + if(session->progress.get_cancel()) break; } diff --git a/intern/cycles/blender/blender_session.h b/intern/cycles/blender/blender_session.h index 3804e07cffc..08f5c873bef 100644 --- a/intern/cycles/blender/blender_session.h +++ b/intern/cycles/blender/blender_session.h @@ -143,6 +143,8 @@ public: static int start_resumable_chunk; static int end_resumable_chunk; + static bool print_render_stats; + protected: void do_write_update_render_result(BL::RenderResult& b_rr, BL::RenderLayer& b_rlay, diff --git a/intern/cycles/render/CMakeLists.txt b/intern/cycles/render/CMakeLists.txt index b7248354abd..7d2220f37f9 100644 --- a/intern/cycles/render/CMakeLists.txt +++ b/intern/cycles/render/CMakeLists.txt @@ -33,6 +33,7 @@ set(SRC session.cpp shader.cpp sobol.cpp + stats.cpp svm.cpp tables.cpp tile.cpp @@ -60,6 +61,7 @@ set(SRC_HEADERS session.h shader.h sobol.h + stats.h svm.h tables.h tile.h diff --git a/intern/cycles/render/image.cpp b/intern/cycles/render/image.cpp index 741dfb0717a..e6ef19cc3be 100644 --- a/intern/cycles/render/image.cpp +++ b/intern/cycles/render/image.cpp @@ -17,6 +17,7 @@ #include "device/device.h" #include "render/image.h" #include "render/scene.h" +#include "render/stats.h" #include "util/util_foreach.h" #include "util/util_logging.h" @@ -1042,4 +1043,15 @@ void ImageManager::device_free(Device *device) } } +void ImageManager::collect_statistics(RenderStats *stats) +{ + for(int type = 0; type < IMAGE_DATA_NUM_TYPES; type++) { + foreach(const Image *image, images[type]) { + stats->image.textures.add_entry( + NamedSizeEntry(path_filename(image->filename), + image->mem->memory_size())); + } + } +} + CCL_NAMESPACE_END diff --git a/intern/cycles/render/image.h b/intern/cycles/render/image.h index 9a2b373d016..d94ebe564e3 100644 --- a/intern/cycles/render/image.h +++ b/intern/cycles/render/image.h @@ -29,6 +29,7 @@ CCL_NAMESPACE_BEGIN class Device; class Progress; +class RenderStats; class Scene; class ImageMetaData { @@ -89,6 +90,8 @@ public: device_memory *image_memory(int flat_slot); + void collect_statistics(RenderStats *stats); + bool need_update; /* NOTE: Here pixels_size is a size of storage, which equals to diff --git a/intern/cycles/render/mesh.cpp b/intern/cycles/render/mesh.cpp index df408b478b2..ade575a52d6 100644 --- a/intern/cycles/render/mesh.cpp +++ b/intern/cycles/render/mesh.cpp @@ -27,6 +27,7 @@ #include "render/nodes.h" #include "render/object.h" #include "render/scene.h" +#include "render/stats.h" #include "kernel/osl/osl_globals.h" @@ -2276,6 +2277,15 @@ void MeshManager::tag_update(Scene *scene) scene->object_manager->need_update = true; } +void MeshManager::collect_statistics(const Scene *scene, RenderStats *stats) +{ + foreach(Mesh *mesh, scene->meshes) { + stats->mesh.geometry.add_entry( + NamedSizeEntry(string(mesh->name.c_str()), + mesh->get_total_size_in_bytes())); + } +} + bool Mesh::need_attribute(Scene *scene, AttributeStandard std) { if(std == ATTR_STD_NONE) diff --git a/intern/cycles/render/mesh.h b/intern/cycles/render/mesh.h index fc7d0b40273..444f03a3664 100644 --- a/intern/cycles/render/mesh.h +++ b/intern/cycles/render/mesh.h @@ -38,6 +38,7 @@ class Device; class DeviceScene; class Mesh; class Progress; +class RenderStats; class Scene; class SceneParams; class AttributeRequest; @@ -351,6 +352,8 @@ public: void create_volume_mesh(Scene *scene, Mesh *mesh, Progress &progress); + void collect_statistics(const Scene *scene, RenderStats *stats); + protected: /* Calculate verts/triangles/curves offsets in global arrays. */ void mesh_calc_offset(Scene *scene); diff --git a/intern/cycles/render/scene.cpp b/intern/cycles/render/scene.cpp index 1d65ef65980..9f93fed139c 100644 --- a/intern/cycles/render/scene.cpp +++ b/intern/cycles/render/scene.cpp @@ -379,4 +379,10 @@ void Scene::device_free() free_memory(false); } +void Scene::collect_statistics(RenderStats *stats) +{ + mesh_manager->collect_statistics(this, stats); + image_manager->collect_statistics(stats); +} + CCL_NAMESPACE_END diff --git a/intern/cycles/render/scene.h b/intern/cycles/render/scene.h index 713eba623b1..dd8069537eb 100644 --- a/intern/cycles/render/scene.h +++ b/intern/cycles/render/scene.h @@ -56,6 +56,7 @@ class ShaderManager; class Progress; class BakeManager; class BakeData; +class RenderStats; /* Scene Device Data */ @@ -255,6 +256,8 @@ public: void reset(); void device_free(); + void collect_statistics(RenderStats *stats); + protected: /* Check if some heavy data worth logging was updated. * Mainly used to suppress extra annoying logging. diff --git a/intern/cycles/render/stats.cpp b/intern/cycles/render/stats.cpp new file mode 100644 index 00000000000..101d33fcf65 --- /dev/null +++ b/intern/cycles/render/stats.cpp @@ -0,0 +1,119 @@ +/* + * Copyright 2011-2018 Blender Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "render/stats.h" +#include "util/util_algorithm.h" +#include "util/util_foreach.h" +#include "util/util_string.h" + +CCL_NAMESPACE_BEGIN + +static int kIndentNumSpaces = 2; + +/* Named size entry. */ + +namespace { + +bool namedSizeEntryComparator(const NamedSizeEntry& a, const NamedSizeEntry& b) +{ + /* We sort in descending order. */ + return a.size > b.size; +} + +} // namespace + +NamedSizeEntry::NamedSizeEntry() + : name(""), + size(0) { +} + +NamedSizeEntry::NamedSizeEntry(const string& name, size_t size) + : name(name), + size(size) { +} + +/* Named size statistics. */ + +NamedSizeStats::NamedSizeStats() + : total_size(0) { +} + +void NamedSizeStats::add_entry(const NamedSizeEntry& entry) { + total_size += entry.size; + entries.push_back(entry); +} + +string NamedSizeStats::full_report(int indent_level) +{ + const string indent(indent_level * kIndentNumSpaces, ' '); + const string double_indent = indent + indent; + string result = ""; + result += string_printf("%sTotal memory: %s (%s)\n", + indent.c_str(), + string_human_readable_size(total_size).c_str(), + string_human_readable_number(total_size).c_str()); + sort(entries.begin(), entries.end(), namedSizeEntryComparator); + foreach(const NamedSizeEntry& entry, entries) { + result += string_printf( + "%s%-32s %s (%s)\n", + double_indent.c_str(), + entry.name.c_str(), + string_human_readable_size(entry.size).c_str(), + string_human_readable_number(entry.size).c_str()); + } + return result; +} + +/* Mesh statistics. */ + +MeshStats::MeshStats() { +} + +string MeshStats::full_report(int indent_level) +{ + const string indent(indent_level * kIndentNumSpaces, ' '); + string result = ""; + result += indent + "Geometry:\n" + geometry.full_report(indent_level + 1); + return result; +} + +/* Image statistics. */ + +ImageStats::ImageStats() { +} + +string ImageStats::full_report(int indent_level) +{ + const string indent(indent_level * kIndentNumSpaces, ' '); + string result = ""; + result += indent + "Textures:\n" + textures.full_report(indent_level + 1); + return result; +} + +/* Overall statistics. */ + +RenderStats::RenderStats() { +} + +string RenderStats::full_report() +{ + string result = ""; + result += "Mesh statistics:\n" + mesh.full_report(1); + result += "Image statistics:\n" + image.full_report(1); + return result; +} + +CCL_NAMESPACE_END diff --git a/intern/cycles/render/stats.h b/intern/cycles/render/stats.h new file mode 100644 index 00000000000..72d5f1dd93d --- /dev/null +++ b/intern/cycles/render/stats.h @@ -0,0 +1,104 @@ +/* + * Copyright 2011-2018 Blender Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __RENDER_STATS_H__ +#define __RENDER_STATS_H__ + +#include "util/util_string.h" +#include "util/util_vector.h" + +CCL_NAMESPACE_BEGIN + +/* Named statistics entry, which corresponds to a size. There is no real + * semantic around the units of size, it just should be the same for all + * entries. + * + * This is a generic entry foi all size-related statistics, which helps + * avoiding duplicating code for things like sorting. + */ +class NamedSizeEntry { +public: + NamedSizeEntry(); + NamedSizeEntry(const string& name, size_t size); + + string name; + size_t size; +}; + +/* Container of named size entries. Used, for example, to store per-mesh memory + * usage statistics. But also keeps track of overall memory usage of the + * container. + */ +class NamedSizeStats { +public: + NamedSizeStats(); + + /* Add entry to the statistics. */ + void add_entry(const NamedSizeEntry& entry); + + /* Generate full human-readable report. */ + string full_report(int indent_level = 0); + + /* Total size of all entries. */ + size_t total_size; + + /* NOTE: Is fine to read directly, but for adding use add_entry(), which + * makes sure all accumulating values are properly updated. + */ + vector entries; +}; + +/* Statistics about mesh in the render database. */ +class MeshStats { +public: + MeshStats(); + + /* Generate full human-readable report. */ + string full_report(int indent_level = 0); + + /* Input geometry statistics, this is what is coming as an input to render + * from. say, Blender. This does not include runtime or engine specific + * memory like BVH. + */ + NamedSizeStats geometry; +}; + +/* Statistics about images held in memory. */ +class ImageStats { +public: + ImageStats(); + + /* Generate full human-readable report. */ + string full_report(int indent_level = 0); + + NamedSizeStats textures; +}; + +/* Render process statistics. */ +class RenderStats { +public: + RenderStats(); + + /* Return full report as string. */ + string full_report(); + + MeshStats mesh; + ImageStats image; +}; + +CCL_NAMESPACE_END + +#endif /* __RENDER_STATS_H__ */ -- cgit v1.2.3