Skip to content

Commit 97bf90d

Browse files
committed
api: IBA::make_texture now honors "maketx:threads" hint
Nearly all IBA functions take an optional nthreads parameter. 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. Then this value is passed to the IBA functions, use of parallel_image, and anything else in the implementation of make_texture that would end up using the thread pool. Signed-off-by: Larry Gritz <lg@larrygritz.com>
1 parent a0db580 commit 97bf90d

2 files changed

Lines changed: 62 additions & 46 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: 61 additions & 46 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,23 +903,27 @@ 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);
@@ -926,13 +932,14 @@ write_mipmap(ImageBufAlgo::MakeTextureMode mode, std::shared_ptr<ImageBuf>& img,
926932
ImageBufAlgo::rangeexpand(*small, *small);
927933
ImageBufAlgo::clamp(*small, *small, 0.0f,
928934
std::numeric_limits<float>::max(),
929-
true);
935+
true, ROI(), nthreads);
930936
}
931937
Filter2D::destroy(filter);
932938
}
933939
}
934940
if (clamp_half)
935-
ImageBufAlgo::clamp(*small, *small, -HALF_MAX, HALF_MAX, true);
941+
ImageBufAlgo::clamp(*small, *small, -HALF_MAX, HALF_MAX, true,
942+
ROI(), nthreads);
936943

