Files
Jorn Visser b1bb1d9815 Build: Make the FFTW threads library required to use FFTW
This is done because the library is necessary to make certain FFTW
functions thread safe, see #136557 as well.

Also pass each library variable separately to
`find_package_handle_standard_args` instead of as a list, as otherwise
it won't correctly detect if `libfftw3f` or `libfftw3f_threads` is
missing. This is because CMake considers a value false if it contains
`-NOTFOUND` at the end, but not if it's in the middle. For example,
CMake considers
`.../libfftw3f.a;.../libfftw3f_threads.a;FFTW3_LIBRARY_D-NOTFOUND` to be
false, but
`.../libfftw3f.a;FFTW3_LIBRARY_THREADS_F-NOTFOUND;.../libfftw3.a` to be
true.

---

I noticed that some other find modules also have the same list issue. I guess it was done this way to make CMake print all the found libraries instead of only the first.

Pull Request: https://projects.blender.org/blender/blender/pulls/136692
2025-03-31 14:42:35 +02:00

99 lines
2.6 KiB
C++

/* SPDX-FileCopyrightText: 2024 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup bli
*/
#if defined(WITH_FFTW3)
# include <fftw3.h>
#endif
#include "BLI_fftw.hh"
#include "BLI_index_range.hh"
#include "BLI_math_vector_types.hh"
#include "BLI_task.hh"
#include "BLI_threads.h"
namespace blender::fftw {
/* Identifies if the given number is a 7-smooth number. */
static bool is_humble_number(int n)
{
if (n <= 1) {
return true;
}
if (n % 2 == 0) {
return is_humble_number(n / 2);
}
if (n % 3 == 0) {
return is_humble_number(n / 3);
}
if (n % 5 == 0) {
return is_humble_number(n / 5);
}
if (n % 7 == 0) {
return is_humble_number(n / 7);
}
return false;
}
/* Finds the even humble number larger than or equal the given number. */
static int find_next_even_humble_number(int n)
{
if (n % 2 == 1) {
n++;
}
while (true) {
if (is_humble_number(n)) {
return n;
}
n += 2;
}
return n;
}
int optimal_size_for_real_transform(int size)
{
/* FFTW is best at handling sizes of the form 2^a * 3^b * 5^c * 7^d * 11^e * 13^f, where e + f is
* either 0 or 1, and the other exponents are arbitrary. And it is beneficial for the size to be
* even for real transforms. To simplify computation, we ignore the 11 and 13 factors and find
* the even humble number that is more then or equal the given size. See Section 4.3.3 Real-data
* DFTs in the FFTW manual for more information. */
return find_next_even_humble_number(size);
}
int2 optimal_size_for_real_transform(int2 size)
{
return int2(optimal_size_for_real_transform(size.x), optimal_size_for_real_transform(size.y));
}
/* See Section 5.2 Usage of Multi-threaded FFTW in the FFTW manual for more information. */
[[maybe_unused]] static void tbb_parallel_loop_for_fftw(void *(*work)(char *),
char *job_data,
size_t element_size,
int number_of_jobs,
void * /*data*/)
{
threading::parallel_for(IndexRange(number_of_jobs), 1, [&](const IndexRange sub_range) {
for (const int64_t i : sub_range) {
work(job_data + element_size * i);
}
});
}
void initialize_float()
{
#if defined(WITH_FFTW3)
fftwf_init_threads();
fftwf_make_planner_thread_safe();
fftwf_plan_with_nthreads(BLI_system_thread_count());
fftwf_threads_set_callback(tbb_parallel_loop_for_fftw, nullptr);
#endif
}
} // namespace blender::fftw