Skip to content

Commit 77708d6

Browse files
lgritzssh4net
authored andcommitted
api: IBA::make_texture now honors "maketx:threads" hint (AcademySoftwareFoundation#5014)
Nearly all IBA functions take an optional parameter controlling the threading. But make_texture() did not, so there was no way to control its thread usage (it would always use the default number of threads). Without changing the call signature or ABI, this patch merely makes make_texture honor any "maketx:threads" hint passed in the config ImageSpec that it already takes to convey all sorts of controls over the texture creation process. Then this value is passed to any IBA functions, use of parallel_image, and anything else in the implementation of make_texture that would end up using the thread pool. Fixes AcademySoftwareFoundation#4254 --------- Signed-off-by: Larry Gritz <lg@larrygritz.com> Signed-off-by: Vlad (Kuzmin) Erium <libalias@gmail.com>
1 parent ebd0d39 commit 77708d6

2 files changed

Lines changed: 65 additions & 48 deletions

File tree

src/include/OpenImageIO/imagebufalgo.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2247,6 +2247,7 @@ enum MakeTextureMode {
22472247
/// the coordinates for normal maps. ("")
22482248
/// - `maketx:verbose` (int) : How much detail should go to outstream (0).
22492249
/// - `maketx:runstats` (int) : If nonzero, print run stats to outstream (0).
2250+
/// - `maketx:threads` (int) : Number of threads to use (0 = auto).
22502251
/// - `maketx:resize` (int) : If nonzero, resize to power of 2. (0)
22512252
/// - `maketx:keepaspect` (int): If nonzero, save aspect ratio to metadata. (0)
22522253
/// - `maketx:nomipmap` (int) : If nonzero, only output the top MIP level (0).

src/libOpenImageIO/maketexture.cpp

Lines changed: 64 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -510,12 +510,11 @@ bump_to_bumpslopes(ImageBuf& dst, const ImageBuf& src,
510510
return false;
511511
}
512512
is_height = false;
513-
} else if (Strutil::iequals(
514-
bumpformat,
515-
"auto")) { // guess input bump format by analyzing channel count and component
513+
} else if (Strutil::iequals(bumpformat, "auto")) {
514+
// guess input bump format by analyzing channel count and component
516515
if (src.spec().nchannels > 2
517-
&& !ImageBufAlgo::isMonochrome(src)) // maybe it's a normal map?
518-
is_height = false;
516+
&& !ImageBufAlgo::isMonochrome(src, 0.0f, ROI(), nthreads))
517+
is_height = false; // maybe it's a normal map?
519518
else
520519
is_height = true;
521520
} else {
@@ -705,6 +704,8 @@ write_mipmap(ImageBufAlgo::MakeTextureMode mode, std::shared_ptr<ImageBuf>& img,
705704
ImageSpec outspec = outspec_template;
706705
outspec.set_format(outputdatatype);
707706

707+
int nthreads = configspec.get_int_attribute("maketx:threads");
708+
708709
// Going from float to half is prone to generating Inf values if we had
709710
// any floats that were out of the range that half can represent. Nobody
710711
// wants Inf in textures; better to clamp.
@@ -783,7 +784,8 @@ write_mipmap(ImageBufAlgo::MakeTextureMode mode, std::shared_ptr<ImageBuf>& img,
783784

784785
if (clamp_half) {
785786
std::shared_ptr<ImageBuf> tmp(new ImageBuf);
786-
ImageBufAlgo::clamp(*tmp, *img, -HALF_MAX, HALF_MAX, true);
787+
ImageBufAlgo::clamp(*tmp, *img, -HALF_MAX, HALF_MAX, true, ROI(),
788+
nthreads);
787789
std::swap(tmp, img);
788790
}
789791
if (!img->write(out)) {
@@ -831,7 +833,8 @@ write_mipmap(ImageBufAlgo::MakeTextureMode mode, std::shared_ptr<ImageBuf>& img,
831833
std::shared_ptr<ImageBuf> t(new ImageBuf(smallspec));
832834
ImageBufAlgo::channels(*t, *small, outspec.nchannels,
833835
cspan<int>(), cspan<float>(),
834-
cspan<std::string>(), true);
836+
cspan<std::string>(), true,
837+
nthreads);
835838
std::swap(t, small);
836839
}
837840
smallspec.tile_width = outspec.tile_width;
@@ -863,7 +866,7 @@ write_mipmap(ImageBufAlgo::MakeTextureMode mode, std::shared_ptr<ImageBuf>& img,
863866
// and pixel windows match. Don't worry, the texture
864867
// engine doesn't care what the upper MIP levels have
865868
// for the window sizes, it uses level 0 to determine
866-
// the relatinship between texture 0-1 space (display
869+
// the relationship between texture 0-1 space (display
867870
// window) and the pixels.
868871
smallspec.x = 0;
869872
smallspec.y = 0;
@@ -875,12 +878,11 @@ write_mipmap(ImageBufAlgo::MakeTextureMode mode, std::shared_ptr<ImageBuf>& img,
875878

876879
if (filtername == "box" && !orig_was_overscan
877880
&& sharpen <= 0.0f) {
878-
ImageBufAlgo::parallel_image(get_roi(small->spec()),
879-
std::bind(resize_block,
880-
std::ref(*small),
881-
std::cref(*img), _1,
882-
envlatlmode,
883-
allow_shift));
881+
ImageBufAlgo::parallel_image(
882+
get_roi(small->spec()), paropt(nthreads), [&](ROI roi) {
883+
resize_block(*small, *img, roi, envlatlmode,
884+
allow_shift);
885+
});
884886
} else {
885887
Filter2D* filter = setup_filter(small->spec(), img->spec(),
886888
filtername);
@@ -901,38 +903,44 @@ write_mipmap(ImageBufAlgo::MakeTextureMode mode, std::shared_ptr<ImageBuf>& img,
901903
OIIO::print(outstream, "\n");
902904
}
903905
if (do_highlight_compensation)
904-
ImageBufAlgo::rangecompress(*img, *img);
906+
ImageBufAlgo::rangecompress(*img, *img, false, ROI(),
907+
nthreads);
905908
if (sharpen > 0.0f && sharpen_first) {
906909
std::shared_ptr<ImageBuf> sharp(new ImageBuf);
907910
bool uok = ImageBufAlgo::unsharp_mask(*sharp, *img,
908-
sharpenfilt, 3.0,
909-
sharpen, 0.0f);
911+
sharpenfilt, 3.0f,
912+
sharpen, 0.0f,
913+
ROI(), nthreads);
910914
if (!uok)
911915
errorfmt("{}", sharp->geterror());
912916
std::swap(img, sharp);
913917
}
914918
ImageBufAlgo::resize(*small, *img,
915-
{ make_pv("filterptr", filter) });
919+
{ make_pv("filterptr", filter) },
920+
ROI(), nthreads);
916921
if (sharpen > 0.0f && !sharpen_first) {
917922
std::shared_ptr<ImageBuf> sharp(new ImageBuf);
918923
bool uok = ImageBufAlgo::unsharp_mask(*sharp, *small,
919-
sharpenfilt, 3.0,
920-
sharpen, 0.0f);
924+
sharpenfilt, 3.0f,
925+
sharpen, 0.0f,
926+
ROI(), nthreads);
921927
if (!uok)
922928
errorfmt("{}", sharp->geterror());
923929
std::swap(small, sharp);
924930
}
925931
if (do_highlight_compensation) {
926-
ImageBufAlgo::rangeexpand(*small, *small);
932+
ImageBufAlgo::rangeexpand(*small, *small, false, ROI(),
933+
nthreads);
927934
ImageBufAlgo::clamp(*small, *small, 0.0f,
928935
std::numeric_limits<float>::max(),
929-
true);
936+
true, ROI(), nthreads);
930937
}
931938
Filter2D::destroy(filter);
932939
}
933940
}
934941
if (clamp_half)
935-
ImageBufAlgo::clamp(*small, *small, -HALF_MAX, HALF_MAX, true);
942+
ImageBufAlgo::clamp(*small, *small, -HALF_MAX, HALF_MAX, true,
943+
ROI(), nthreads);
936944

