Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKévin Dietrich <kevin.dietrich@mailoo.org>2021-08-20 15:29:05 +0300
committerKévin Dietrich <kevin.dietrich@mailoo.org>2021-08-20 15:34:43 +0300
commit9bfc47c9334bc4fbecbe7871fff9af4cc46c8832 (patch)
tree40b56b036e4974111c7c9f0cf2ffe338a45053d8 /intern/cycles/render
parentaccf3045be40433045c197cfcdbcbc32a7724403 (diff)
Alembic Procedural: basic cache control settings
This adds a setting to enable data caching, and another one to set the maximum cache size in megabytes. When caching is enabled we load the data for the entire animation in memory, as we already do, however, if the data exceeds the memory limit, render is aborted. When caching is disabled, we simply load the data for the current frame in memory. Ref D10197 Reviewed By: brecht Differential Revision: https://developer.blender.org/D11163
Diffstat (limited to 'intern/cycles/render')
-rw-r--r--intern/cycles/render/alembic.cpp70
-rw-r--r--intern/cycles/render/alembic.h30
-rw-r--r--intern/cycles/render/alembic_read.cpp16
3 files changed, 113 insertions, 3 deletions
diff --git a/intern/cycles/render/alembic.cpp b/intern/cycles/render/alembic.cpp
index 81f47256739..69bc0712674 100644
--- a/intern/cycles/render/alembic.cpp
+++ b/intern/cycles/render/alembic.cpp
@@ -25,6 +25,7 @@
#include "render/shader.h"
#include "util/util_foreach.h"
+#include "util/util_logging.h"
#include "util/util_progress.h"
#include "util/util_transform.h"
#include "util/util_vector.h"
@@ -211,6 +212,35 @@ void CachedData::set_time_sampling(TimeSampling time_sampling)
}
}
+size_t CachedData::memory_used() const
+{
+ size_t mem_used = 0;
+
+ mem_used += curve_first_key.memory_used();
+ mem_used += curve_keys.memory_used();
+ mem_used += curve_radius.memory_used();
+ mem_used += curve_shader.memory_used();
+ mem_used += num_ngons.memory_used();
+ mem_used += shader.memory_used();
+ mem_used += subd_creases_edge.memory_used();
+ mem_used += subd_creases_weight.memory_used();
+ mem_used += subd_face_corners.memory_used();
+ mem_used += subd_num_corners.memory_used();
+ mem_used += subd_ptex_offset.memory_used();
+ mem_used += subd_smooth.memory_used();
+ mem_used += subd_start_corner.memory_used();
+ mem_used += transforms.memory_used();
+ mem_used += triangles.memory_used();
+ mem_used += uv_loops.memory_used();
+ mem_used += vertices.memory_used();
+
+ for (const CachedAttribute &attr : attributes) {
+ mem_used += attr.data.memory_used();
+ }
+
+ return mem_used;
+}
+
static M44d convert_yup_zup(const M44d &mtx, float scale_mult)
{
V3d scale, shear, rotation, translation;
@@ -706,6 +736,9 @@ NODE_DEFINE(AlembicProcedural)
SOCKET_NODE_ARRAY(objects, "Objects", AlembicObject::get_node_type());
+ SOCKET_BOOLEAN(use_prefetch, "Use Prefetch", true);
+ SOCKET_INT(prefetch_cache_size, "Prefetch Cache Size", 4096);
+
return type;
}
@@ -823,6 +856,30 @@ void AlembicProcedural::generate(Scene *scene, Progress &progress)
}
}
+ if (use_prefetch_is_modified()) {
+ if (!use_prefetch) {
+ for (Node *node : objects) {
+ AlembicObject *object = static_cast<AlembicObject *>(node);
+ object->clear_cache();
+ }
+ }
+ }
+
+ if (prefetch_cache_size_is_modified()) {
+ /* Check whether the current memory usage fits in the new requested size,
+ * abort the render if it is any higher. */
+ size_t memory_used = 0ul;
+ for (Node *node : objects) {
+ AlembicObject *object = static_cast<AlembicObject *>(node);
+ memory_used += object->get_cached_data().memory_used();
+ }
+
+ if (memory_used > get_prefetch_cache_size_in_bytes()) {
+ progress.set_error("Error: Alembic Procedural memory limit reached");
+ return;
+ }
+ }
+
build_caches(progress);
foreach (Node *node, objects) {
@@ -1300,6 +1357,8 @@ void AlembicProcedural::walk_hierarchy(
void AlembicProcedural::build_caches(Progress &progress)
{
+ size_t memory_used = 0;
+
for (Node *node : objects) {
AlembicObject *object = static_cast<AlembicObject *>(node);
@@ -1353,7 +1412,18 @@ void AlembicProcedural::build_caches(Progress &progress)
if (scale_is_modified() || object->get_cached_data().transforms.size() == 0) {
object->setup_transform_cache(object->get_cached_data(), scale);
}
+
+ memory_used += object->get_cached_data().memory_used();
+
+ if (use_prefetch) {
+ if (memory_used > get_prefetch_cache_size_in_bytes()) {
+ progress.set_error("Error: Alembic Procedural memory limit reached");
+ return;
+ }
+ }
}
+
+ VLOG(1) << "AlembicProcedural memory usage : " << string_human_readable_size(memory_used);
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/render/alembic.h b/intern/cycles/render/alembic.h
index 9c58af720f6..8e166a5ab04 100644
--- a/intern/cycles/render/alembic.h
+++ b/intern/cycles/render/alembic.h
@@ -272,6 +272,21 @@ template<typename T> class DataStore {
node->set(*socket, value);
}
+ size_t memory_used() const
+ {
+ if constexpr (is_array<T>::value) {
+ size_t mem_used = 0;
+
+ for (const T &array : data) {
+ mem_used += array.size() * sizeof(array[0]);
+ }
+
+ return mem_used;
+ }
+
+ return data.size() * sizeof(T);
+ }
+
private:
const TimeIndexPair &get_index_for_time(double time) const
{
@@ -332,6 +347,8 @@ struct CachedData {
void invalidate_last_loaded_time(bool attributes_only = false);
void set_time_sampling(Alembic::AbcCoreAbstract::TimeSampling time_sampling);
+
+ size_t memory_used() const;
};
/* Representation of an Alembic object for the AlembicProcedural.
@@ -482,6 +499,13 @@ class AlembicProcedural : public Procedural {
* software. */
NODE_SOCKET_API(float, scale)
+ /* Cache controls */
+ NODE_SOCKET_API(bool, use_prefetch)
+
+ /* Memory limit for the cache, if the data does not fit within this limit, rendering is aborted.
+ */
+ NODE_SOCKET_API(int, prefetch_cache_size)
+
AlembicProcedural();
~AlembicProcedural();
@@ -531,6 +555,12 @@ class AlembicProcedural : public Procedural {
void read_subd(AlembicObject *abc_object, Alembic::AbcGeom::Abc::chrono_t frame_time);
void build_caches(Progress &progress);
+
+ size_t get_prefetch_cache_size_in_bytes() const
+ {
+ /* prefetch_cache_size is in megabytes, so convert to bytes. */
+ return static_cast<size_t>(prefetch_cache_size) * 1024 * 1024;
+ }
};
CCL_NAMESPACE_END
diff --git a/intern/cycles/render/alembic_read.cpp b/intern/cycles/render/alembic_read.cpp
index c53ec668938..b105af63b44 100644
--- a/intern/cycles/render/alembic_read.cpp
+++ b/intern/cycles/render/alembic_read.cpp
@@ -44,9 +44,19 @@ static set<chrono_t> get_relevant_sample_times(AlembicProcedural *proc,
return result;
}
- // load the data for the entire animation
- const double start_frame = static_cast<double>(proc->get_start_frame());
- const double end_frame = static_cast<double>(proc->get_end_frame());
+ double start_frame;
+ double end_frame;
+
+ if (proc->get_use_prefetch()) {
+ // load the data for the entire animation
+ start_frame = static_cast<double>(proc->get_start_frame());
+ end_frame = static_cast<double>(proc->get_end_frame());
+ }
+ else {
+ // load the data for the current frame
+ start_frame = static_cast<double>(proc->get_frame());
+ end_frame = start_frame;
+ }
const double frame_rate = static_cast<double>(proc->get_frame_rate());
const double start_time = start_frame / frame_rate;