PointCache: improve performance and compression, always compress

Point Caches (used by particle system, cloth, boids etc.) are now
always compressed, uzing zstd coupled with lossless data filtering.

- This is both smaller cache files _and_ faster than the old
  "Heavy" compression mode,
- And smaller data files and same or slightly faster speed than
  using no compression at all,
- There was not much difference between compression levels once
  data filtering got added, so option to pick them was removed.
- So there's no downside to just always using the compression,
  which makes for a simpler UI.
- RNA change: removes PointCache.compression property.

More details and cache size / performance numbers in the PR.

Pull Request: https://projects.blender.org/blender/blender/pulls/144356
This commit is contained in:
Aras Pranckevicius
2025-08-13 16:38:46 +02:00
committed by Aras Pranckevicius
parent fbdc501c50
commit 3d9155eb0a
10 changed files with 221 additions and 176 deletions

View File

@@ -2649,7 +2649,6 @@ url_manual_mapping = (
("bpy.types.object.visible_diffuse*", "render/cycles/object_settings/object_data.html#bpy-types-object-visible-diffuse"),
("bpy.types.objectsolverconstraint*", "animation/constraints/motion_tracking/object_solver.html#bpy-types-objectsolverconstraint"),
("bpy.types.particlesystemmodifier*", "physics/particles/index.html#bpy-types-particlesystemmodifier"),
("bpy.types.pointcache.compression*", "physics/baking.html#bpy-types-pointcache-compression"),
("bpy.types.rendersettings.threads*", "render/cycles/render_settings/performance.html#bpy-types-rendersettings-threads"),
("bpy.types.scenedisplay.render_aa*", "render/workbench/sampling.html#bpy-types-scenedisplay-render-aa"),
("bpy.types.sceneeevee.motion_blur*", "render/eevee/render_settings/motion_blur.html#bpy-types-sceneeevee-motion-blur"),

View File

@@ -188,10 +188,6 @@ def point_cache_ui(self, cache, enabled, cachetype):
subcol.active = cache.use_disk_cache
subcol.prop(cache, "use_library_path", text="Use Library Path")
col = flow.column()
col.active = cache.use_disk_cache
col.prop(cache, "compression", text="Compression")
if cache.id_data.library and not cache.use_disk_cache:
can_bake = False

View File

@@ -1,4 +1,5 @@
/* SPDX-FileCopyrightText: 2001-2002 NaN Holding BV. All rights reserved.
* SPDX-FileCopyrightText: 2025 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
@@ -35,6 +36,7 @@
#include "DNA_scene_types.h"
#include "DNA_space_types.h"
#include "BLI_compression.hh"
#include "BLI_fileops.h"
#include "BLI_listbase.h"
#include "BLI_math_rotation.h"
@@ -83,8 +85,6 @@
lzo_align_t __LZO_MMODEL var[((size) + (sizeof(lzo_align_t) - 1)) / sizeof(lzo_align_t)]
#endif
#define LZO_OUT_LEN(size) ((size) + (size) / 16 + 64 + 3)
#if 0 // #ifdef WITH_LZMA
# include "LzmaLib.h"
#endif
@@ -128,12 +128,14 @@ static int ptcache_extra_datasize[] = {
};
/* forward declarations */
static int ptcache_file_compressed_read(PTCacheFile *pf, uchar *result, uint len);
static int ptcache_file_compressed_read(PTCacheFile *pf,
uchar *result,
uint items_num,
uint item_size);
static void ptcache_file_compressed_write(PTCacheFile *pf,
const void *data,
uint items_num,
uint item_size,
PointCacheCompression compression);
uint item_size);
static int ptcache_file_write(PTCacheFile *pf, const void *data, uint items_num, uint item_size);
static bool ptcache_file_read(PTCacheFile *pf, void *f, uint items_num, uint item_size);
@@ -709,8 +711,7 @@ static int ptcache_dynamicpaint_write(PTCacheFile *pf, void *dp_v)
return 0;
}
ptcache_file_compressed_write(
pf, surface->data->type_data, total_points, in_stride, PTCACHE_COMPRESS_ZSTD_FAST);
ptcache_file_compressed_write(pf, surface->data->type_data, total_points, in_stride);
}
return 1;
}
@@ -751,9 +752,8 @@ static int ptcache_dynamicpaint_read(PTCacheFile *pf, void *dp_v)
return 0;
}
int ret = ptcache_file_compressed_read(pf,
static_cast<uchar *>(surface->data->type_data),
data_len * surface->data->total_points);
int ret = ptcache_file_compressed_read(
pf, static_cast<uchar *>(surface->data->type_data), surface->data->total_points, data_len);
if (ret) {
CLOG_ERROR(&LOG, "Dynamic Paint: Unable to read the compressed cache data");
return 0;
@@ -1508,11 +1508,13 @@ static void ptcache_file_close(PTCacheFile *pf)
}
}
static int ptcache_file_compressed_read(PTCacheFile *pf, uchar *result, uint len)
static int ptcache_file_compressed_read(PTCacheFile *pf,
uchar *result,
uint items_num,
uint item_size)
{
int r = 0;
size_t in_len;
uchar *in;
uchar compressed_val = 0;
ptcache_file_read(pf, &compressed_val, 1, sizeof(uchar));
@@ -1525,26 +1527,36 @@ static int ptcache_file_compressed_read(PTCacheFile *pf, uchar *result, uint len
/* do nothing */
}
else {
in = MEM_calloc_arrayN<uchar>(in_len, "pointcache_compressed_buffer");
uchar *in = MEM_calloc_arrayN<uchar>(in_len, "pointcache_compressed_buffer");
ptcache_file_read(pf, in, in_len, sizeof(uchar));
uchar *decomp_result = result;
if (compressed == PTCACHE_COMPRESS_ZSTD_FILTERED) {
decomp_result = MEM_malloc_arrayN<uchar>(items_num * item_size,
"pointcache_unfilter_buffer");
}
#if 0 // #ifdef WITH_LZO
if (compressed == PTCACHE_COMPRESS_LZO_DEPRECATED) {
size_t out_len = len;
r = lzo1x_decompress_safe(in, (lzo_uint)in_len, result, (lzo_uint *)&out_len, nullptr);
size_t out_len = items_num * item_size;
r = lzo1x_decompress_safe(in, (lzo_uint)in_len, decomp_result, (lzo_uint *)&out_len, nullptr);
}
#endif
#if 0 // #ifdef WITH_LZMA
if (compressed == PTCACHE_COMPRESS_LZMA_DEPRECATED) {
size_t leni = in_len, leno = len;
size_t leni = in_len, leno = items_num * item_size;
uchar lzma_props[16] = {};
uint lzma_props_size = 0;
ptcache_file_read(pf, &lzma_props_size, 1, sizeof(uint));
ptcache_file_read(pf, lzma_props, lzma_props_size, sizeof(uchar));
r = LzmaUncompress(result, &leno, in, &leni, lzma_props, lzma_props_size);
r = LzmaUncompress(decomp_result, &leno, in, &leni, lzma_props, lzma_props_size);
}
#endif
if (ELEM(compressed, PTCACHE_COMPRESS_ZSTD_FAST, PTCACHE_COMPRESS_ZSTD_SLOW)) {
const size_t err = ZSTD_decompress(result, len, in, in_len);
if (ELEM(compressed,
PTCACHE_COMPRESS_ZSTD_FILTERED,
PTCACHE_COMPRESS_ZSTD_FAST_DEPRECATED,
PTCACHE_COMPRESS_ZSTD_SLOW_DEPRECATED))
{
const size_t err = ZSTD_decompress(decomp_result, items_num * item_size, in, in_len);
r = ZSTD_isError(err);
}
else {
@@ -1552,102 +1564,47 @@ static int ptcache_file_compressed_read(PTCacheFile *pf, uchar *result, uint len
r = 1;
}
MEM_freeN(in);
/* Un-filter the decompressed data, if needed. */
if (compressed == PTCACHE_COMPRESS_ZSTD_FILTERED) {
blender::unfilter_transpose_delta(decomp_result, result, items_num, item_size);
MEM_freeN(decomp_result);
}
}
}
else {
ptcache_file_read(pf, result, len, sizeof(uchar));
ptcache_file_read(pf, result, items_num * item_size, sizeof(uchar));
}
return r;
}
static void ptcache_file_compressed_write(PTCacheFile *pf,
const void *data,
uint items_num,
uint item_size,
PointCacheCompression compression)
uint item_size)
{
/* Allocate space for compressed data. */
const PointCacheCompression compression = PTCACHE_COMPRESS_ZSTD_FILTERED;
const uint data_size = items_num * item_size;
size_t out_len = 0;
if (ELEM(compression, PTCACHE_COMPRESS_ZSTD_FAST, PTCACHE_COMPRESS_ZSTD_SLOW)) {
out_len = ZSTD_compressBound(data_size);
if (ZSTD_isError(out_len)) {
compression = PTCACHE_COMPRESS_NO;
}
}
else if (compression != PTCACHE_COMPRESS_NO) {
out_len = LZO_OUT_LEN(data_size);
}
size_t out_len = ZSTD_compressBound(data_size);
blender::Array<uchar> out(out_len);
/* Do actual compression. */
int r = 0;
uchar lzma_props[16] = {};
size_t lzma_props_size = 5;
/* Filter the data: transpose by bytes; delta-encode. */
blender::Array<uchar> filtered(data_size);
blender::filter_transpose_delta((const uint8_t *)data, filtered.data(), items_num, item_size);
#if 0 // #ifdef WITH_LZO
if (compression == PTCACHE_COMPRESS_LZO_DEPRECATED) {
LZO_HEAP_ALLOC(wrkmem, LZO1X_MEM_COMPRESS);
r = lzo1x_1_compress(
(const uchar *)data, (lzo_uint)data_size, out.data(), (lzo_uint *)&out_len, wrkmem);
if (!(r == LZO_E_OK) || (out_len >= data_size)) {
compression = PTCACHE_COMPRESS_NO;
}
}
#endif
#if 0 // #ifdef WITH_LZMA
if (compression == PTCACHE_COMPRESS_LZMA_DEPRECATED) {
r = LzmaCompress(out.data(),
&out_len,
(const uchar *)data,
data_size, /* Assume `sizeof(char) == 1`. */
lzma_props,
&lzma_props_size,
5,
1 << 24,
3,
0,
2,
32,
2);
if (!(r == SZ_OK) || (out_len >= data_size)) {
compression = PTCACHE_COMPRESS_NO;
}
}
#endif
if (ELEM(compression, PTCACHE_COMPRESS_ZSTD_FAST, PTCACHE_COMPRESS_ZSTD_SLOW)) {
/* Zstd level zero is "default" (currently 3). */
const int zstd_level = compression == PTCACHE_COMPRESS_ZSTD_SLOW ? 22 : 0;
r = ZSTD_compress(out.data(), out_len, data, data_size, zstd_level);
if (ZSTD_isError(r)) {
compression = PTCACHE_COMPRESS_NO;
}
else {
out_len = r;
r = 0;
}
}
/* Do compression: always zstd level 3. */
const int zstd_level = 3;
size_t res = ZSTD_compress(out.data(), out_len, filtered.data(), data_size, zstd_level);
out_len = res;
/* Write to file. */
const uchar compression_val = compression;
ptcache_file_write(pf, &compression_val, 1, sizeof(uchar));
if (compression != PTCACHE_COMPRESS_NO) {
uint size = out_len;
ptcache_file_write(pf, &size, 1, sizeof(uint));
ptcache_file_write(pf, out.data(), out_len, sizeof(uchar));
}
else {
ptcache_file_write(pf, data, data_size, sizeof(uchar));
}
if (compression == PTCACHE_COMPRESS_LZMA_DEPRECATED) {
uint size = lzma_props_size;
ptcache_file_write(pf, &lzma_props_size, 1, sizeof(uint));
ptcache_file_write(pf, lzma_props, size, sizeof(uchar));
}
uint size = out_len;
ptcache_file_write(pf, &size, 1, sizeof(uint));
ptcache_file_write(pf, out.data(), out_len, sizeof(uchar));
}
static bool ptcache_file_read(PTCacheFile *pf, void *f, uint items_num, uint item_size)
@@ -1671,20 +1628,6 @@ static bool ptcache_file_data_read(PTCacheFile *pf)
return true;
}
static int ptcache_file_data_write(PTCacheFile *pf)
{
int i;
for (i = 0; i < BPHYS_TOT_DATA; i++) {
if ((pf->data_types & (1 << i)) &&
!ptcache_file_write(pf, pf->cur[i], 1, ptcache_data_size[i]))
{
return 0;
}
}
return 1;
}
static int ptcache_file_header_begin_read(PTCacheFile *pf)
{
uint typeflag = 0;
@@ -1990,9 +1933,9 @@ static PTCacheMem *ptcache_disk_frame_to_mem(PTCacheID *pid, int cfra)
if (pf->flag & PTCACHE_TYPEFLAG_COMPRESS) {
for (i = 0; !error && i < BPHYS_TOT_DATA; i++) {
uint out_len = pm->totpoint * ptcache_data_size[i];
if (pf->data_types & (1 << i)) {
error = ptcache_file_compressed_read(pf, static_cast<uchar *>(pm->data[i]), out_len);
error = ptcache_file_compressed_read(
pf, static_cast<uchar *>(pm->data[i]), pm->totpoint, ptcache_data_size[i]);
}
}
}
@@ -2028,7 +1971,8 @@ static PTCacheMem *ptcache_disk_frame_to_mem(PTCacheID *pid, int cfra)
if (pf->flag & PTCACHE_TYPEFLAG_COMPRESS) {
error = ptcache_file_compressed_read(pf,
static_cast<uchar *>(extra->data),
extra->totdata * ptcache_extra_datasize[extra->type]);
extra->totdata,
ptcache_extra_datasize[extra->type]);
}
else {
ptcache_file_read(pf, extra->data, extra->totdata, ptcache_extra_datasize[extra->type]);
@@ -2077,36 +2021,16 @@ static int ptcache_mem_frame_to_disk(PTCacheID *pid, PTCacheMem *pm)
pf->flag |= PTCACHE_TYPEFLAG_EXTRADATA;
}
const PointCacheCompression compression = PointCacheCompression(pid->cache->compression);
if (compression != PTCACHE_COMPRESS_NO) {
pf->flag |= PTCACHE_TYPEFLAG_COMPRESS;
}
pf->flag |= PTCACHE_TYPEFLAG_COMPRESS;
if (!ptcache_file_header_begin_write(pf) || !pid->write_header(pf)) {
error = 1;
}
if (!error) {
if (compression != PTCACHE_COMPRESS_NO) {
for (i = 0; i < BPHYS_TOT_DATA; i++) {
if (pm->data[i]) {
ptcache_file_compressed_write(
pf, pm->data[i], pm->totpoint, ptcache_data_size[i], compression);
}
}
}
else {
void *cur[BPHYS_TOT_DATA];
BKE_ptcache_mem_pointers_init(pm, cur);
ptcache_file_pointers_init(pf);
for (i = 0; i < pm->totpoint; i++) {
ptcache_data_copy(cur, pf->cur);
if (!ptcache_file_data_write(pf)) {
error = 1;
break;
}
BKE_ptcache_mem_pointers_incr(cur);
for (i = 0; i < BPHYS_TOT_DATA; i++) {
if (pm->data[i]) {
ptcache_file_compressed_write(pf, pm->data[i], pm->totpoint, ptcache_data_size[i]);
}
}
}
@@ -2122,13 +2046,8 @@ static int ptcache_mem_frame_to_disk(PTCacheID *pid, PTCacheMem *pm)
ptcache_file_write(pf, &extra->type, 1, sizeof(uint));
ptcache_file_write(pf, &extra->totdata, 1, sizeof(uint));
if (compression != PTCACHE_COMPRESS_NO) {
ptcache_file_compressed_write(
pf, extra->data, extra->totdata, ptcache_extra_datasize[extra->type], compression);
}
else {
ptcache_file_write(pf, extra->data, extra->totdata, ptcache_extra_datasize[extra->type]);
}
ptcache_file_compressed_write(
pf, extra->data, extra->totdata, ptcache_extra_datasize[extra->type]);
}
}

