Basics of temporary and persistent cache working again

Edge cases not really tested still though
This commit is contained in:
Hans Goudey 2022-12-08 00:06:35 -06:00
parent 24e2d08b49
commit c9958c8e9f
3 changed files with 48 additions and 69 deletions

View File

@ -4,6 +4,7 @@
#include <map>
#include "BLI_bit_vector.hh"
#include "BLI_compute_context.hh"
#include "BLI_map.hh"
@ -30,28 +31,23 @@ struct TimePoint {
/* TODO: Clear cache when editing nodes? Only sometimes, when persistent caching is turned off. */
class SimulationCache {
/* TODO: These will need to be a generic value at some point. */
struct CacheValues {
/* TODO: This will need to be a generic value at some point. */
/* Map from simulation time index (see #SimulationCache::times) to value. */
Vector<GeometrySet> persistent_cache;
BitVector<> persistent_caches_filled;
std::optional<GeometrySet> non_persistent_value;
GeometrySet lookup_index(const int index) const
void ensure_size(const int size)
{
if (!persistent_cache.index_range().contains(index)) {
return persistent_cache[index];
}
return {};
persistent_cache.resize(size);
persistent_caches_filled.resize(size);
}
};
/* Map from cache data identifier (socket name) to values at stored times. */
Map<std::string, CacheValues> caches_;
/* Ordered list of cached simulation frames. */
Vector<TimePoint> persistent_times_;
std::optional<TimePoint> start_time_;
std::optional<TimePoint> last_run_time_;
@ -68,20 +64,13 @@ class SimulationCache {
std::optional<GeometrySet> value_at_or_before_time(StringRef data_name, TimePoint time)
{
const CacheValues *values = caches_.lookup_ptr(data_name);
if (!values) {
return std::nullopt;
if (std::optional<GeometrySet> value = this->value_at_time(data_name, time)) {
return value;
}
if (last_run_time_->time < time.time) {
if (values->non_persistent_value) {
return std::move(values->non_persistent_value);
}
if (std::optional<GeometrySet> value = this->value_before_time(data_name, time)) {
return value;
}
const int index = this->index_at_or_before_time(time);
if (!values->persistent_cache.index_range().contains(index)) {
return std::nullopt;
}
return values->persistent_cache[index];
return std::nullopt;
}
std::optional<GeometrySet> value_before_time(StringRef data_name, TimePoint time)
@ -95,10 +84,22 @@ class SimulationCache {
return std::move(values->non_persistent_value);
}
}
const int index = this->index_before_time(time);
if (!values->persistent_cache.index_range().contains(index)) {
/* TODO: Maybe separate retrieval of persistent and temprary cache values? Though that doesn't
* really provide a benefit right now. */
if (values->persistent_cache.is_empty()) {
return std::nullopt;
}
int index = std::min<int>(values->persistent_cache.index_range().last(),
time.frame - start_time_->frame);
if (index < 0) {
return std::nullopt;
}
while (!values->persistent_caches_filled[index]) {
index--;
if (index < 0) {
return std::nullopt;
}
}
return values->persistent_cache[index];
}
@ -108,11 +109,14 @@ class SimulationCache {
if (!values) {
return std::nullopt;
}
const std::optional<int> index = this->index_at_time(time);
if (!index) {
const int index = time.frame - start_time_->frame;
if (!values->persistent_cache.index_range().contains(index)) {
return std::nullopt;
}
return values->persistent_cache[*index];
if (!values->persistent_caches_filled[index]) {
return std::nullopt;
}
return values->persistent_cache[index];
}
void store_temporary(const StringRef data_name, const TimePoint time, GeometrySet value)
@ -131,62 +135,31 @@ class SimulationCache {
if (!start_time_) {
start_time_.emplace(time);
}
const int index = this->index_before_time(time);
persistent_times_.resize(index);
persistent_times_[index] = time;
CacheValues &values = caches_.lookup_or_add_default_as(data_name);
values.persistent_cache.resize(index);
const int index = time.frame - start_time_->frame;
values.ensure_size(index + 1);
values.persistent_cache[index] = std::move(value);
values.persistent_caches_filled[index].set();
}
void clear()
{
persistent_times_.clear();
caches_.clear();
start_time_.reset();
last_run_time_.reset();
}
bool is_empty() const
{
return persistent_times_.is_empty();
}
private:
int index_at_or_before_time(const TimePoint time) const
{
if (persistent_times_.is_empty()) {
return 0;
}
int insert_index = 0;
for (const int i : persistent_times_.index_range()) {
if (persistent_times_[i].frame <= time.frame) {
break;
for (const CacheValues &values : caches_.values()) {
if (values.non_persistent_value) {
return false;
}
insert_index++;
}
return insert_index;
}
int index_before_time(const TimePoint time) const
{
if (persistent_times_.is_empty()) {
return 0;
}
int insert_index = 0;
for (const int i : persistent_times_.index_range()) {
if (persistent_times_[i].frame < time.frame) {
break;
}
insert_index++;
}
return insert_index;
}
std::optional<int> index_at_time(const TimePoint time) const
{
for (const int i : persistent_times_.index_range()) {
if (persistent_times_[i].frame == time.frame) {
return i;
if (!values.persistent_cache.is_empty()) {
return false;
}
}
return std::nullopt;
return true;
}
};

View File

@ -345,6 +345,7 @@ set(SRC
BKE_colorband.h
BKE_colortools.h
BKE_compute_contexts.hh
BKE_compute_cache.hh
BKE_constraint.h
BKE_context.h
BKE_cpp_types.h

View File

@ -91,6 +91,11 @@ static void node_geo_exec(GeoNodeExecParams params)
GeometrySet geometry_set = params.extract_input<GeometrySet>("Geometry");
geometry_set.ensure_owns_direct_data();
if (storage.use_persistent_cache) {
if (!cache.is_empty()) {
if (time.time < cache.start_time()->time) {
cache.clear();
}
}
/* If using the cache or there is no cached data yet, write the input in a new cache value. */
cache.store_persistent("Geometry", time, geometry_set);
}