Files
OpenColorIO/tests/cpu/UnitTestMain.cpp
caa20dd196 Adsk contrib - Add support for neon intrinsic integration (#1828)
* Merging the previous ARM Neon branch

Signed-off-by: Cédrik Fuoco <cedrik.fuoco@autodesk.com>

* Testing each SIMD variants using a small code snippet and first pass on unifying the way related cmake variables

Signed-off-by: Cédrik Fuoco <cedrik.fuoco@autodesk.com>

* Removing the usage of USE_SSE in favor of the new OCIO_USE_SSE2 as they serve the same purpose

Signed-off-by: Cédrik Fuoco <cedrik.fuoco@autodesk.com>

* Using try_compile instead of check_cxx_source_compiles as it was given false positive.  Stubbing cpuinfo for Apple ARM plateform. Handling Apple M1 correctly and adding support for SSE2NEON.

Signed-off-by: Cédrik Fuoco <cedrik.fuoco@autodesk.com>

* Comments clean up and refactor some comments and documentations

Signed-off-by: Cédrik Fuoco <cedrik.fuoco@autodesk.com>

* Added something in the documentation for Rosetta and small change in cmake

Signed-off-by: Cédrik Fuoco <cedrik.fuoco@autodesk.com>

* Fixing the build under Rosetta and fixing issue in the MacOS CI.

Signed-off-by: Cédrik Fuoco <cedrik.fuoco@autodesk.com>

* Using try_compile for CheckSupportSSEUsingSSE2NEON to standardize the code and fixed CheckSupport compiler flags.

Signed-off-by: Cédrik Fuoco <cedrik.fuoco@autodesk.com>

* use emmintrin.h for only sse2 features

Signed-off-by: Mark Reid <mindmark@gmail.com>
Signed-off-by: Cédrik Fuoco <cedrik.fuoco@autodesk.com>

* Allow F16C to be completely turned off

Signed-off-by: Mark Reid <mindmark@gmail.com>
Signed-off-by: Cédrik Fuoco <cedrik.fuoco@autodesk.com>

* Seperate SIMD test code from code that adds unit tests.

This isolates the compulation units and
avoids executing illegal hardware instructions

Signed-off-by: Mark Reid <mindmark@gmail.com>
Signed-off-by: Cédrik Fuoco <cedrik.fuoco@autodesk.com>

* remove uneeded checks

Signed-off-by: Cédrik Fuoco <cedrik.fuoco@autodesk.com>

* use software implementations of f16c intrinsics for SSE2

Signed-off-by: Cédrik Fuoco <cedrik.fuoco@autodesk.com>

* Added preprocessor checks for ARM as it is needed for universal build on APPLE platform

Signed-off-by: Cédrik Fuoco <cedrik.fuoco@autodesk.com>

* Adding missing checks for "not arm64"

Signed-off-by: Cédrik Fuoco <cedrik.fuoco@autodesk.com>

* Ease the future maintainability a the new OCIO_USE_xyz be moving the logic into CPUInfoConfig.h.in as well as fixing issue on ARM when building with OCIO_USE_SSE2NEON=OFF.

Signed-off-by: Cédrik Fuoco <cedrik.fuoco@autodesk.com>

* Fixing some spacing, documentations and making some cmake conditions clearer.

Signed-off-by: Cédrik Fuoco <cedrik.fuoco@autodesk.com>

* Adding a build in ci_workflow for macos USE_OCIO_SSE2NEON=OFF

Signed-off-by: Cédrik Fuoco <cedrik.fuoco@autodesk.com>

* typo

Signed-off-by: Cédrik Fuoco <cedrik.fuoco@autodesk.com>

* Changing back all the macOS (except one) builds to x86_64 only as it takes double the time to do the universal build.
OCIO no longuer build a universal binary by default

Signed-off-by: Cédrik Fuoco <cedrik.fuoco@autodesk.com>

* Update the CMakeLists.txt logic to accomodate all scenario and fixing documentations.

Signed-off-by: Cédrik Fuoco <cedrik.fuoco@autodesk.com>

* Update documentation and remove ocio_use_sse2neon from the CI matrix

Signed-off-by: Cédrik Fuoco <cedrik.fuoco@autodesk.com>

---------

Signed-off-by: Cédrik Fuoco <cedrik.fuoco@autodesk.com>
Signed-off-by: Mark Reid <mindmark@gmail.com>
Signed-off-by: Cédrik Fuoco <105517825+cedrik-fuoco-adsk@users.noreply.github.com>
Co-authored-by: Mark Reid <mindmark@gmail.com>
Co-authored-by: Doug Walker <doug.walker@autodesk.com>
2023-08-31 21:10:29 -04:00

270 lines
7.6 KiB
C++

// SPDX-License-Identifier: BSD-3-Clause
// Copyright Contributors to the OpenColorIO Project.
#if defined(_WIN32) && !defined(NDEBUG)
#include <crtdbg.h>
#include <ctype.h>
#endif
#include <cstring>
#include "testutils/UnitTest.h"
#include "apputils/argparse.h"
#include "utils/StringUtils.h"
#include "UnitTestOptimFlags.h"
#include "CPUInfo.h"
namespace OCIO = OCIO_NAMESPACE;
#if !defined(NDEBUG) && defined(_WIN32)
OCIO_ADD_TEST(UnitTest, windows_debug)
{
// The debug VC++ CRT libraries do pop an 'assert' dialog box
// on some errors hanging unit test executions. To avoid the hang
// (for Debug mode only) the code disables the dialog box.
// The new behavior is now to crash or continue (i.e. later crash)
// depending of the operation:
// 1. isspace() works like:
// --> returns false when it's not a 'space' character,
// but hiding that it's not an ASCII character.
// 2. iterator error crashes the program (like in Release mode).
// --> std::vector<int> v; v[10]; // Crash
// Use an invalid ASCII character (in any locals).
OCIO_CHECK_ASSERT(!::isspace(INT_MAX));
}
#endif
#if OCIO_ARCH_X86 || OCIO_USE_SSE2NEON
#define ENABLE_SIMD_USAGE
#endif
int main(int argc, const char ** argv)
{
std::cerr << "\n OpenColorIO_Core_Unit_Tests \n\n";
// Make sure OptimizationFlags env variable is turned off during tests and
// restored at the end.
OCIOOptimizationFlagsEnvGuard flagsGuard("");
#if !defined(NDEBUG) && defined(_WIN32)
// Disable the 'assert' dialog box in debug mode.
_CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_DEBUG);
#endif
bool printHelp = false;
bool stopOnFirstError = false;
// Note that empty strings mean to run all the unit tests.
std::string filter, utestGroupAllowed, utestNameAllowed;
#if defined(ENABLE_SIMD_USAGE)
bool no_accel = false;
bool sse2 = false;
bool avx = false;
bool avx2 = false;
bool f16c = false;
#endif
ArgParse ap;
ap.options("\nCommand line arguments:\n",
"--help", &printHelp, "Print help message",
"--stop_on_error", &stopOnFirstError, "Stop on the first error",
#if defined(ENABLE_SIMD_USAGE)
"--no_accel", &no_accel, "Disable ALL Accelerated features",
"--sse2", &sse2, "Enable SSE2 Accelerated features",
"--avx", &avx, "Enable AVX Accelerated features",
"--avx2", &avx2, "Enable AVX2 Accelerated features",
"--f16c", &f16c, "Enable F16C Accelerated features",
#endif
"--run_only %s", &filter, "Run only some unit tests\n"
"\tex: --run_only \"FileRules/clone\"\n"
"\tex: --run_only FileRules i.e. \"FileRules/*\"\n"
"\tex: --run_only /clone i.e. \"*/clone\"\n",
nullptr);
if (ap.parse(argc, argv) < 0)
{
std::cerr << ap.geterror() << std::endl;
ap.usage();
return 1;
}
if (printHelp)
{
ap.usage();
return 1;
}
#if defined(ENABLE_SIMD_USAGE)
OCIO::CPUInfo &cpu = OCIO::CPUInfo::instance();
if (no_accel || sse2 || avx || avx2 || f16c)
{
unsigned flags = 0;
if (sse2)
{
if (!cpu.hasSSE2())
{
std::cerr << "-sse2 disabled or not supported by processor\n";
GetUnitTests().clear();
}
flags |= X86_CPU_FLAG_SSE2;
}
if (avx)
{
if (!cpu.hasAVX())
{
std::cerr << "-avx disabled or not supported by processor\n";
GetUnitTests().clear();
}
flags |= X86_CPU_FLAG_AVX;
}
if (avx2)
{
if (!cpu.hasAVX2())
{
std::cerr << "-avx2 not supported by processor\n";
GetUnitTests().clear();
}
flags |= X86_CPU_FLAG_AVX2;
}
if (f16c)
{
if (!cpu.hasF16C())
{
std::cerr << "-f16c disabled or not supported by processor\n";
GetUnitTests().clear();
}
flags |= X86_CPU_FLAG_F16C;
}
cpu.flags = flags;
}
std::cerr << cpu.name << " ";
if (cpu.hasSSE2())
std::cerr << "+sse2";
if (cpu.hasAVX())
std::cerr << "+avx";
if (cpu.hasAVX2())
std::cerr << "+avx2";
if (cpu.hasF16C())
std::cerr << "+f16c";
std::cerr << "\n\n";
#endif
if (!filter.empty())
{
const std::vector<std::string> results = StringUtils::Split(filter, '/');
if (results.size() >= 1)
{
utestGroupAllowed = StringUtils::Lower(StringUtils::Trim(results[0]));
if (results.size() >= 2)
{
utestNameAllowed = StringUtils::Lower(StringUtils::Trim(results[1]));
if (results.size() >= 3)
{
std::cerr << "Invalid value for the argument '--run_only'." << std::endl;
ap.usage();
return 1;
}
}
}
}
int unit_test_failed = 0;
int unit_test_skipped = 0;
const size_t numTests = GetUnitTests().size();
for(size_t index = 0; index < numTests; ++index)
{
const std::string utestGroup = GetUnitTests()[index]->group;
const std::string utestName = GetUnitTests()[index]->name;
bool utestAllowed = true;
if (!utestGroupAllowed.empty() && StringUtils::Lower(utestGroup)!=utestGroupAllowed)
{
utestAllowed = false;
}
if (!utestNameAllowed.empty() && StringUtils::Lower(utestName)!=utestNameAllowed)
{
utestAllowed = false;
}
if (!utestAllowed)
{
continue;
}
const int _tmp = unit_test_failures;
bool skipped = false;
try
{
GetUnitTests()[index]->function();
}
catch(SkipException &)
{
skipped = true;
++unit_test_skipped;
}
catch(std::exception & ex)
{
std::cerr << "\nFAILED: " << ex.what() << "." << std::endl;
++unit_test_failures;
}
catch(...)
{
std::cerr << "\nFAILED: Unexpected error." << std::endl;
++unit_test_failures;
}
const bool passing = (_tmp == unit_test_failures);
if (!passing)
{
++unit_test_failed;
}
std::string name(utestGroup);
name += " / " + utestName;
constexpr size_t maxCharToDisplay = 59;
if (name.size() > maxCharToDisplay)
{
name.resize(maxCharToDisplay);
}
std::cerr << "[" << std::right << std::setw(4)
<< (index+1) << "/" << numTests << "] ["
<< std::left << std::setw(maxCharToDisplay+1)
<< name << "] - "
<< (passing ? skipped ? "SKIPPED" : "PASSED" : "FAILED")
<< std::endl;
if (stopOnFirstError && !passing)
{
break;
}
}
std::cerr << "\n\n" << unit_test_failed << " tests failed with "
<< unit_test_failures << " errors "
<< unit_test_skipped << " skips.\n\n";
GetUnitTests().clear();
return unit_test_failures;
}