View File

@@ -0,0 +1,43 @@
/* SPDX-FileCopyrightText: 2025 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
#pragma once
/** \file
* \ingroup bli
*
* Utilities for lossless data compression.
*/
#include <cstddef>
#include <cstdint>
namespace blender {
/**
* Transforms array of data, making it more compressible,
* especially if data is smoothly varying. Typically you do
* this before compression with a general purpose compressor.
*
* Transposes input array so that output data is first byte of
* all items, then 2nd byte of all items, etc. And successive
* items within each "byte stream" are stored as difference
* from previous byte.
*
* See https://aras-p.info/blog/2023/03/01/Float-Compression-7-More-Filtering-Optimization/
* for details.
*/
void filter_transpose_delta(const uint8_t *src, uint8_t *dst, size_t items_num, size_t item_size);
/**
* Reverses the data transform done by #unfilter_transpose_delta.
* Typically you do this after decompression with a general purpose
* compressor.
*/
void unfilter_transpose_delta(const uint8_t *src,
uint8_t *dst,
size_t items_num,
size_t item_size);
} // namespace blender

View File

@@ -53,6 +53,7 @@ set(SRC
intern/bitmap_draw_2d.cc
intern/boxpack_2d.cc
intern/cache_mutex.cc
intern/compression.cc
intern/compute_context.cc
intern/convexhull_2d.cc
intern/cpp_type.cc
@@ -206,6 +207,7 @@ set(SRC
BLI_compiler_attrs.h
BLI_compiler_compat.h
BLI_compiler_typecheck.h
BLI_compression.hh
BLI_compute_context.hh
BLI_concurrent_map.hh
BLI_console.h
@@ -528,6 +530,7 @@ if(WITH_GTESTS)
tests/BLI_bounds_test.cc
tests/BLI_build_config_test.cc
tests/BLI_color_test.cc
tests/BLI_compression_test.cc
tests/BLI_convexhull_2d_test.cc
tests/BLI_cpp_type_test.cc
tests/BLI_csv_parse_test.cc

View File

@@ -0,0 +1,44 @@
/* SPDX-FileCopyrightText: 2025 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup bli
*/
#include "BLI_compression.hh"
namespace blender {
void filter_transpose_delta(const uint8_t *src, uint8_t *dst, size_t items_num, size_t item_size)
{
for (size_t ib = 0; ib < item_size; ib++) {
uint8_t prev = 0;
const uint8_t *src_ptr = src + ib;
size_t it = 0;
for (; it < items_num; it++) {
uint8_t v = *src_ptr;
*dst = v - prev;
prev = v;
src_ptr += item_size;
dst += 1;
}
}
}
void unfilter_transpose_delta(const uint8_t *src, uint8_t *dst, size_t items_num, size_t item_size)
{
for (size_t ib = 0; ib < item_size; ib++) {
uint8_t prev = 0;
uint8_t *dst_ptr = dst + ib;
for (size_t it = 0; it < items_num; it++) {
uint8_t v = *src + prev;
prev = v;
*dst_ptr = v;
src += 1;
dst_ptr += item_size;
}
}
}
} // namespace blender

View File

@@ -0,0 +1,55 @@
/* SPDX-FileCopyrightText: 2025 Blender Authors
*
* SPDX-License-Identifier: Apache-2.0 */
#include "testing/testing.h"
#include "BLI_array.hh"
#include "BLI_compression.hh"
namespace blender {
TEST(compression, filter_transpose_delta)
{
constexpr int num = 5;
constexpr int size = 3;
uint8_t input[num * size] = {0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 5, 4, 3};
uint8_t filtered_exp[num * size] = {0, 2, 6, 26, 227, 1, 2, 10, 42, 205, 1, 4, 16, 68, 170};
uint8_t filtered[num * size] = {};
uint8_t unfiltered[num * size] = {};
filter_transpose_delta(input, filtered, num, size);
EXPECT_EQ_ARRAY(filtered_exp, filtered, num * size);
unfilter_transpose_delta(filtered, unfiltered, num, size);
EXPECT_EQ_ARRAY(input, unfiltered, num * size);
}
static uint32_t pcg_rand(uint32_t &rng_state)
{
uint32_t state = rng_state;
rng_state = rng_state * 747796405u + 2891336453u;
uint32_t word = ((state >> ((state >> 28u) + 4u)) ^ state) * 277803737u;
return (word >> 22u) ^ word;
}
TEST(compression, filter_transpose_delta_stress)
{
uint32_t rng = 1;
constexpr int size = 64 * 1024;
Array<uint8_t> input(size);
Array<uint8_t> filtered(size);
Array<uint8_t> unfiltered(size);
for (uint8_t &val : input) {
val = pcg_rand(rng);
}
const int strides[] = {1, 2, 3, 4, 5, 8, 13, 16, 25, 48, 64, 65, 101, 300, 512, 513, size};
for (int stride : strides) {
const int num = size / stride;
filter_transpose_delta(input.data(), filtered.data(), num, stride);
unfilter_transpose_delta(filtered.data(), unfiltered.data(), num, stride);
EXPECT_EQ_ARRAY(input.data(), unfiltered.data(), num * stride);
}
}
} // namespace blender

View File

@@ -1250,15 +1250,13 @@ static void do_version_remove_lzo_and_lzma_compression(FileData *fd, Object *obj
LISTBASE_FOREACH (PTCacheID *, pid, &pidlist) {
bool found_incompatible_cache = false;
if (pid->cache->compression == PTCACHE_COMPRESS_LZO_DEPRECATED) {
pid->cache->compression = PTCACHE_COMPRESS_ZSTD_FAST;
if (ELEM(pid->cache->compression,
PTCACHE_COMPRESS_LZO_DEPRECATED,
PTCACHE_COMPRESS_LZMA_DEPRECATED))
{
pid->cache->compression = PTCACHE_COMPRESS_ZSTD_FILTERED;
found_incompatible_cache = true;
}
else if (pid->cache->compression == PTCACHE_COMPRESS_LZMA_DEPRECATED) {
pid->cache->compression = PTCACHE_COMPRESS_ZSTD_SLOW;
found_incompatible_cache = true;
}
if (pid->type == PTCACHE_TYPE_DYNAMICPAINT) {
/* Dynamicpaint was hardcoded to use LZO. */
found_incompatible_cache = true;

View File

@@ -95,7 +95,7 @@ typedef struct PointCache {
int totpoint;
/** Modifier stack index. */
int index;
/** #PointCacheCompression. */
/** #PointCacheCompression. Used for versioning only; now cache is always compressed. */
short compression;
char _pad0[2];
@@ -149,12 +149,16 @@ enum {
PTCACHE_FLAGS_COPY = PTCACHE_DISK_CACHE | PTCACHE_EXTERNAL | PTCACHE_IGNORE_LIBPATH,
};
/* Note: the enum values look like bit flags, but they are not really;
* it is just an enum with strange values. */
/**
* Cache files baked before 5.0 could have used LZO or LZMA.
* During 5.0 alpha ZSTD compression had two settings.
* Now only the ZSTD+filtering option is used.
*/
typedef enum PointCacheCompression {
PTCACHE_COMPRESS_NO = 0,
PTCACHE_COMPRESS_LZO_DEPRECATED = 1, /* Removed in 5.0. */
PTCACHE_COMPRESS_LZMA_DEPRECATED = 2, /* Removed in 5.0. */
PTCACHE_COMPRESS_ZSTD_FAST = 4,
PTCACHE_COMPRESS_ZSTD_SLOW = 8,
PTCACHE_COMPRESS_ZSTD_FILTERED = 3,
PTCACHE_COMPRESS_ZSTD_FAST_DEPRECATED = 4, /* Used only during 5.0 alpha. */
PTCACHE_COMPRESS_ZSTD_SLOW_DEPRECATED = 8, /* Used only during 5.0 alpha. */
} PointCacheCompression;

View File

@@ -957,18 +957,6 @@ static void rna_def_pointcache_common(StructRNA *srna)
{
PropertyRNA *prop;
static const EnumPropertyItem point_cache_compress_items[] = {
{PTCACHE_COMPRESS_NO, "NO", 0, "None", "No compression"},
/* TODO: Deprecated. Remove after short testing period in 5.0. */
# if 0 // WITH_LZO, WITH_LZMA
{PTCACHE_COMPRESS_LZO, "LIGHT", 0, "Lite", "Fast but not so effective compression"},
{PTCACHE_COMPRESS_LZMA, "HEAVY", 0, "Heavy", "Effective but slow compression"},
# endif
{PTCACHE_COMPRESS_ZSTD_FAST, "FAST", 0, "Fast", "Fast but not so effective compression"},
{PTCACHE_COMPRESS_ZSTD_SLOW, "SLOW", 0, "Slow", "Effective but slow compression"},
{0, nullptr, 0, nullptr, nullptr},
};
RNA_def_struct_path_func(srna, "rna_PointCache_path");
RNA_define_lib_overridable(true);
@@ -997,10 +985,6 @@ static void rna_def_pointcache_common(StructRNA *srna)
RNA_def_property_ui_text(prop, "Cache Index", "Index number of cache files");
RNA_def_property_update(prop, NC_OBJECT, "rna_Cache_idname_change");
prop = RNA_def_property(srna, "compression", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_items(prop, point_cache_compress_items);
RNA_def_property_ui_text(prop, "Cache Compression", "Compression method to be used");
/* flags */
prop = RNA_def_property(srna, "is_baked", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, nullptr, "flag", PTCACHE_BAKED);