diff --git a/libs/filabridge/include/filament/MaterialChunkType.h b/libs/filabridge/include/filament/MaterialChunkType.h index f7fd8f8383..73eef6a599 100644 --- a/libs/filabridge/include/filament/MaterialChunkType.h +++ b/libs/filabridge/include/filament/MaterialChunkType.h @@ -58,6 +58,7 @@ enum UTILS_PUBLIC ChunkType : uint64_t { MaterialName = charTo64bitNum("MAT_NAME"), MaterialVersion = charTo64bitNum("MAT_VERS"), + MaterialCompilationParameters = charTo64bitNum("MAT_CPRM"), MaterialCacheId = charTo64bitNum("MAT_UUID"), MaterialFeatureLevel = charTo64bitNum("MAT_FEAT"), MaterialShading = charTo64bitNum("MAT_SHAD"), diff --git a/libs/filamat/include/filamat/MaterialBuilder.h b/libs/filamat/include/filamat/MaterialBuilder.h index c33ad580e0..6279643dd9 100644 --- a/libs/filamat/include/filamat/MaterialBuilder.h +++ b/libs/filamat/include/filamat/MaterialBuilder.h @@ -295,6 +295,9 @@ public: //! Set the file name of this material file. Used in error reporting. MaterialBuilder& fileName(const char* name) noexcept; + //! Set the commandline parameters of matc. Used for debugging purpose. + MaterialBuilder& compilationParameters(const char* params) noexcept; + //! Set the shading model. MaterialBuilder& shading(Shading shading) noexcept; @@ -876,6 +879,7 @@ private: utils::CString mMaterialName; utils::CString mFileName; + utils::CString mCompilationParameters; class ShaderCode { public: diff --git a/libs/filamat/src/MaterialBuilder.cpp b/libs/filamat/src/MaterialBuilder.cpp index 2e1736350d..1a3545364a 100644 --- a/libs/filamat/src/MaterialBuilder.cpp +++ b/libs/filamat/src/MaterialBuilder.cpp @@ -232,6 +232,11 @@ MaterialBuilder& MaterialBuilder::fileName(const char* name) noexcept { return *this; } +MaterialBuilder& MaterialBuilder::compilationParameters(const char* params) noexcept { + mCompilationParameters = CString(params); + return *this; +} + MaterialBuilder& MaterialBuilder::material(const char* code, size_t const line) noexcept { mMaterialFragmentCode.setUnresolved(CString(code)); mMaterialFragmentCode.setLineOffset(line); @@ -1594,6 +1599,8 @@ void MaterialBuilder::writeCommonChunks(ChunkContainer& container, MaterialInfo& container.emplace(MaterialVersion, MATERIAL_VERSION); container.emplace(MaterialFeatureLevel, (uint8_t)info.featureLevel); container.emplace(MaterialName, mMaterialName.c_str_safe()); + container.emplace(MaterialCompilationParameters, + mCompilationParameters.c_str_safe()); container.emplace(MaterialShaderModels, mShaderModels.getValue()); container.emplace(ChunkType::MaterialDomain, static_cast(mMaterialDomain)); diff --git a/libs/filament-matp/include/filament-matp/Config.h b/libs/filament-matp/include/filament-matp/Config.h index 28d6e4cd2f..9adb589066 100644 --- a/libs/filament-matp/include/filament-matp/Config.h +++ b/libs/filament-matp/include/filament-matp/Config.h @@ -75,6 +75,8 @@ public: virtual std::string toString() const noexcept = 0; + virtual std::string toPIISafeString() const noexcept = 0; + bool isDebug() const noexcept { return mDebug; } diff --git a/libs/matdbg/src/TextWriter.cpp b/libs/matdbg/src/TextWriter.cpp index 8c39827c55..a181e810b3 100644 --- a/libs/matdbg/src/TextWriter.cpp +++ b/libs/matdbg/src/TextWriter.cpp @@ -107,6 +107,12 @@ static bool printMaterial(ostream& text, const ChunkContainer& container) { text << name.c_str() << endl; } + CString compilationParameters; + if (read(container, MaterialCompilationParameters, &compilationParameters)) { + text << " " << setw(alignment) << left << "Compilation Parameters: "; + text << compilationParameters.c_str() << endl; + } + text << endl; text << "Shading:" << endl; diff --git a/tools/matc/src/matc/CommandlineConfig.cpp b/tools/matc/src/matc/CommandlineConfig.cpp index 6adeb94c90..8d205b7c1f 100644 --- a/tools/matc/src/matc/CommandlineConfig.cpp +++ b/tools/matc/src/matc/CommandlineConfig.cpp @@ -30,6 +30,53 @@ using namespace utils; namespace matc { +static constexpr const char* OPTSTR = "hLxo:f:dm:a:l:p:D:T:P:OSEr:vV:gtwF1R"; +static const struct option OPTIONS[] = { + { "help", no_argument, nullptr, 'h' }, + { "license", no_argument, nullptr, 'L' }, + { "output", required_argument, nullptr, 'o' }, + { "output-format", required_argument, nullptr, 'f' }, + { "debug", no_argument, nullptr, 'd' }, + { "variant-filter", required_argument, nullptr, 'V' }, + { "platform", required_argument, nullptr, 'p' }, + { "optimize", no_argument, nullptr, 'x' }, // for backward compatibility + { "optimize", no_argument, nullptr, 'O' }, // for backward compatibility + { "optimize-size", no_argument, nullptr, 'S' }, + { "optimize-none", no_argument, nullptr, 'g' }, + { "preprocessor-only", no_argument, nullptr, 'E' }, + { "api", required_argument, nullptr, 'a' }, + { "feature-level", required_argument, nullptr, 'l' }, + { "no-essl1", no_argument, nullptr, '1' }, + { "define", required_argument, nullptr, 'D' }, + { "template", required_argument, nullptr, 'T' }, + { "material-parameter",required_argument, nullptr, 'P' }, + { "reflect", required_argument, nullptr, 'r' }, + { "print", no_argument, nullptr, 't' }, + { "version", no_argument, nullptr, 'v' }, + { "raw", no_argument, nullptr, 'w' }, + { "no-sampler-validation", no_argument, nullptr, 'F' }, + { "save-raw-variants", no_argument, nullptr, 'R' }, + { nullptr, 0, nullptr, 0 } // termination of the option list +}; + +// A list of options that may contain PII(Personally Identifiable Information) data. +// We ignore these options when we call the `toPIISafeString` method. +static const std::string_view PII_OPTIONS[] = { + "output", +}; + +static bool isPIIOption(const char* longOptionName) { + if (!longOptionName) { + return false; + } + for (auto option : PII_OPTIONS) { + if (option == longOptionName) { + return true; + } + } + return false; +} + static void usage(char* name) { std::string exec_name(utils::Path(name).getName()); std::string usage( @@ -181,35 +228,6 @@ static void parseDefine(std::string defineString, matp::Config::StringReplacemen } bool CommandlineConfig::parse() { - static constexpr const char* OPTSTR = "hLxo:f:dm:a:l:p:D:T:P:OSEr:vV:gtwF1R"; - static const struct option OPTIONS[] = { - { "help", no_argument, nullptr, 'h' }, - { "license", no_argument, nullptr, 'L' }, - { "output", required_argument, nullptr, 'o' }, - { "output-format", required_argument, nullptr, 'f' }, - { "debug", no_argument, nullptr, 'd' }, - { "variant-filter", required_argument, nullptr, 'V' }, - { "platform", required_argument, nullptr, 'p' }, - { "optimize", no_argument, nullptr, 'x' }, // for backward compatibility - { "optimize", no_argument, nullptr, 'O' }, // for backward compatibility - { "optimize-size", no_argument, nullptr, 'S' }, - { "optimize-none", no_argument, nullptr, 'g' }, - { "preprocessor-only", no_argument, nullptr, 'E' }, - { "api", required_argument, nullptr, 'a' }, - { "feature-level", required_argument, nullptr, 'l' }, - { "no-essl1", no_argument, nullptr, '1' }, - { "define", required_argument, nullptr, 'D' }, - { "template", required_argument, nullptr, 'T' }, - { "material-parameter",required_argument, nullptr, 'P' }, - { "reflect", required_argument, nullptr, 'r' }, - { "print", no_argument, nullptr, 't' }, - { "version", no_argument, nullptr, 'v' }, - { "raw", no_argument, nullptr, 'w' }, - { "no-sampler-validation", no_argument, nullptr, 'F' }, - { "save-raw-variants", no_argument, nullptr, 'R' }, - { nullptr, 0, nullptr, 0 } // termination of the option list - }; - int opt; int option_index = 0; @@ -348,4 +366,72 @@ bool CommandlineConfig::parse() { return true; } +// This method concatenates all options and arguments, excluding the executable name, input file +// name, and any options found in PII_OPTIONS due to potential PII data. +std::string CommandlineConfig::toPIISafeString() const noexcept { + std::string result; + optind = 1; // Reset getopt's internal index before parsing + + while (true) { + // getopt_long will only set `long_index` if a long option is parsed. + int long_index = -1; + int opt = getopt_long(mArgc, mArgv, OPTSTR, OPTIONS, &long_index); + if (opt == -1) { + break; // End of options + } + + // Find the matched option. + const struct option* matched_option = nullptr; + if (long_index != -1) { + // A long option was parsed (e.g., --help) + matched_option = &OPTIONS[long_index]; + } else if (opt > 0) { + // A short option was parsed (e.g., -h) + for (int i = 0; OPTIONS[i].name != nullptr; ++i) { + if (OPTIONS[i].val == opt) { + matched_option = &OPTIONS[i]; + break; + } + } + } + + if (!matched_option) { + std::cerr << "Failed to find the matched option: long_index=" << long_index + << ", opt=" << opt << std::endl; + continue; + } + + // Skip if it's a PII option. + if (isPIIOption(matched_option->name)) { + continue; + } + + // Reconstruct the option. + if (long_index != -1) { + result += "--"; + result += matched_option->name; + result += " "; + } else if (opt > 0) { + result += "-"; + result += (char)matched_option->val; + result += " "; + } + + // Add an argument if available. + if (optarg && matched_option && matched_option->has_arg != no_argument) { + result += optarg; + result += " "; + } + } + + // We're ignoring the last (remaining) argument because it's user input with PII. + + // Trim trailing space + if (!result.empty()) { + result.pop_back(); + } + + return result; +} + } // namespace matc diff --git a/tools/matc/src/matc/CommandlineConfig.h b/tools/matc/src/matc/CommandlineConfig.h index cd74071360..56ea0c0513 100644 --- a/tools/matc/src/matc/CommandlineConfig.h +++ b/tools/matc/src/matc/CommandlineConfig.h @@ -122,6 +122,8 @@ public: return parameters; } + std::string toPIISafeString() const noexcept override; + private: bool parse(); diff --git a/tools/matc/src/matc/MaterialCompiler.cpp b/tools/matc/src/matc/MaterialCompiler.cpp index d85e14ebf9..3f34d666be 100644 --- a/tools/matc/src/matc/MaterialCompiler.cpp +++ b/tools/matc/src/matc/MaterialCompiler.cpp @@ -76,6 +76,8 @@ bool MaterialCompiler::run(const matp::Config& config) { return true; } + builder.compilationParameters(config.toPIISafeString().c_str()); + JobSystem js; js.adopt();