937945
double this_miptime = miptimer();
938946
stat_miptime += this_miptime;
@@ -1093,6 +1101,8 @@ make_texture_impl(ImageBufAlgo::MakeTextureMode mode, const ImageBuf* input,
10931101
if (!configspec.tile_depth)
10941102
configspec.tile_depth = 1;
10951103

1104+
int nthreads = configspec.get_int_attribute("maketx:threads");
1105+
10961106
bool ignore_unassoc = configspec.get_int_attribute("maketx:ignore_unassoc");
10971107
ImageSpec inconfig;
10981108
if (ignore_unassoc)
@@ -1257,8 +1267,7 @@ make_texture_impl(ImageBufAlgo::MakeTextureMode mode, const ImageBuf* input,
12571267
bool ok = true;
12581268
OIIO_DISPATCH_COMMON_TYPES(ok, "lightprobe_to_envlatl",
12591269
lightprobe_to_envlatl, src->spec().format,
1260-
*latlong, *src, true);
1261-
// lightprobe_to_envlatl(*latlong, *src, true);
1270+
*latlong, *src, true, ROI(), nthreads);
12621271
// Carry on with the lat-long environment map from here on out
12631272
mode = ImageBufAlgo::MakeTxEnvLatl;
12641273
src = latlong;
@@ -1269,7 +1278,8 @@ make_texture_impl(ImageBufAlgo::MakeTextureMode mode, const ImageBuf* input,
12691278
if (Strutil::iequals(configspec.get_string_attribute("maketx:bumprange",
12701279
"auto"),
12711280
"auto"))
1272-
src_pixel_stats = ImageBufAlgo::computePixelStats(*src);
1281+
src_pixel_stats = ImageBufAlgo::computePixelStats(*src, ROI(),
1282+
nthreads);
12731283

12741284
ImageSpec newspec = src->spec();
12751285
newspec.tile_width = newspec.tile_height = 0;
@@ -1286,7 +1296,8 @@ make_texture_impl(ImageBufAlgo::MakeTextureMode mode, const ImageBuf* input,
12861296
bool ok;
12871297
OIIO_DISPATCH_COMMON_TYPES(ok, "bump_to_bumpslopes", bump_to_bumpslopes,
12881298
src->spec().format, *bumpslopes, *src,
1289-
configspec, src_pixel_stats, outstream);
1299+
configspec, src_pixel_stats, outstream,
1300+
ROI(), nthreads);
12901301
// bump_to_bumpslopes(*bumpslopes, *src);
12911302
mode = ImageBufAlgo::MakeTxTexture;
12921303
src = bumpslopes;
@@ -1330,7 +1341,8 @@ make_texture_impl(ImageBufAlgo::MakeTextureMode mode, const ImageBuf* input,
13301341
std::vector<imagesize_t> hist;
13311342

13321343
for (int i = 0; i < channels; i++) {
1333-
hist = ImageBufAlgo::histogram(*src, i, bins, 0.0f, 1.0f);
1344+
hist = ImageBufAlgo::histogram(*src, i, bins, 0.0f, 1.0f, false,
1345+
ROI(), nthreads);
13341346

13351347
// Turn the histogram into a non-normalized CDF
13361348
for (uint64_t j = 1; j < bins; j++) {
@@ -1389,7 +1401,7 @@ make_texture_impl(ImageBufAlgo::MakeTextureMode mode, const ImageBuf* input,
13891401
bool compute_stats = (constant_color_detect || opaque_detect
13901402
|| compute_average_color || monochrome_detect);
13911403
if (compute_stats) {
1392-
pixel_stats = ImageBufAlgo::computePixelStats(*src);
1404+
pixel_stats = ImageBufAlgo::computePixelStats(*src, ROI(), nthreads);
13931405
}
13941406
double stat_pixelstatstime = alltime.lap();
13951407
STATUS("pixelstats", stat_pixelstatstime);
@@ -1420,7 +1432,7 @@ make_texture_impl(ImageBufAlgo::MakeTextureMode mode, const ImageBuf* input,
14201432
newspec.full_height = newspec.height;
14211433
newspec.full_depth = newspec.depth;
14221434
src->reset(newspec);
1423-
ImageBufAlgo::fill(*src, constantColor);
1435+
ImageBufAlgo::fill(*src, constantColor, ROI(), nthreads);
14241436
if (verbose) {
14251437
outstream << " Constant color image detected. ";
14261438
outstream << "Creating " << newspec.width << "x"
@@ -1441,7 +1453,7 @@ make_texture_impl(ImageBufAlgo::MakeTextureMode mode, const ImageBuf* input,
14411453
std::shared_ptr<ImageBuf> newsrc(new ImageBuf(src->spec()));
14421454
ImageBufAlgo::channels(*newsrc, *src, src->nchannels() - 1,
14431455
cspan<int>(), cspan<float>(),
1444-
cspan<std::string>(), true);
1456+
cspan<std::string>(), true, nthreads);
14451457
std::swap(src, newsrc); // N.B. the old src will delete
14461458
}
14471459

@@ -1455,14 +1467,14 @@ make_texture_impl(ImageBufAlgo::MakeTextureMode mode, const ImageBuf* input,
14551467
&& src->spec().alpha_channel < 0
14561468
&& pixel_stats.avg[0] == pixel_stats.avg[1]
14571469
&& pixel_stats.avg[0] == pixel_stats.avg[2]
1458-
&& ImageBufAlgo::isMonochrome(*src)) {
1470+
&& ImageBufAlgo::isMonochrome(*src, 0.0f, ROI(), nthreads)) {
14591471
if (verbose)
14601472
OIIO::print(
14611473
outstream,
14621474
" Monochrome image detected. Converting to single channel texture.\n");
14631475
std::shared_ptr<ImageBuf> newsrc(new ImageBuf(src->spec()));
14641476
ImageBufAlgo::channels(*newsrc, *src, 1, cspan<int>(), cspan<float>(),
1465-
cspan<std::string>(), true);
1477+
cspan<std::string>(), true, nthreads);
14661478
newsrc->specmod().default_channel_names();
14671479
std::swap(src, newsrc);
14681480
}
@@ -1475,7 +1487,8 @@ make_texture_impl(ImageBufAlgo::MakeTextureMode mode, const ImageBuf* input,
14751487
<< std::endl;
14761488
std::shared_ptr<ImageBuf> newsrc(new ImageBuf(src->spec()));
14771489
ImageBufAlgo::channels(*newsrc, *src, nchannels, cspan<int>(),
1478-
cspan<float>(), cspan<std::string>(), true);
1490+
cspan<float>(), cspan<std::string>(), true,
1491+
nthreads);
14791492
std::swap(src, newsrc);
14801493
}
14811494

@@ -1663,7 +1676,8 @@ make_texture_impl(ImageBufAlgo::MakeTextureMode mode, const ImageBuf* input,
16631676
&& (srcspec.format.basetype == TypeDesc::FLOAT
16641677
|| srcspec.format.basetype == TypeDesc::HALF
16651678
|| srcspec.format.basetype == TypeDesc::DOUBLE)
1666-
&& !ImageBufAlgo::fixNonFinite(*src, *src, fixmode, &pixelsFixed)) {
1679+
&& !ImageBufAlgo::fixNonFinite(*src, *src, fixmode, &pixelsFixed, ROI(),
1680+
nthreads)) {
16671681
errorfmt("Error fixing nans/infs.");
16681682
return false;
16691683
}
@@ -1677,7 +1691,7 @@ make_texture_impl(ImageBufAlgo::MakeTextureMode mode, const ImageBuf* input,
16771691
|| srcspec.format.basetype == TypeDesc::HALF
16781692
|| srcspec.format.basetype == TypeDesc::DOUBLE)) {
16791693
int found_nonfinite = 0;
1680-
ImageBufAlgo::parallel_image(get_roi(srcspec),
1694+
ImageBufAlgo::parallel_image(get_roi(srcspec), nthreads,
16811695
std::bind(check_nan_block, std::ref(*src),
16821696
_1, std::ref(found_nonfinite)));
16831697
if (found_nonfinite) {
@@ -1736,7 +1750,7 @@ make_texture_impl(ImageBufAlgo::MakeTextureMode mode, const ImageBuf* input,
17361750
outstream << " Unpremulting image..." << std::endl;
17371751

17381752
if (!ImageBufAlgo::colorconvert(*ccSrc, *src, processor.get(),
1739-
unpremult)) {
1753+
unpremult, ROI(), nthreads)) {
17401754
errorfmt("Error applying color conversion to image.");
17411755
return false;
17421756
}
@@ -1838,10 +1852,12 @@ make_texture_impl(ImageBufAlgo::MakeTextureMode mode, const ImageBuf* input,
18381852
toplevel.reset(new ImageBuf(dstspec));
18391853
if ((resize_filter == "box" || resize_filter == "triangle")
18401854
&& !orig_was_overscan) {
1841-
ImageBufAlgo::parallel_image(
1842-
get_roi(dstspec),
1843-
std::bind(resize_block, std::ref(*toplevel), std::cref(*src),
1844-
_1, envlatlmode, allow_shift != 0));
1855+
ImageBufAlgo::parallel_image(get_roi(dstspec), nthreads,
1856+
[&](ROI roi) {
1857+
resize_block(*toplevel, *src, roi,
1858+
envlatlmode,
1859+
allow_shift != 0);
1860+
});
18451861
} else {
18461862
Filter2D* filter = setup_filter(toplevel->spec(), src->spec(),
18471863
resize_filter);
@@ -1850,7 +1866,8 @@ make_texture_impl(ImageBufAlgo::MakeTextureMode mode, const ImageBuf* input,
18501866
return false;
18511867
}
18521868
ImageBufAlgo::resize(*toplevel, *src,
1853-
{ make_pv("filterptr", filter) });
1869+
{ make_pv("filterptr", filter) }, ROI(),
1870+
nthreads);
18541871
Filter2D::destroy(filter);
18551872
}
18561873
}
@@ -1906,12 +1923,11 @@ make_texture_impl(ImageBufAlgo::MakeTextureMode mode, const ImageBuf* input,
19061923
addlHashData << "keepaspect=1 ";
19071924

19081925
const int sha1_blocksize = 256;
1909-
std::string hash_digest
1910-
= configspec.get_int_attribute("maketx:hash", 1)
1911-
? ImageBufAlgo::computePixelHashSHA1(*toplevel,
1912-
addlHashData.str(),
1913-
ROI::All(), sha1_blocksize)
1914-
: "";
1926+
std::string hash_digest = configspec.get_int_attribute("maketx:hash", 1)
1927+
? ImageBufAlgo::computePixelHashSHA1(
1928+
*toplevel, addlHashData.str(), ROI::All(),
1929+
sha1_blocksize, nthreads)
1930+
: "";
19151931
if (hash_digest.length()) {
19161932
if (out->supports("arbitrary_metadata")) {
19171933
dstspec.attribute("oiio:SHA-1", hash_digest);

0 commit comments

Comments
 (0)