2323#include < MaterialXCore/Material.h>
2424#include < MaterialXCore/Unit.h>
2525
26+ #include < MaterialXTrace/Tracing.h>
27+
2628#include < iostream>
29+ #include < optional>
2730
2831namespace mx = MaterialX;
2932
@@ -652,24 +655,36 @@ void ShaderGeneratorTester::registerLights(mx::DocumentPtr doc, const std::vecto
652655
653656void ShaderGeneratorTester::validate (const mx::GenOptions& generateOptions, const std::string& optionsFilePath)
654657{
655- // Start logging
656- _logFile.open (_logFilePath);
657-
658- // Check for an option file
658+ // Check for an option file first (before opening log) so we can use outputDirectory
659659 TestSuiteOptions options;
660660 if (!options.readOptions (optionsFilePath))
661661 {
662- _logFile << " Cannot read options file: " << optionsFilePath << " . Skipping test." << std::endl;
663- _logFile.close ();
662+ std::cerr << " Cannot read options file: " << optionsFilePath << " . Skipping test." << std::endl;
664663 return ;
665664 }
666665 // Test has been turned off so just do nothing.
667666 if (!runTest (options))
668667 {
669- _logFile << " Target: " << _targetString << " not set to run. Skipping test." << std::endl;
670- _logFile.close ();
668+ std::cerr << " Target: " << _targetString << " not set to run. Skipping test." << std::endl;
671669 return ;
672670 }
671+
672+ #ifdef MATERIALX_BUILD_PERFETTO_TRACING
673+ // Set up Perfetto tracing if enabled
674+ std::optional<mx::Tracing::Dispatcher::ShutdownGuard> tracingGuard;
675+ if (options.enableTracing )
676+ {
677+ mx::FilePath tracePath = options.resolveOutputPath (_shaderGenerator->getTarget () + " _gen_trace.perfetto-trace" );
678+ mx::Tracing::Dispatcher::getInstance ().setSink (
679+ mx::Tracing::createPerfettoSink (tracePath.asString ()));
680+ tracingGuard.emplace ();
681+ }
682+ #endif
683+
684+ // Start logging - use outputDirectory if set
685+ mx::FilePath logPath = options.resolveOutputPath (_logFilePath);
686+ _logFile.open (logPath.asString ());
687+
673688 options.print (_logFile);
674689
675690 // Add files to override the files in the test suite to be examined.
@@ -839,7 +854,11 @@ void ShaderGeneratorTester::validate(const mx::GenOptions& generateOptions, cons
839854 _logFile << " ------------ Run validation with element: " << namePath << " ------------" << std::endl;
840855
841856 mx::StringVec sourceCode;
842- const bool generatedCode = generateCode (context, elementName, element, _logFile, _testStages, sourceCode);
857+ bool generatedCode = false ;
858+ {
859+ MX_TRACE_SCOPE (mx::Tracing::Category::ShaderGen, elementName.c_str ());
860+ generatedCode = generateCode (context, elementName, element, _logFile, _testStages, sourceCode);
861+ }
843862
844863 // Record implementations tested
845864 if (options.checkImplCount )
@@ -879,6 +898,17 @@ void ShaderGeneratorTester::validate(const mx::GenOptions& generateOptions, cons
879898 path = searchPath.isEmpty () ? mx::FilePath () : searchPath[0 ];
880899 }
881900
901+ // Redirect to outputDirectory if set
902+ if (!options.outputDirectory .isEmpty ())
903+ {
904+ mx::FilePath materialDir = path.getBaseName ();
905+ path = options.outputDirectory / materialDir;
906+ if (!path.exists ())
907+ {
908+ path.createDirectory ();
909+ }
910+ }
911+
882912 std::vector<mx::FilePath> sourceCodePaths;
883913 if (sourceCode.size () > 1 )
884914 {
@@ -939,6 +969,12 @@ void ShaderGeneratorTester::validate(const mx::GenOptions& generateOptions, cons
939969 {
940970 _logFile.close ();
941971 }
972+
973+ // Print effective output directory for easy access (clickable in terminals)
974+ if (!options.outputDirectory .isEmpty ())
975+ {
976+ std::cout << std::endl << " Test artifacts written to: " << options.outputDirectory .asString () << std::endl;
977+ }
942978}
943979
944980void TestSuiteOptions::print (std::ostream& output) const
@@ -968,6 +1004,8 @@ void TestSuiteOptions::print(std::ostream& output) const
9681004 output << " \t Extra library paths: " << extraLibraryPaths.asString () << std::endl;
9691005 output << " \t Render test paths: " << renderTestPaths.asString () << std::endl;
9701006 output << " \t Enable Reference Quality: " << enableReferenceQuality << std::endl;
1007+ output << " \t Output Directory: " << (outputDirectory.isEmpty () ? " (default)" : outputDirectory.asString ()) << std::endl;
1008+ output << " \t Enable Tracing: " << enableTracing << std::endl;
9711009}
9721010
9731011bool TestSuiteOptions::readOptions (const std::string& optionFile)
@@ -993,6 +1031,8 @@ bool TestSuiteOptions::readOptions(const std::string& optionFile)
9931031 const std::string EXTRA_LIBRARY_PATHS (" extraLibraryPaths" );
9941032 const std::string RENDER_TEST_PATHS (" renderTestPaths" );
9951033 const std::string ENABLE_REFERENCE_QUALITY (" enableReferenceQuality" );
1034+ const std::string OUTPUT_DIRECTORY_STRING (" outputDirectory" );
1035+ const std::string ENABLE_TRACING_STRING (" enableTracing" );
9961036
9971037 overrideFiles.clear ();
9981038 dumpGeneratedCode = false ;
@@ -1091,6 +1131,23 @@ bool TestSuiteOptions::readOptions(const std::string& optionFile)
10911131 {
10921132 enableReferenceQuality = val->asA <bool >();
10931133 }
1134+ else if (name == OUTPUT_DIRECTORY_STRING)
1135+ {
1136+ std::string dirPath = p->getValueString ();
1137+ if (!dirPath.empty ())
1138+ {
1139+ outputDirectory = mx::FilePath (dirPath);
1140+ // Create the directory if it doesn't exist
1141+ if (!outputDirectory.exists ())
1142+ {
1143+ outputDirectory.createDirectory ();
1144+ }
1145+ }
1146+ }
1147+ else if (name == ENABLE_TRACING_STRING)
1148+ {
1149+ enableTracing = val->asA <bool >();
1150+ }
10941151 }
10951152 }
10961153 }
0 commit comments