diff --git a/CMakeLists.txt b/CMakeLists.txt index de6aa7442f..0d6a64d6b1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -45,6 +45,7 @@ option(MATERIALX_BUILD_GEN_MSL "Build the MSL shader generator back-end." ON) option(MATERIALX_BUILD_RENDER "Build the MaterialX Render modules." ON) option(MATERIALX_BUILD_OIIO "Build OpenImageIO support for MaterialXRender." OFF) option(MATERIALX_BUILD_TESTS "Build unit tests." ON) +option(MATERIALX_BUILD_BENCHMARK_TESTS "Build benchmark tests." OFF) option(MATERIALX_BUILD_SHARED_LIBS "Build MaterialX libraries as shared rather than static." OFF) option(MATERIALX_PYTHON_LTO "Enable link-time optimizations for MaterialX Python." ON) @@ -131,6 +132,7 @@ mark_as_advanced(MATERIALX_BUILD_GEN_MSL) mark_as_advanced(MATERIALX_BUILD_RENDER) mark_as_advanced(MATERIALX_BUILD_OIIO) mark_as_advanced(MATERIALX_BUILD_TESTS) +mark_as_advanced(MATERIALX_BUILD_BENCHMARK_TESTS) mark_as_advanced(MATERIALX_BUILD_SHARED_LIBS) mark_as_advanced(MATERIALX_NAMESPACE_SUFFIX) mark_as_advanced(MATERIALX_LIBNAME_SUFFIX) @@ -177,6 +179,9 @@ endif() if(MATERIALX_TEST_RENDER) add_definitions(-DMATERIALX_TEST_RENDER) endif() +if (MATERIALX_BUILD_BENCHMARK_TESTS) + add_definitions(-DMATERIALX_BUILD_BENCHMARK_TESTS) +endif() if (MATERIALX_BUILD_GEN_MDL) add_definitions(-DMATERIALX_MDLC_EXECUTABLE=\"${MATERIALX_MDLC_EXECUTABLE}\") diff --git a/source/MaterialXTest/CMakeLists.txt b/source/MaterialXTest/CMakeLists.txt index e66db4bd2e..862a176b50 100644 --- a/source/MaterialXTest/CMakeLists.txt +++ b/source/MaterialXTest/CMakeLists.txt @@ -121,6 +121,10 @@ set_target_properties( VERSION "${MATERIALX_LIBRARY_VERSION}" SOVERSION "${MATERIALX_MAJOR_VERSION}") +if(MATERIALX_BUILD_BENCHMARK_TESTS) + target_compile_definitions(MaterialXTest PRIVATE -DCATCH_CONFIG_ENABLE_BENCHMARKING) +endif() + target_link_libraries( MaterialXTest ${CMAKE_DL_LIBS}) diff --git a/source/MaterialXTest/External/Catch/catch.hpp b/source/MaterialXTest/External/Catch/catch.hpp index d2a12427b2..9b309bddc6 100644 --- a/source/MaterialXTest/External/Catch/catch.hpp +++ b/source/MaterialXTest/External/Catch/catch.hpp @@ -1,6 +1,6 @@ /* - * Catch v2.13.9 - * Generated: 2022-04-12 22:37:23.260201 + * Catch v2.13.10 + * Generated: 2022-10-16 11:01:23.452308 * ---------------------------------------------------------- * This file has been merged from multiple headers. Please don't edit it directly * Copyright (c) 2022 Two Blue Cubes Ltd. All rights reserved. @@ -15,7 +15,7 @@ #define CATCH_VERSION_MAJOR 2 #define CATCH_VERSION_MINOR 13 -#define CATCH_VERSION_PATCH 9 +#define CATCH_VERSION_PATCH 10 #ifdef __clang__ # pragma clang system_header @@ -7395,8 +7395,6 @@ namespace Catch { template struct ObjectStorage { - using TStorage = typename std::aligned_storage::value>::type; - ObjectStorage() : data() {} ObjectStorage(const ObjectStorage& other) @@ -7439,7 +7437,7 @@ namespace Catch { return *static_cast(static_cast(&data)); } - TStorage data; + struct { alignas(T) unsigned char data[sizeof(T)]; } data; }; } @@ -7949,7 +7947,7 @@ namespace Catch { #if defined(__i386__) || defined(__x86_64__) #define CATCH_TRAP() __asm__("int $3\n" : : ) /* NOLINT */ #elif defined(__aarch64__) - #define CATCH_TRAP() __asm__(".inst 0xd4200000") + #define CATCH_TRAP() __asm__(".inst 0xd43e0000") #endif #elif defined(CATCH_PLATFORM_IPHONE) @@ -13558,7 +13556,7 @@ namespace Catch { // Handle list request if( Option listed = list( m_config ) ) - return static_cast( *listed ); + return (std::min) (MaxExitCode, static_cast(*listed)); TestGroup tests { m_config }; auto const totals = tests.execute(); @@ -15391,7 +15389,7 @@ namespace Catch { } Version const& libraryVersion() { - static Version version( 2, 13, 9, "", 0 ); + static Version version( 2, 13, 10, "", 0 ); return version; } @@ -17526,12 +17524,20 @@ namespace Catch { #ifndef __OBJC__ +#ifndef CATCH_INTERNAL_CDECL +#ifdef _MSC_VER +#define CATCH_INTERNAL_CDECL __cdecl +#else +#define CATCH_INTERNAL_CDECL +#endif +#endif + #if defined(CATCH_CONFIG_WCHAR) && defined(CATCH_PLATFORM_WINDOWS) && defined(_UNICODE) && !defined(DO_NOT_USE_WMAIN) // Standard C/C++ Win32 Unicode wmain entry point -extern "C" int wmain (int argc, wchar_t * argv[], wchar_t * []) { +extern "C" int CATCH_INTERNAL_CDECL wmain (int argc, wchar_t * argv[], wchar_t * []) { #else // Standard C/C++ main entry point -int main (int argc, char * argv[]) { +int CATCH_INTERNAL_CDECL main (int argc, char * argv[]) { #endif return Catch::Session().run( argc, argv ); diff --git a/source/MaterialXTest/MaterialXGenGlsl/GenGlsl.cpp b/source/MaterialXTest/MaterialXGenGlsl/GenGlsl.cpp index 339d3853cb..2cc4d7ccf4 100644 --- a/source/MaterialXTest/MaterialXGenGlsl/GenGlsl.cpp +++ b/source/MaterialXTest/MaterialXGenGlsl/GenGlsl.cpp @@ -119,6 +119,17 @@ TEST_CASE("GenShader: Bind Light Shaders", "[genglsl]") REQUIRE_NOTHROW(mx::HwShaderGenerator::bindLightShader(*spotLightShader, 66, context)); } +#ifdef MATERIALX_BUILD_BENCHMARK_TESTS +TEST_CASE("GenShader: Performance Test", "[genglsl]") +{ + mx::GenContext context(mx::GlslShaderGenerator::create()); + BENCHMARK("Load documents, validate and generate shader") + { + return GenShaderUtil::shaderGenPerformanceTest(context); + }; +} +#endif + enum class GlslType { Glsl400, diff --git a/source/MaterialXTest/MaterialXGenShader/GenShaderUtil.cpp b/source/MaterialXTest/MaterialXGenShader/GenShaderUtil.cpp index 261aacdefe..2ca8afa86c 100644 --- a/source/MaterialXTest/MaterialXGenShader/GenShaderUtil.cpp +++ b/source/MaterialXTest/MaterialXGenShader/GenShaderUtil.cpp @@ -314,6 +314,85 @@ void testUniqueNames(mx::GenContext& context, const std::string& stage) REQUIRE(sgNode1->getOutput()->getVariable() == "unique_names_out"); } +// Test ShaderGen performance +void shaderGenPerformanceTest(mx::GenContext& context) +{ + mx::DocumentPtr nodeLibrary = mx::createDocument(); + mx::FilePath currentPath = mx::FilePath::getCurrentPath(); + const mx::FileSearchPath libSearchPath(currentPath); + + // Load the standard libraries. + loadLibraries({ "libraries" }, libSearchPath, nodeLibrary); + context.registerSourceCodeSearchPath(libSearchPath); + + // Enable Color Management + mx::ColorManagementSystemPtr colorManagementSystem = + mx::DefaultColorManagementSystem::create(context.getShaderGenerator().getTarget()); + + REQUIRE(colorManagementSystem); + if (colorManagementSystem) + { + context.getShaderGenerator().setColorManagementSystem(colorManagementSystem); + colorManagementSystem->loadLibrary(nodeLibrary); + } + + // Enable Unit System + mx::UnitSystemPtr unitSystem = mx::UnitSystem::create(context.getShaderGenerator().getTarget()); + REQUIRE(unitSystem); + if (unitSystem) + { + context.getShaderGenerator().setUnitSystem(unitSystem); + unitSystem->loadLibrary(nodeLibrary); + // Setup Unit converters + unitSystem->setUnitConverterRegistry(mx::UnitConverterRegistry::create()); + mx::UnitTypeDefPtr distanceTypeDef = nodeLibrary->getUnitTypeDef("distance"); + unitSystem->getUnitConverterRegistry()->addUnitConverter(distanceTypeDef, mx::LinearUnitConverter::create(distanceTypeDef)); + mx::UnitTypeDefPtr angleTypeDef = nodeLibrary->getUnitTypeDef("angle"); + unitSystem->getUnitConverterRegistry()->addUnitConverter(angleTypeDef, mx::LinearUnitConverter::create(angleTypeDef)); + context.getOptions().targetDistanceUnit = "meter"; + } + + // Read mtlx documents + mx::FilePathVec testRootPaths; + testRootPaths.push_back("resources/Materials/Examples/StandardSurface"); + + std::vector loadedDocuments; + mx::StringVec documentsPaths; + mx::StringVec errorLog; + + for (const auto& testRoot : testRootPaths) + { + mx::loadDocuments(testRoot, libSearchPath, {}, {}, loadedDocuments, documentsPaths, + nullptr, &errorLog); + } + + REQUIRE(loadedDocuments.size() > 0); + REQUIRE(loadedDocuments.size() == documentsPaths.size()); + + // Shuffle the order of documents and perform document library import validatation and shadergen + std::random_device random_dev; + std::mt19937 generator(random_dev()); + std::shuffle(loadedDocuments.begin(), loadedDocuments.end(), generator); + for (const auto& doc : loadedDocuments) + { + doc->importLibrary(nodeLibrary); + std::vector elements = mx::findRenderableElements(doc); + + REQUIRE(elements.size() > 0); + + std::string message; + bool docValid = doc->validate(&message); + + REQUIRE(docValid == true); + + mx::StringVec sourceCode; + mx::ShaderPtr shader = nullptr; + shader = context.getShaderGenerator().generate(elements[0]->getName(), elements[0], context); + + REQUIRE(shader != nullptr); + REQUIRE(shader->getSourceCode(mx::Stage::PIXEL).length() > 0); + } +} void ShaderGeneratorTester::checkImplementationUsage(const mx::StringSet& usedImpls, const mx::GenContext& context, diff --git a/source/MaterialXTest/MaterialXGenShader/GenShaderUtil.h b/source/MaterialXTest/MaterialXGenShader/GenShaderUtil.h index ea34170d71..9c471466aa 100644 --- a/source/MaterialXTest/MaterialXGenShader/GenShaderUtil.h +++ b/source/MaterialXTest/MaterialXGenShader/GenShaderUtil.h @@ -52,6 +52,9 @@ void checkImplementations(mx::GenContext& context, // Utility test to check unique name generation on a shader generator void testUniqueNames(mx::GenContext& context, const std::string& stage); +// Utility to perfrom simple performance test to load, validate and generate shaders +void shaderGenPerformanceTest(mx::GenContext& context); + // // Render validation options. Reflects the _options.mtlx // file in the test suite area.