This example loads an MDL module and scan for selected information, such as its import, resource dependencies and more.
Using the command line, we can specify which details of a module to extract, such as its imports, type and constant definitions, material and function declarations, as well as resource dependencies. Additionally, the tool can optionally perform a recursive scan of the imported modules.
#include <iostream>
#include <string>
#include <unordered_set>
#include "example_shared.h"
enum Dump_options
{
DUMP_NOTHING = 0x00,
DUMP_IMPORTS = 0x01,
DUMP_TYPES = 0x02,
DUMP_CONSTANTS = 0x04,
DUMP_DEFINITIONS = 0x08,
DUMP_RESOURCES = 0x10,
DUMP_ALL = 0xFF
};
class Options
{
public:
static void print_usage(std::ostream& s);
bool parse(int argc, char* argv[]);
std::string m_qualified_module_name = "::nvidia::sdk_examples::tutorials";
bool m_recursive = false;
bool m_skip_standard = false;
int m_dump_options = DUMP_IMPORTS | DUMP_RESOURCES;
std::string m_def_filter = "";
bool m_nostdpath = false;
std::vector<std::string> m_mdl_paths;
};
class MDL_module_scanner
{
public:
void scan_module(const std::string& qualified_module_name);
private:
void dump_definition(
std::ostream& s);
void dump_module(
Options m_options;
std::unordered_set<std::string> m_module_list;
};
: m_neuray(neuray)
, m_options(options)
{
}
void MDL_module_scanner::scan_module(const std::string& qualified_module_name)
{
scope(database->get_global_scope());
context(m_mdl_factory->create_execution_context());
m_transaction = scope->create_transaction();
{
check_success(mdl_impexp_api->load_module(
m_transaction.get(), qualified_module_name.c_str(), context.get()) >= 0);
print_messages(context.get());
m_mdl_factory->get_db_module_name(qualified_module_name.c_str()));
dump_module(module.get(), 0);
}
m_transaction->commit();
}
void MDL_module_scanner::dump_definition(
std::ostream& s)
{
const std::string shift(level * 4 + 4, ' ');
m_mdl_factory->create_type_factory(m_transaction.get()));
m_mdl_factory->create_expression_factory(m_transaction.get()));
for (
mi::Size index = 0; index < count; index++)
{
s << shift << "parameter " << type_text->get_c_str() << " " << name;
defaults->get_expression(name.c_str()));
if (default_.is_valid_interface())
{
expression_factory->dump(default_.get(), 0, level + 1));
s << ", default = " << default_text->get_c_str() << std::endl;
}
else
{
s << " (no default)" << std::endl;
}
}
for (
mi::Size i = 0; i < temporary_count; ++i)
{
std::stringstream name;
name << i;
expression_factory->dump(temporary.get(), name.str().c_str(), 1));
s << shift << "temporary " << result->get_c_str() << std::endl;
}
if (result)
s << shift << "body " << result->get_c_str() << std::endl;
else
s << shift << "body not available for this function" << std::endl;
s << std::endl;
}
void MDL_module_scanner::dump_module(
{
const std::string separator(120 - level * 4, '-');
const std::string shift(level * 4, ' ');
decoded_name(m_mdl_factory->decode_name(module->
get_mdl_name()));
const std::string module_name = decoded_name->get_c_str();
std::cout << shift << separator << std::endl;
{
std::cout << shift << "Found module: " << module_name << " (Standard Module)" << std::endl;
}
else
{
std::cout << shift << "Found module: " << module_name << std::endl;
if (filename)
std::cout << shift << "Loaded file : " << filename << std::endl;
}
std::cout << std::endl;
if (module_count > 0 && m_options.m_dump_options & DUMP_IMPORTS)
{
std::cout << shift << "+Imports included in " << module_name << ":" << std::endl;
for (
mi::Size i = 0; i < module_count; i++)
{
const std::string import_name(module->
get_import(i));
decoded_name(m_mdl_factory->decode_name(imported_module->get_mdl_name()));
const std::string imported_name = decoded_name->get_c_str();
std::cout << shift << " " << imported_name << std::endl;
}
std::cout << std::endl;
}
if (m_options.m_dump_options & DUMP_TYPES)
{
m_mdl_factory->create_type_factory(m_transaction.get()));
const mi::Size num_types = types->get_size();
if (num_types > 0)
{
std::cout << shift << "+Types defined in " << module_name << ":" << std::endl;
for (
mi::Size i = 0; i < num_types; ++i)
{
std::cout << shift << " " << result->get_c_str() << std::endl;
}
std::cout << std::endl;
}
}
if (m_options.m_dump_options & DUMP_CONSTANTS)
{
m_mdl_factory->create_value_factory(m_transaction.get()));
const mi::Size num_constants = constants->get_size();
if (num_constants > 0)
{
std::cout << shift << "+Constants defined in " << module_name << ":" << std::endl;
for (
mi::Size i = 0; i < num_constants; ++i)
{
const char* name = constants->get_name(i);
std::cout << shift << " " << name << " = " << result->get_c_str() << std::endl;
}
std::cout << std::endl;
}
}
if (function_count > 0 && m_options.m_dump_options & DUMP_DEFINITIONS)
{
std::cout << shift << "+Functions defined in " << module_name << ":" << std::endl;
for (
mi::Size i = 0; i < function_count; i++)
{
const bool apply_filter = !m_options.m_def_filter.empty() &&
(function_name.find(m_options.m_def_filter) != std::string::npos);
if (m_options.m_def_filter.empty() || apply_filter)
{
std::cout << shift << " " << function_name << std::endl;
if (apply_filter)
dump_definition(function_definition.get(), level + 1, std::cout);
const char* thumbnail = function_definition->get_thumbnail();
if (thumbnail)
std::cout << shift << " Thumbnail: " << thumbnail << std::endl;
}
}
std::cout << std::endl;
}
if (material_count > 0 && m_options.m_dump_options & DUMP_DEFINITIONS)
{
std::cout << shift << "+Materials defined in " << module_name << ":" << std::endl;
for (
mi::Size i = 0; i < material_count; i++)
{
const bool apply_filter = !m_options.m_def_filter.empty() &&
(material_name.find(m_options.m_def_filter) != std::string::npos);
if (m_options.m_def_filter.empty() || apply_filter)
{
std::cout << shift << " " << material_name << std::endl;
if (apply_filter)
dump_definition(material_definition.get(), level + 1, std::cout);
const char* thumbnail = material_definition->get_thumbnail();
if (thumbnail)
std::cout << shift << " Thumbnail: " << thumbnail << std::endl;
}
}
std::cout << std::endl;
}
if (resources_count > 0 && m_options.m_dump_options & DUMP_RESOURCES)
{
std::cout << shift << "+Resources used in " << module_name << ":" << std::endl;
for (
mi::Size r = 0; r < resources_count; ++r)
{
const char* db_name = resource->get_value();
const char* mdl_file_path = resource->get_file_path();
if (db_name == nullptr)
{
std::cout << shift << " db_name: none" << std::endl;
std::cout << shift << " mdl_file_path: " << mdl_file_path << std::endl
<< std::endl;
continue;
}
std::cout << shift << " db_name: " << db_name << std::endl;
std::cout << shift << " mdl_file_path: " << mdl_file_path << std::endl;
resource->get_type());
switch (type->get_kind())
{
{
for (
mi::Size f = 0, fn = image->get_length(); f < fn; ++f)
for (
mi::Size t = 0, tn = image->get_frame_length(f); t < tn; ++t)
{
const char* resolved_file_path = image->get_filename(f, t);
if (resolved_file_path)
{
std::cout << shift << " resolved_file_path[" << f << "," << t << "]: "
<< resolved_file_path << std::endl;
}
}
break;
}
{
const char* resolved_file_path = light_profile->get_filename();
if (resolved_file_path)
std::cout << shift << " resolved_file_path: " << resolved_file_path << std::endl;
break;
}
{
const char* resolved_file_path = mbsdf->get_filename();
if(resolved_file_path)
std::cout << shift << " resolved_file_path: " << resolved_file_path << std::endl;
break;
}
default:
exit_failure(std::string("Unexpected Resource type: " +
std::to_string(type->get_kind())).c_str());
break;
}
std::cout << std::endl;
}
}
if (m_options.m_recursive)
{
for (
mi::Size i = 0; i < module_count; i++)
{
auto it = std::find(m_module_list.begin(), m_module_list.end(), db_name);
if (it != m_module_list.end())
continue;
m_module_list.insert(db_name);
{
if (m_options.m_skip_standard && imported_module->is_standard_module())
continue;
dump_module(imported_module.get(), level + 1);
}
}
}
std::cout << std::endl;
}
void Options::print_usage(std::ostream& s)
{
s << R"(
code_gen [options] <qualified_module_name>
options:
-h|--help Print this usage message and exit.
-p|--mdl_path <path> Add the given path to the MDL search path.
-n|--nostdpath Prevent adding the MDL system and user search
path(s) to the MDL search path.
-f|--filter Select type of information to be dumped.
Format: -f "type1|type2|...|typeN".
Types: 'imports', 'types', 'constants', definitions', 'resources',
'all'.
Default: "imports|resources".
-r|--recursive Scan imported modules recursively.
-s|--skip_standard Skip standard modules.
-d|--filter_definitions If 'definitions' have been included with the '-f' option, this extra
filter will select only function and material definitions with names
that contain the "substring", and for the previous, it will dump
extended information like parameters with its defaults, temporaries
and the body.
Format: -d "substring")";
s << std::endl << std::endl;
}
bool Options::parse(int argc, char* argv[])
{
for (int i = 1; i < argc; ++i)
{
const std::string arg = argv[i];
if (arg[0] == '-')
{
if (arg == "-h" || arg == "--help")
{
return false;
}
else if (arg == "-n" || arg == "--nostdpath")
{
m_nostdpath = true;
}
else if (arg == "-p" || arg == "--mdl_path")
{
if (i == argc - 1)
{
std::cerr << "error: Argument for -p|--mdl_path missing." << std::endl;
return false;
}
m_mdl_paths.push_back(argv[++i]);
}
else if (arg == "-f" || arg == "--filter")
{
if (i == argc - 1)
{
std::cerr << "error: Argument for -f|--filter missing." << std::endl;
return false;
}
std::istringstream ss(argv[++i]);
std::string type;
m_dump_options = DUMP_NOTHING;
while (std::getline(ss, type, '|'))
{
if (type == "imports")
{
m_dump_options |= DUMP_IMPORTS;
}
else if (type == "types")
{
m_dump_options |= DUMP_TYPES;
}
else if (type == "constants")
{
m_dump_options |= DUMP_CONSTANTS;
}
else if (type == "definitions")
{
m_dump_options |= DUMP_DEFINITIONS;
}
else if (type == "resources")
{
m_dump_options |= DUMP_RESOURCES;
}
else if (type == "all")
{
m_dump_options |= DUMP_ALL;
}
else
{
std::cerr << "error: Unknown filter type: " << type << "." << std::endl;
return false;
}
}
}
else if (arg == "-r" || arg == "--recursive")
{
m_recursive = true;
}
else if (arg == "-s" || arg == "--skip_standard")
{
m_skip_standard = true;
}
else if (arg == "-d" || arg == "--filter_definitions")
{
if (i == argc - 1)
{
std::cerr << "error: Argument for -d|--filter_definitions missing." << std::endl;
return false;
}
m_def_filter = argv[++i];
}
else
{
std::cerr << "error: Unknown option \"" << arg << "\"." << std::endl;
return false;
}
}
else
{
if (i == argc - 1)
m_qualified_module_name = arg;
}
}
return true;
}
int MAIN_UTF8(int argc, char* argv[])
{
Options options;
if (!options.parse(argc, argv))
{
options.print_usage(std::cout);
exit_failure("Failed to parse command line arguments.");
}
if (!neuray.is_valid_interface())
exit_failure("Failed to load the SDK.");
mi::examples::mdl::Configure_options configure_options;
configure_options.additional_mdl_paths = options.m_mdl_paths;
if (options.m_nostdpath)
{
configure_options.add_admin_space_search_paths = false;
configure_options.add_user_space_search_paths = false;
configure_options.add_example_search_path = false;
}
if (!mi::examples::mdl::configure(neuray.get(), configure_options))
exit_failure("Failed to initialize the SDK.");
if (ret != 0)
exit_failure("Failed to initialize the SDK. Result code: %d", ret);
{
MDL_module_scanner module_scanner(neuray.get(), options);
module_scanner.scan_module(options.m_qualified_module_name);
}
if (neuray->shutdown() != 0)
exit_failure("Failed to shutdown the SDK.");
neuray = nullptr;
if (!mi::examples::mdl::unload())
exit_failure("Failed to unload the SDK.");
exit_success();
}
COMMANDLINE_TO_UTF8
A scene element that stores measured BSDF data.
Definition: ibsdf_measurement.h:39
This interface is used to interact with the distributed database.
Definition: idatabase.h:363
This interface represents a function definition.
Definition: ifunction_definition.h:44
virtual const IExpression * get_temporary(Size index) const =0
Returns the expression of a temporary.
virtual Size get_parameter_count() const =0
Returns the number of parameters.
virtual const IExpression * get_body() const =0
Returns the expression that represents the body of the function (if possible).
virtual Size get_temporary_count() const =0
Returns the number of temporaries used by this function.
virtual const IType_list * get_parameter_types() const =0
Returns the types of all parameters.
virtual const char * get_parameter_name(Size index) const =0
Returns the name of the parameter at index.
virtual const IExpression_list * get_defaults() const =0
Returns the defaults of all parameters.
This interface represents a pixel image file.
Definition: iimage.h:66
This interface represents light profiles.
Definition: ilightprofile.h:73
Factory for various MDL interfaces and functions.
Definition: imdl_factory.h:53
API component for MDL related import and export operations.
Definition: imdl_impexp_api.h:43
This interface represents an MDL module.
Definition: imodule.h:634
virtual const IValue_resource * get_resource(Size index) const =0
Returns a resource defined in the module.
virtual Size get_function_count() const =0
Returns the number of function definitions exported by the module.
virtual const char * get_function(Size index) const =0
Returns the DB name of the function definition at index.
virtual bool is_standard_module() const =0
Indicates whether this module is a standard module.
virtual const IValue_list * get_constants() const =0
Returns the constants exported by this module.
virtual const char * get_filename() const =0
Returns the name of the MDL source file from which this module was created.
virtual Size get_import_count() const =0
Returns the number of modules imported by the module.
virtual const char * get_material(Size index) const =0
Returns the DB name of the material definition at index.
virtual const char * get_import(Size index) const =0
Returns the DB name of the imported module at index.
virtual const char * get_mdl_name() const =0
Returns the MDL name of the module.
virtual Size get_material_count() const =0
Returns the number of material definitions exported by the module.
virtual const IType_list * get_types() const =0
Returns the types exported by this module.
virtual Size get_resources_count() const =0
Returns the number of resources defined in the module.
This is an object representing the MDL SDK library.
Definition: ineuray.h:44
Textures add image processing options to images.
Definition: itexture.h:68
@ TK_TEXTURE
A texture type. See mi::neuraylib::IType_texture.
Definition: itype.h:183
@ TK_BSDF_MEASUREMENT
The bsdf_measurement type. See mi::neuraylib::IType_bsdf_measurement.
Definition: itype.h:187
@ TK_LIGHT_PROFILE
The light_profile type. See mi::neuraylib::IType_light_profile.
Definition: itype.h:185
int Sint32
32-bit signed integer.
Definition: types.h:46
Uint64 Size
Unsigned integral type that is large enough to hold the size of all types.
Definition: types.h:112