937944
double this_miptime = miptimer();
938945
stat_miptime += this_miptime;
@@ -1093,6 +1100,8 @@ make_texture_impl(ImageBufAlgo::MakeTextureMode mode, const ImageBuf* input,
10931100
if (!configspec.tile_depth)
10941101
configspec.tile_depth = 1;
10951102

1103+
int nthreads = configspec.get_int_attribute("maketx:threads");
1104+
10961105
bool ignore_unassoc = configspec.get_int_attribute("maketx:ignore_unassoc");
10971106
ImageSpec inconfig;
10981107
if (ignore_unassoc)
@@ -1257,8 +1266,7 @@ make_texture_impl(ImageBufAlgo::MakeTextureMode mode, const ImageBuf* input,
12571266
bool ok = true;
12581267
OIIO_DISPATCH_COMMON_TYPES(ok, "lightprobe_to_envlatl",
12591268
lightprobe_to_envlatl, src->spec().format,
1260-
*latlong, *src, true);
1261-
// lightprobe_to_envlatl(*latlong, *src, true);
1269+
*latlong, *src, true, ROI(), nthreads);
12621270
// Carry on with the lat-long environment map from here on out
12631271
mode = ImageBufAlgo::MakeTxEnvLatl;
12641272
src = latlong;
@@ -1269,7 +1277,8 @@ make_texture_impl(ImageBufAlgo::MakeTextureMode mode, const ImageBuf* input,
12691277
if (Strutil::iequals(configspec.get_string_attribute("maketx:bumprange",
12701278
"auto"),
12711279
"auto"))
1272-
src_pixel_stats = ImageBufAlgo::computePixelStats(*src);
1280+
src_pixel_stats = ImageBufAlgo::computePixelStats(*src, ROI(),
1281+
nthreads);
12731282

12741283
ImageSpec newspec = src->spec();
12751284
newspec.tile_width = newspec.tile_height = 0;
@@ -1286,7 +1295,8 @@ make_texture_impl(ImageBufAlgo::MakeTextureMode mode, const ImageBuf* input,
12861295
bool ok;
12871296
OIIO_DISPATCH_COMMON_TYPES(ok, "bump_to_bumpslopes", bump_to_bumpslopes,
12881297
src->spec().format, *bumpslopes, *src,
1289-
configspec, src_pixel_stats, outstream);
1298+
configspec, src_pixel_stats, outstream,
1299+
ROI(), nthreads);
12901300
// bump_to_bumpslopes(*bumpslopes, *src);
12911301
mode = ImageBufAlgo::MakeTxTexture;
12921302
src = bumpslopes;
@@ -1330,7 +1340,8 @@ make_texture_impl(ImageBufAlgo::MakeTextureMode mode, const ImageBuf* input,
13301340
std::vector<imagesize_t> hist;
13311341

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

13351346
// Turn the histogram into a non-normalized CDF
13361347
for (uint64_t j = 1; j < bins; j++) {
@@ -1389,7 +1400,7 @@ make_texture_impl(ImageBufAlgo::MakeTextureMode mode, const ImageBuf* input,
13891400
bool compute_stats = (constant_color_detect || opaque_detect
13901401
|| compute_average_color || monochrome_detect);
13911402
if (compute_stats) {
1392-
pixel_stats = ImageBufAlgo::computePixelStats(*src);
1403+
pixel_stats = ImageBufAlgo::computePixelStats(*src, ROI(), nthreads);
13931404
}
13941405
double stat_pixelstatstime = alltime.lap();
13951406
STATUS("pixelstats", stat_pixelstatstime);
@@ -1420,7 +1431,7 @@ make_texture_impl(ImageBufAlgo::MakeTextureMode mode, const ImageBuf* input,
14201431
newspec.full_height = newspec.height;
14211432
newspec.full_depth = newspec.depth;
14221433
src->reset(newspec);
1423-
ImageBufAlgo::fill(*src, constantColor);
1434+
ImageBufAlgo::fill(*src, constantColor, ROI(), nthreads);
14241435
if (verbose) {
14251436
outstream << " Constant color image detected. ";
14261437
outstream << "Creating " << newspec.width << "x"
@@ -1455,14 +1466,14 @@ make_texture_impl(ImageBufAlgo::MakeTextureMode mode, const ImageBuf* input,
14551466
&& src->spec().alpha_channel < 0
14561467
&& pixel_stats.avg[0] == pixel_stats.avg[1]
14571468
&& pixel_stats.avg[0] == pixel_stats.avg[2]
1458-
&& ImageBufAlgo::isMonochrome(*src)) {
1469+
&& ImageBufAlgo::isMonochrome(*src, 0.0f, ROI(), nthreads)) {
14591470
if (verbose)
14601471
OIIO::print(
14611472
outstream,
14621473
" Monochrome image detected. Converting to single channel texture.\n");
14631474
std::shared_ptr<ImageBuf> newsrc(new ImageBuf(src->spec()));
14641475
ImageBufAlgo::channels(*newsrc, *src, 1, cspan<int>(), cspan<float>(),
1465-
cspan<std::string>(), true);
1476+
cspan<std::string>(), true, nthreads);
14661477
newsrc->specmod().default_channel_names();
14671478
std::swap(src, newsrc);
14681479
}
@@ -1475,7 +1486,8 @@ make_texture_impl(ImageBufAlgo::MakeTextureMode mode, const ImageBuf* input,
14751486
<< std::endl;
14761487
std::shared_ptr<ImageBuf> newsrc(new ImageBuf(src->spec()));
14771488
ImageBufAlgo::channels(*newsrc, *src, nchannels, cspan<int>(),
1478-
cspan<float>(), cspan<std::string>(), true);
1489+
cspan<float>(), cspan<std::string>(), true,
1490+
nthreads);
14791491
std::swap(src, newsrc);
14801492
}
14811493

@@ -1663,7 +1675,8 @@ make_texture_impl(ImageBufAlgo::MakeTextureMode mode, const ImageBuf* input,
16631675
&& (srcspec.format.basetype == TypeDesc::FLOAT
16641676
|| srcspec.format.basetype == TypeDesc::HALF
16651677
|| srcspec.format.basetype == TypeDesc::DOUBLE)
1666-
&& !ImageBufAlgo::fixNonFinite(*src, *src, fixmode, &pixelsFixed)) {
1678+
&& !ImageBufAlgo::fixNonFinite(*src, *src, fixmode, &pixelsFixed, ROI(),
1679+
nthreads)) {
16671680
errorfmt("Error fixing nans/infs.");
16681681
return false;
16691682
}
@@ -1677,7 +1690,7 @@ make_texture_impl(ImageBufAlgo::MakeTextureMode mode, const ImageBuf* input,
16771690
|| srcspec.format.basetype == TypeDesc::HALF
16781691
|| srcspec.format.basetype == TypeDesc::DOUBLE)) {
16791692
int found_nonfinite = 0;
1680-
ImageBufAlgo::parallel_image(get_roi(srcspec),
1693+
ImageBufAlgo::parallel_image(get_roi(srcspec), nthreads,
16811694
std::bind(check_nan_block, std::ref(*src),
16821695
_1, std::ref(found_nonfinite)));
16831696
if (found_nonfinite) {
@@ -1736,7 +1749,7 @@ make_texture_impl(ImageBufAlgo::MakeTextureMode mode, const ImageBuf* input,
17361749
outstream << " Unpremulting image..." << std::endl;
17371750

17381751
if (!ImageBufAlgo::colorconvert(*ccSrc, *src, processor.get(),
1739-
unpremult)) {
1752+
unpremult, ROI(), nthreads)) {
17401753
errorfmt("Error applying color conversion to image.");
17411754
return false;
17421755
}
@@ -1838,10 +1851,12 @@ make_texture_impl(ImageBufAlgo::MakeTextureMode mode, const ImageBuf* input,
18381851
toplevel.reset(new ImageBuf(dstspec));
18391852
if ((resize_filter == "box" || resize_filter == "triangle")
18401853
&& !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));
1854+
ImageBufAlgo::parallel_image(get_roi(dstspec), paropt(nthreads),
1855+
[&](ROI roi) {
1856+
resize_block(*toplevel, *src, roi,
1857+
envlatlmode,
1858+
allow_shift != 0);
1859+
});
18451860
} else {
18461861
Filter2D* filter = setup_filter(toplevel->spec(), src->spec(),
18471862
resize_filter);
@@ -1850,7 +1865,8 @@ make_texture_impl(ImageBufAlgo::MakeTextureMode mode, const ImageBuf* input,
18501865
return false;
18511866
}
18521867
ImageBufAlgo::resize(*toplevel, *src,
1853-
{ make_pv("filterptr", filter) });
1868+
{ make_pv("filterptr", filter) }, ROI(),
1869+
nthreads);
18541870
Filter2D::destroy(filter);
18551871
}
18561872
}
@@ -1906,12 +1922,11 @@ make_texture_impl(ImageBufAlgo::MakeTextureMode mode, const ImageBuf* input,
19061922
addlHashData << "keepaspect=1 ";
19071923

19081924
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-
: "";
1925+
std::string hash_digest = configspec.get_int_attribute("maketx:hash", 1)
1926+
? ImageBufAlgo::computePixelHashSHA1(
1927+
*toplevel, addlHashData.str(),
1928+
ROI::All(), sha1_blocksize, nthreads)
1929+
: "";
19151930
if (hash_digest.length()) {
19161931
if (out->supports("arbitrary_metadata")) {
19171932
dstspec.attribute("oiio:SHA-1", hash_digest);

0 commit comments

Comments
 (0)