2323#include < boost/format.hpp>
2424
2525#include < OpenImageDenoise/oidn.hpp>
26+ #include < oneapi/tbb.h>
2627
2728#include " slg/film/imagepipeline/plugins/intel_oidn.h"
2829#include " slg/film/framebuffer.h"
2930
3031using namespace std ;
3132using namespace luxrays ;
3233using namespace slg ;
34+ using namespace oneapi ::tbb;
3335
3436// ------------------------------------------------------------------------------
3537// Intel Open Image Denoise
@@ -89,7 +91,7 @@ void IntelOIDN::FilterImage(const string &imageName,
8991 filter.set (" cleanAux" , cleanAux);
9092 filter.set (" maxMemoryMB" , oidnMemLimit);
9193 filter.setImage (" color" , colorBuf, oidn::Format::Float3, width, height);
92- if (albedoBuffer) {
94+ if (albedoBuffer) {
9395 filter.setImage (" albedo" , albedoBuf, oidn::Format::Float3, width, height);
9496
9597 // Normals can only be used if albedo is supplied as well
@@ -110,6 +112,49 @@ void IntelOIDN::FilterImage(const string &imageName,
110112 SLG_LOG (" IntelOIDNPlugin " + imageName + " filtering error: " << errorMessage);
111113}
112114
115+
116+ IntelOIDN::float_buffer IntelOIDN::PrepareBuffer (
117+ const std::string& imageName,
118+ const GenericFrameBuffer<4 , 1 , float >& channel,
119+ const u_int width,
120+ const u_int height,
121+ bool enablePrefiltering
122+ ) const {
123+ IntelOIDN::float_buffer outBuffer (width * height * 3 );
124+ IntelOIDN::float_buffer tmpBuffer (outBuffer.size ());
125+ IntelOIDN::float_buffer dummy1 (outBuffer.size ());
126+ IntelOIDN::float_buffer dummy2 (outBuffer.size ());
127+
128+ // Extract channel
129+ tbb::parallel_for (
130+ tbb::blocked_range<u_int>(0 , width * height),
131+ [&](tbb::blocked_range<u_int>& r) {
132+ for (u_int i = r.begin (); i < r.end (); ++i)
133+ channel.GetWeightedPixel (i, &tmpBuffer[i * 3 ]);
134+ }
135+ );
136+
137+ // Prefilter
138+ if (enablePrefiltering) {
139+ FilterImage (
140+ imageName,
141+ &tmpBuffer[0 ],
142+ &outBuffer[0 ],
143+ &dummy1[0 ],
144+ &dummy2[0 ],
145+ width, height,
146+ false
147+ );
148+ } else {
149+ return tmpBuffer;
150+ }
151+
152+ return outBuffer;
153+
154+ }
155+
156+
157+
113158void IntelOIDN::Apply (Film &film, const u_int index) {
114159 const double totalStartTime = WallClockTime ();
115160
@@ -121,61 +166,72 @@ void IntelOIDN::Apply(Film &film, const u_int index) {
121166 const u_int height = film.GetHeight ();
122167 const u_int pixelCount = width * height;
123168
124- vector<float > outputBuffer (3 * pixelCount);
125- vector<float > albedoBuffer (3 * pixelCount);
126- vector<float > normalBuffer (3 * pixelCount), dummy1 (3 * pixelCount), dummy2 (3 * pixelCount);
127-
169+ float_buffer outputBuffer (3 * pixelCount);
170+ float_buffer albedoBuffer;
171+ float_buffer normalBuffer;
172+
173+ // Prepare functions
174+ auto prepareAlbedo = [&]() {
175+ albedoBuffer = PrepareBuffer (
176+ " Albedo" ,
177+ *film.channel_ALBEDO ,
178+ width,
179+ height,
180+ enablePrefiltering
181+ );
182+ };
183+
184+ auto prepareNormal = [&]() {
185+ normalBuffer = PrepareBuffer (
186+ " Normal" ,
187+ *film.channel_AVG_SHADING_NORMAL ,
188+ width,
189+ height,
190+ enablePrefiltering
191+ );
192+ };
193+
194+ SLG_LOG (" IntelOIDNPlugin preparing inputs" );
128195 if (film.HasChannel (Film::ALBEDO)) {
129- albedoBuffer.resize (3 * pixelCount);
130- for (u_int i = 0 ; i < pixelCount; ++i)
131- film.channel_ALBEDO ->GetWeightedPixel (i, &albedoBuffer[i * 3 ]);
132-
133- // GenericFrameBuffer<3, 0, float>::SaveHDR("debug-albedo0.exr", albedoBuffer, width, height);
134-
135- if (enablePrefiltering) {
136- vector<float > albedoBufferTmp (3 * pixelCount);
137- FilterImage (" Albedo" , &albedoBuffer[0 ], &albedoBufferTmp[0 ],
138- &dummy1[0 ], &dummy2[0 ], width, height, false );
139- for (u_int i = 0 ; i < albedoBuffer.size (); ++i)
140- albedoBuffer[i] = albedoBufferTmp[i];
141-
142- // GenericFrameBuffer<3, 0, float>::SaveHDR("debug-albedo1.exr", albedoBuffer, width, height);
143- }
144-
145- // Normals can only be used if albedo is supplied as well
146196 if (film.HasChannel (Film::AVG_SHADING_NORMAL)) {
147- normalBuffer.resize (3 * pixelCount);
148- for (u_int i = 0 ; i < pixelCount; ++i)
149- film.channel_AVG_SHADING_NORMAL ->GetWeightedPixel (i, &normalBuffer[i * 3 ]);
150-
151- // GenericFrameBuffer<3, 0, float>::SaveHDR("debug-normal.exr", normalBuffer, width, height);
152-
153- if (enablePrefiltering) {
154- vector<float > normalBufferTmp (3 * pixelCount);
155- FilterImage (" Normal" , &normalBuffer[0 ], &normalBufferTmp[0 ],
156- &dummy1[0 ], &dummy2[0 ], width, height, false );
157- for (u_int i = 0 ; i < normalBuffer.size (); ++i)
158- normalBuffer[i] = normalBufferTmp[i];
159-
160- // GenericFrameBuffer<3, 0, float>::SaveHDR("debug-normal1.exr", normalBuffer, width, height);
161- }
162- } else
163- SLG_LOG (" [IntelOIDNPlugin] Warning: AVG_SHADING_NORMAL AOV not found" );
164- } else
197+ // Prepare both (and parallelize)
198+ tbb::parallel_invoke (prepareAlbedo, prepareNormal);
199+ } else {
200+ // Prepare only albedo
201+ SLG_LOG (" [IntelOIDNPlugin] Warning: AVG_SHADING_NORMAL AOV not found" );
202+ prepareAlbedo ();
203+ normalBuffer = float_buffer (3 * pixelCount);
204+ }
205+ } else {
165206 SLG_LOG (" [IntelOIDNPlugin] Warning: ALBEDO AOV not found" );
207+ albedoBuffer = float_buffer (3 * pixelCount);
208+ normalBuffer = float_buffer (3 * pixelCount);
209+ }
166210
211+
212+ SLG_LOG (" IntelOIDNPlugin filtering image" );
167213 FilterImage (" Image Pipeline" , (float *)pixels, &outputBuffer[0 ],
168214 (albedoBuffer.size () > 0 ) ? &albedoBuffer[0 ] : nullptr ,
169215 (normalBuffer.size () > 0 ) ? &normalBuffer[0 ] : nullptr ,
170216 width, height, enablePrefiltering);
171217
172218 SLG_LOG (" IntelOIDNPlugin copying output buffer" );
173- for (u_int i = 0 ; i < pixelCount; ++i) {
174- const u_int i3 = i * 3 ;
175- pixels[i].c [0 ] = Lerp (sharpness, outputBuffer[i3], pixels[i].c [0 ]);
176- pixels[i].c [1 ] = Lerp (sharpness, outputBuffer[i3 + 1 ], pixels[i].c [1 ]);
177- pixels[i].c [2 ] = Lerp (sharpness, outputBuffer[i3 + 2 ], pixels[i].c [2 ]);
178- }
219+ tbb::affinity_partitioner aff_p;
220+ tbb::parallel_for (
221+ tbb::blocked_range2d<size_t , size_t >(0 , pixelCount, 0 , 3 ),
222+ [&](const blocked_range2d<size_t , size_t >& r) {
223+ for (size_t i = r.rows ().begin (); i < r.rows ().end (); ++i) {
224+ for (size_t j = r.cols ().begin (); j < r.cols ().end (); ++j) {
225+ pixels[i].c [j] = std::lerp (
226+ outputBuffer[i * 3 + j],
227+ pixels[i].c [j],
228+ sharpness
229+ );
230+ }
231+ }
232+ },
233+ aff_p
234+ );
179235
180236 SLG_LOG (" IntelOIDNPlugin single execution took a total of " << (boost::format (" %.3f" ) % (WallClockTime () - totalStartTime)) << " secs" );
181237}
0 commit comments