Skip to content

Commit f7cd3a1

Browse files
authored
imagecache: remove redundant ImageSpec from ImageCache internals (AcademySoftwareFoundation#4664)
Backend changes for issue AcademySoftwareFoundation#4436. ## Description - add `ImageDims` struct to store only a subset of `ImageSpec` or use it as a view on an existing ImageSpec. - move `ImageDims` and `ImageSpec` ownership to `ImageCacheFile` and use them as a pool - add `ImageSpec* m_spec` in `SubimageInfo` to access the descriptors that are common across all mip level - add `ImageDims* m_dims` in `LevelInfo` to access the despcriptors that differ per mip level - add functions to access to mip level dimensions: ```c++ const Dimensions& SubimageInfo::leveldims(int miplevel) const; ``` - do the plumbing across all `libtexture` to use the new interface ## Tests I performed a batch of testing to compare the memory usage and performance of different strategies using 17 `ptex` files from the PTex library samples (some from the Moana Island dataset, so they are quite heavy). The baseline numbers are approximates but gives a good estimate of the memory usage. Baseline | Total (MB) | Specs (MB) (%) | # specs | Subimages (MB) (%) -- | -- | -- | -- | -- OIIO 3.0 main | 1500 | 1200 (80%) | 4936364 | 300 (20%) Method | Total (MB) | Specs (MB) (%) | # specs | Subimages (MB) (%) -- | -- | -- | -- | -- No reuse | 787,2 | 454,3 (58%) | 4936381 | 332,5 (42%) Reuse dist=1 | 442,2 | 109,3 (25%) | 1193485 | 332,5 (75%) Reuse dist=10 | 368,5 | 35,6 (10%) | 380506 | 332,5 (90%) Reuse dist=inf | 333,2 | 0,292 (<1%) | 3020 | 332,5 (>99%) These numbers shows that the memory is now bounded by the `SubimageInfo` + `LevelInfo` structure sizes, and not from the descriptors `ImageSpec` + `Dimensions`  with the right amount of reuse across subimages and mip levels. --------- Signed-off-by: Basile Fraboni <basile.fraboni@gmail.com>
1 parent 9e28800 commit f7cd3a1

File tree

13 files changed

+1004
-607
lines changed

13 files changed

+1004
-607
lines changed

src/include/OpenImageIO/memory.h

Lines changed: 24 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ template<typename T>
4848
inline size_t
4949
footprint(const T* t)
5050
{
51-
return sizeof(T) + (t ? footprint(*t) : 0);
51+
return sizeof(T*) + (t ? footprint(*t) : 0);
5252
}
5353

5454
/// Specializations for common STL types
@@ -68,16 +68,6 @@ heapsize<std::string>(const std::string& s)
6868
return is_small ? 0 : s.capacity();
6969
}
7070

71-
// heapsize specialization for std::vector
72-
template<typename T>
73-
inline size_t
74-
heapsize(const std::vector<T>& vec)
75-
{
76-
size_t size = 0;
77-
for (const T& elem : vec)
78-
size += footprint(elem);
79-
return size;
80-
}
8171

8272
// heapsize specialization for std::shared_ptr
8373
template<typename T>
@@ -111,6 +101,29 @@ footprint(const std::unique_ptr<T>& ref)
111101
return sizeof(std::unique_ptr<T>) + heapsize(ref);
112102
}
113103

104+
// heapsize specialization for std::vector
105+
template<typename T>
106+
inline size_t
107+
heapsize(const std::vector<T>& vec)
108+
{
109+
size_t size = 0;
110+
// account for used allocated memory
111+
for (const T& elem : vec)
112+
size += footprint(elem);
113+
// account for unused allocated memory
114+
size += (vec.capacity() - vec.size()) * sizeof(T);
115+
return size;
116+
}
117+
118+
// footprint specialization for std::vector
119+
template<typename T>
120+
inline size_t
121+
footprint(const std::vector<T>& vec)
122+
{
123+
return sizeof(std::vector<T>) + heapsize<T>(vec);
124+
}
125+
126+
114127
} // namespace pvt
115128

116129

src/libtexture/environment.cpp

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -202,7 +202,8 @@ convention is dictated by OpenEXR.
202202
OIIO_NAMESPACE_BEGIN
203203
using namespace pvt;
204204
using namespace simd;
205-
205+
using SubimageInfo = ImageCacheFile::SubimageInfo;
206+
using ImageDims = ImageCacheFile::ImageDims;
206207

207208
bool
208209
TextureSystem::environment(ustring filename, TextureOpt& options, V3fParam R,
@@ -352,7 +353,7 @@ TextureSystemImpl::environment(TextureHandle* texture_handle_,
352353
return missing_texture(options, nchannels, result, dresultds,
353354
dresultdt);
354355
}
355-
const ImageSpec& spec(texturefile->spec(options.subimage, 0));
356+
const ImageSpec& spec(texturefile->spec(options.subimage));
356357

357358
// Environment maps dictate particular wrap modes
358359
options.swrap = texturefile->m_sample_border
@@ -455,9 +456,8 @@ TextureSystemImpl::environment(TextureHandle* texture_handle_,
455456
invsamples = 1.0f;
456457
}
457458

458-
ImageCacheFile::SubimageInfo& subinfo(
459-
texturefile->subimageinfo(options.subimage));
460-
int min_mip_level = subinfo.min_mip_level;
459+
const SubimageInfo& si(texturefile->subimageinfo(options.subimage));
460+
int min_mip_level = si.min_mip_level;
461461

462462
// FIXME -- assuming latlong
463463
bool ok = true;
@@ -472,14 +472,14 @@ TextureSystemImpl::environment(TextureHandle* texture_handle_,
472472
int miplevel[2] = { -1, -1 };
473473
float levelblend = 0;
474474

475-
int nmiplevels = (int)subinfo.levels.size();
475+
int nmiplevels = (int)si.levels.size();
476476
for (int m = min_mip_level; m < nmiplevels; ++m) {
477477
// Compute the filter size in raster space at this MIP level.
478478
// Filters are in radians, and the vertical resolution of a
479479
// latlong map is PI radians. So to compute the raster size of
480480
// our filter width...
481-
float filtwidth_ras = subinfo.spec(m).full_height * filtwidth
482-
* M_1_PI;
481+
const ImageDims& dims(si.leveldims(m));
482+
float filtwidth_ras = dims.full_height * filtwidth * M_1_PI;
483483
// Once the filter width is smaller than one texel at this level,
484484
// we've gone too far, so we know that we want to interpolate the
485485
// previous level and the current level. Note that filtwidth_ras
@@ -524,8 +524,7 @@ TextureSystemImpl::environment(TextureHandle* texture_handle_,
524524
int lev = miplevel[level];
525525
if (options.interpmode == TextureOpt::InterpSmartBicubic) {
526526
if (lev == 0
527-
|| (texturefile->spec(options.subimage, lev).full_height
528-
< naturalres / 2)) {
527+
|| (si.leveldims(lev).full_height < naturalres / 2)) {
529528
sampler = &TextureSystemImpl::sample_bicubic;
530529
++stats.cubic_interps;
531530
} else {

0 commit comments

Comments
 (0)