This example illustrates the necessary steps from loading an MDL module and processing a material up to the point where shader code is generated and potentially serialized. In addition to the more complex Example for a Microsoft DXR-based MDL-enabled Path Tracer and Example for Compiled Distribution Functions (PTX), this example focuses only on the key steps required for code generation without any renderer specific work in order to provide a quick and precise overview.
#include <iostream>
#include <algorithm>
#include <cctype>
#include <memory>
#include <string>
#include "example_shared.h"
class Options
{
public:
static void print_usage(std::ostream& s);
bool parse(int argc, char* argv[]);
bool m_help = false;
bool m_nostdpath = false;
std::vector<std::string> m_mdl_paths;
std::string m_output_file;
bool m_use_class_compilation = true;
bool m_fold_ternary_on_df = false;
bool m_fold_all_bool_parameters = false;
bool m_fold_all_enum_parameters = false;
bool m_single_init = false;
bool m_ignore_noinline = true;
bool m_disable_pdf = false;
bool m_enable_aux = false;
bool m_enable_bsdf_flags = false;
bool m_glsl_place_uniforms_into_ssbo = false;
bool m_enable_ro_segment = false;
bool m_disable_ro_segment = false;
std::string m_max_const_data = "1024";
std::string m_lambda_return_mode;
bool m_warn_spectrum_conv = false;
std::string m_backend = "hlsl";
bool m_use_derivatives = false;
std::string m_num_texture_results = "16";
bool m_dump_metadata = false;
bool m_adapt_normal = false;
bool m_adapt_microfacet_roughness = false;
bool m_experimental = false;
bool m_run_material_analysis = false;
std::string m_qualified_material_name = "::nvidia::sdk_examples::tutorials::example_material";
std::vector<TD> m_descs;
std::vector<std::unique_ptr<std::string> > m_desc_strs;
std::string m_distilling_target = "";
};
void dump_dag(
std::ostream &s)
{
std::stringstream name;
name << i;
vf->dump(argument.get(), name.str().c_str(), 1));
if (!pn)
pn = "n/a";
s << " argument (original parameter name: " << pn << ") "
<< result->get_c_str() << std::endl;
}
std::stringstream name;
name << i;
ef->dump(temporary.get(), name.str().c_str(), 1));
s << " temporary " << result->get_c_str() << std::endl;
}
ef->dump(body.get(), 0, 1));
s << " body " << result->get_c_str() << std::endl;
}
{
out << "/* String table\n";
for (
mi::Size i = 0, n = code->get_string_constant_count(); i < n; ++i)
{
const char* c = code->get_string_constant(i);
out << " " << i << ": \"" << c << "\"\n";
}
out << "*/\n\n";
out << "/* Texture table\n";
for (
mi::Size i = 0, n = code->get_texture_count(); i < n; ++i)
{
const char* c = code->get_texture(i);
if (!c || strlen(c) == 0)
c = code->get_texture_url(i);
const char* b = code->get_texture_is_body_resource(i) ? "(body)" : "(non-body)";
out << " " << i << ": \"" << c << "\" " << b << "\n";
}
out << "*/\n\n";
out << "/* Light Profile table\n";
for (
mi::Size i = 0, n = code->get_light_profile_count(); i < n; ++i)
{
const char* c = code->get_light_profile(i);
if (!c || strlen(c) == 0)
c = code->get_light_profile_url(i);
const char* b = code->get_light_profile_is_body_resource(i) ? "(body)" : "(non-body)";
out << " " << i << ": \"" << c << "\" " << b << "\n";
}
out << "*/\n\n";
out << "/* BSDF measurement table\n";
for (
mi::Size i = 0, n = code->get_bsdf_measurement_count(); i < n; ++i)
{
const char* c = code->get_bsdf_measurement(i);
if (!c || strlen(c) == 0)
c = code->get_bsdf_measurement_url(i);
const char* b = code->get_bsdf_measurement_is_body_resource(i) ? "(body)" : "(non-body)";
out << " " << i << ": \"" << c << "\" " << b << "\n";
}
out << "*/\n\n";
}
{
switch (o) {
return "OPAQUE";
return "TRANSPARENT";
default:
return "UNKNOWN";
}
}
{
{
if (options.m_experimental)
context->set_option("experimental", true);
std::string module_name, material_name;
if (!mi::examples::mdl::parse_cmd_argument_material_name(
options.m_qualified_material_name, module_name, material_name))
exit_failure("Failed to parse the qualified material name: %s",
options.m_qualified_material_name.c_str());
mdl_impexp_api->load_module(trans.get(), module_name.c_str(), context.get());
if (!print_messages(context.get()))
exit_failure("Failed to load the selected module.");
if (!module)
exit_failure("Failed to access the loaded module.");
std::string material_db_name
= std::string(module_db_name->get_c_str()) + "::" + material_name;
material_db_name = mi::examples::mdl::add_missing_material_signature(
module.get(), material_db_name);
if (material_db_name.empty())
exit_failure("Failed to find the material '%s' in the module '%s'.",
material_name.c_str(), module_name.c_str());
if (!material_definition)
exit_failure("Failed to access the material definition.");
trans.get(), material_db_name.c_str(), mdl_factory.get());
if (!dw.is_valid())
exit_failure("Failed to access the material definition.");
if (result != 0)
exit_failure("Failed to create a material instance of: %s::%s (%d)",
module_name.c_str(), material_name.c_str(), result);
const mi::Uint32 flags = options.m_use_class_compilation
context->set_option("fold_ternary_on_df", options.m_fold_ternary_on_df);
context->set_option("fold_all_bool_parameters", options.m_fold_all_bool_parameters);
context->set_option("fold_all_enum_parameters", options.m_fold_all_enum_parameters);
context->set_option("ignore_noinline", options.m_ignore_noinline);
material_instance2->create_compiled_material(flags, context.get()));
if (!options.m_distilling_target.empty()) {
bool target_supported = false;
for (
mi::Size i = 0, n = distiller->get_target_count(); i < n; ++i) {
if (options.m_distilling_target == distiller->get_target_name(i)) {
target_supported = true;
break;
}
}
if (!target_supported)
exit_failure("Distilling target '%s' is unknown.",
options.m_distilling_target.c_str());
compiled_material = distiller->distill_material(
compiled_material.get(), options.m_distilling_target.c_str(), nullptr, &result);
if (result != 0)
exit_failure("Failed to distill a material instance of: %s::%s (%d)",
module_name.c_str(), material_name.c_str(), result);
}
if (options.m_backend == "dag") {
if (!options.m_output_file.empty())
{
std::ofstream file_stream;
file_stream.open(options.m_output_file.c_str());
if (file_stream)
{
file_stream << "\n\n\n";
dump_dag(trans.get(), mdl_factory.get(), compiled_material.get(), file_stream);
file_stream << "\n\n\n";
file_stream.close();
}
} else {
std::cout << "\n\n\n";
dump_dag(trans.get(), mdl_factory.get(), compiled_material.get(), std::cout);
std::cout << "\n\n\n";
}
} else {
if (options.m_backend == "glsl")
else if (options.m_backend == "hlsl")
else if (options.m_backend == "ptx")
else if (options.m_backend == "llvm")
else
exit_failure("Selected back-end '%s' is invalid or not supported.",
options.m_backend.c_str());
backend->set_option("texture_runtime_with_derivs",
options.m_use_derivatives ? "on" : "off");
backend->set_option("num_texture_results", options.m_num_texture_results.c_str());
backend->set_option("num_texture_spaces", "4");
backend->set_option("jit_warn_spectrum_conversion",
options.m_warn_spectrum_conv ? "on" : "off");
backend->set_option("use_renderer_adapt_normal",
options.m_adapt_normal ? "on" : "off");
backend->set_option("use_renderer_adapt_microfacet_roughness",
options.m_adapt_microfacet_roughness ? "on" : "off");
backend->set_option("enable_pdf",
!options.m_disable_pdf ? "on" : "off");
backend->set_option("enable_auxiliary",
options.m_enable_aux ? "on" : "off");
backend->set_option("libbsdf_flags_in_bsdf_data",
options.m_enable_bsdf_flags ? "on" : "off");
if (options.m_glsl_place_uniforms_into_ssbo) {
backend->set_option("glsl_place_uniforms_into_ssbo", "on");
backend->set_option("glsl_max_const_data", options.m_max_const_data.c_str());
}
if (options.m_enable_ro_segment) {
backend->set_option("enable_ro_segment", "on");
backend->set_option("max_const_data", options.m_max_const_data.c_str());
}
if (options.m_disable_ro_segment) {
backend->set_option("enable_ro_segment", "off");
}
if (!options.m_lambda_return_mode.empty()) {
if (backend->set_option(
"lambda_return_mode", options.m_lambda_return_mode.c_str()) != 0) {
exit_failure("Setting 'lambda_return_mode' option failed.");
}
}
backend->create_link_unit(trans.get(), context.get()));
if (!print_messages(context.get()))
exit_failure("Failed to create a link unit for the %s back-end",
options.m_backend.c_str());
if (options.m_descs.empty()) {
auto &descs = options.m_descs;
descs.push_back(TD("ior", "ior"));
descs.push_back(TD("thin_walled", "thin_walled"));
descs.push_back(TD("surface.scattering", "surface_scattering"));
descs.push_back(TD("surface.emission.emission", "surface_emission_emission"));
descs.push_back(TD("surface.emission.intensity", "surface_emission_intensity"));
descs.push_back(TD("surface.emission.mode", "surface_emission_mode"));
descs.push_back(TD("backface.scattering", "backface_scattering"));
descs.push_back(TD("backface.emission.emission", "backface_emission_emission"));
descs.push_back(TD("backface.emission.intensity", "backface_emission_intensity"));
descs.push_back(TD("backface.emission.mode", "backface_emission_mode"));
descs.push_back(TD("volume.absorption_coefficient", "volume_absorption_coefficient"));
descs.push_back(TD("volume.scattering_coefficient", "volume_scattering_coefficient"));
descs.push_back(TD("geometry.normal", "geometry_normal"));
descs.push_back(TD("geometry.cutout_opacity", "geometry_cutout_opacity"));
descs.push_back(TD("geometry.displacement", "geometry_displacement"));
}
if (options.m_single_init)
options.m_descs.insert(options.m_descs.begin(), TD("init", "init"));
link_unit->add_material(
compiled_material.get(), options.m_descs.data(), options.m_descs.size(), context.get());
if (!print_messages(context.get()))
exit_failure("Failed to select functions for code generation.");
backend->translate_link_unit(link_unit.get(), context.get()));
if (!print_messages(context.get()))
exit_failure("Failed to translate the link unit to %s code.",
options.m_backend.c_str());
if (!options.m_output_file.empty())
{
std::ofstream file_stream;
file_stream.open(options.m_output_file.c_str());
if (file_stream)
{
file_stream << target_code->get_code();
if (options.m_dump_metadata)
dump_metadata(target_code, file_stream);
file_stream.close();
}
}
else {
std::cout << "\n\n\n" << target_code->get_code() << "\n\n\n";
if (options.m_dump_metadata)
dump_metadata(target_code, std::cout);
}
if (options.m_backend != "llvm") {
context->set_option("serialize_class_instance_data", true);
target_code->serialize(context.get()));
if (!print_messages(context.get()))
exit_failure("MDL target code serialization failed.");
tc_buffer->get_data_size();
tc_buffer->get_data();
}
}
std::cout <<
"compiled material hash: \n" << std::hex << hash.
m_id1 <<
" " << hash.
m_id2
<<
" " << hash.
m_id3 <<
" " << hash.
m_id4 << std::dec <<
"\n";
if (options.m_run_material_analysis) {
std::cout << "\n\n\n";
std::cout << "Might depend on transform state functions: " <<
(compiled_material->depends_on_state_transform() ? "YES" : "NO") << "\n";
std::cout << "Might depend on state::object_id(): " <<
(compiled_material->depends_on_state_object_id() ? "YES" : "NO") << "\n";
std::cout << "Might depend on global distribution: " <<
(compiled_material->depends_on_global_distribution() ? "YES" : "NO") << "\n";
std::cout << "Might depend on uniform scene data: " <<
(compiled_material->depends_on_uniform_scene_data() ? "YES" : "NO") << "\n";
std::cout << "Opacity of this instance: " <<
opacity(compiled_material->get_opacity()) << "\n";
std::cout << "Surface opacity of this instance: " <<
opacity(compiled_material->get_surface_opacity()) << "\n";
std::cout << "Has constant cutout opacity: " <<
(compiled_material->get_cutout_opacity(&cutout_opacity) ? "YES" : "NO") << "\n";
std::cout << "Cutout opacity of this instance: " << cutout_opacity << "\n";
}
}
trans->commit();
}
int MAIN_UTF8(int argc, char* argv[])
{
Options options;
mi::examples::mdl::Configure_options configure_options;
if (!options.parse(argc, argv))
{
options.print_usage(std::cout);
exit_failure("Failed to parse command line arguments.");
}
if (options.m_help) {
options.print_usage(std::cout);
exit_success();
}
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 (!neuray.is_valid_interface())
exit_failure("Failed to load the SDK.");
if (!mi::examples::mdl::configure(neuray.get(), configure_options))
exit_failure("Failed to initialize the SDK.");
exit_failure("Failed to load the mdl_distiller plugin.");
if (ret != 0)
exit_failure("Failed to initialize the SDK. Result code: %d", ret);
code_gen(neuray.get(), options);
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
void Options::print_usage(std::ostream& s)
{
s << R"(
code_gen [options] <qualified_material_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.
-o|--output <file> Export the module to this file. Default: stdout
-b|--backend <backend> Select the back-end to generate code for. One of
{DAG, GLSL, HLSL, PTX, LLVM}. Default: HLSL
-e|--expr_path <path> Add an MDL expression path to generate, like "surface.scattering".
Defaults to a set of expression paths.
-d|--derivatives Generate code with derivative support.
-i|--instance_compilation Use instance compilation instead of class compilation.
-t|--text_results <num> Number of float4 texture result slots in the state. Default: 16
-M|--dump-meta-data Print all generated meta data tables.
--ft Fold ternary operators when used on distribution functions.
--fb Fold boolean parameters.
--fe Fold enum parameters.
--single-init Compile in single init mode.
--dian Disable ignoring anno::noinline() annotations.
--disable_pdf Disable generation of separate PDF function.
--enable_aux Enable generation of auxiliary function.
--enable_bsdf_flags Enable "flags" field in BSDF data structures in generated code.
--glsl_place_uniforms_into_ssbo Enable placing constants into a shader storage buffer object.
--enable_ro_segment Enable storing bigger constants in a read-only data segment
(enabled by default for HLSL backend).
--disable_ro_segment Disable storing bigger constants in a read-only data segment
(only needed for HLSL backend).
--max_const_data <size> Set the maximum size of constants in bytes in the generated code
(requires read-only data segment or ssbo, default 1024).
--lambda_return_mode <mode> Set how base types and vector types are returned for PTX and LLVM
backends. One of {default, sret, value}.
--adapt_normal Enable renderer callback to adapt the normal.
--adapt_microfacet_roughness Enable renderer callback to adapt the roughness for
microfacet BSDFs.
--experimental Enable experimental compiler features (for internal testing).
--warn-spectrum-conv Warn if a spectrum constructor is converted into RGB.
--analyze Run backend analysis
--distill <target> Distill the material before running the code generation.)";
s << 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")
m_help = true;
else if (arg == "-n" || arg == "--nostdpath")
m_nostdpath = true;
else if (arg == "-d" || arg == "--derivatives")
m_use_derivatives = true;
else if (arg == "-i" || arg == "--instance_compilation")
m_use_class_compilation = false;
else if (arg == "--ft")
m_fold_ternary_on_df = true;
else if (arg == "--fb")
m_fold_all_bool_parameters = true;
else if (arg == "--fe")
m_fold_all_enum_parameters = true;
else if (arg == "--single-init")
m_single_init = true;
else if (arg == "--dian")
m_ignore_noinline = false;
else if (arg == "--disable_pdf")
m_disable_pdf = true;
else if (arg == "--enable_aux")
m_enable_aux = true;
else if (arg == "--enable_bsdf_flags")
m_enable_bsdf_flags = true;
else if (arg == "--glsl_place_uniforms_into_ssbo")
m_glsl_place_uniforms_into_ssbo = true;
else if (arg == "--enable_ro_segment")
m_enable_ro_segment = true;
else if (arg == "--disable_ro_segment")
m_disable_ro_segment = true;
else if (arg == "--max_const_data")
{
if (i == argc - 1)
{
std::cerr << "error: Argument for --max_const_data missing." << std::endl;
return false;
}
m_max_const_data = argv[++i];
}
else if (arg == "--lambda_return_mode")
{
if (i == argc - 1)
{
std::cerr << "error: Argument for --lambda_return_mode missing." << std::endl;
return false;
}
m_lambda_return_mode = argv[++i];
}
else if (arg == "--adapt_normal")
m_adapt_normal = true;
else if (arg == "--adapt_microfacet_roughness")
m_adapt_microfacet_roughness = true;
else if (arg == "--analyze")
m_run_material_analysis = true;
else if (arg == "--experimental")
m_experimental = true;
else if (arg == "--warn-spectrum-conv")
m_warn_spectrum_conv = 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 == "-o" || arg == "--output")
{
if (i == argc - 1)
{
std::cerr << "error: Argument for -o|--output missing." << std::endl;
return false;
}
m_output_file = argv[++i];
}
else if (arg == "-b" || arg == "--backend")
{
if (i == argc - 1)
{
std::cerr << "error: Argument for -b|--backend missing." << std::endl;
return false;
}
m_backend = argv[++i];
[](unsigned char c) { return std::tolower(c); });
}
else if (arg == "-e" || arg == "--expr_path")
{
if (i == argc - 1)
{
std::cerr << "error: Argument for -e|--expr_path missing." << std::endl;
return false;
}
std::string expr = argv[++i];
std::string func_name = expr;
[](unsigned char c) { return char(c) == '.' ? '_' : c; });
m_desc_strs.push_back(std::unique_ptr<std::string>(new std::string(expr)));
m_desc_strs.push_back(std::unique_ptr<std::string>(new std::string(func_name)));
m_descs.push_back(TD(
m_desc_strs[m_desc_strs.size() - 2].get()->c_str(),
m_desc_strs.back().get()->c_str()));
}
else if (arg == "-t" || arg == "--text_results")
{
if (i == argc - 1)
{
std::cerr << "error: Argument for -t|--text_results missing." << std::endl;
return false;
}
m_num_texture_results = argv[++i];
}
else if (arg == "-M" || arg == "--dump_meta_data")
m_dump_metadata = true;
else if (arg == "--distill")
{
if (i == argc - 1)
{
std::cerr << "error: Argument for --distill missing." << std::endl;
return false;
}
m_distilling_target = argv[++i];
}
else
{
std::cerr << "error: Unknown option \"" << arg << "\"." << std::endl;
return false;
}
}
else
{
if (i != argc - 1)
{
std::cerr << "error: Unexpected argument \"" << arg << "\"." << std::endl;
return false;
}
m_qualified_material_name = arg;
}
}
if (!m_help)
{
if (m_qualified_material_name.empty())
{
std::cerr << "error: Qualified material name missing." << std::endl;
return false;
}
if (m_backend != "dag" && m_backend != "glsl" && m_backend != "hlsl" &&
m_backend != "ptx" && m_backend != "llvm")
{
std::cerr << "error: Back-end is missing or invalid." << std::endl;
return false;
}
if (m_glsl_place_uniforms_into_ssbo && m_backend != "glsl")
{
std::cerr << "error: Option \"glsl_place_uniforms_into_ssbo\" is only available for "
"GLSL backend." << std::endl;
return false;
}
}
return true;
}
Handle class template for interfaces, automatizing the lifetime control via reference counting.
Definition: handle.h:113
A wrapper around the interface for MDL function definitions.
Definition: definition_wrapper.h:44
This interface represents a compiled material.
Definition: icompiled_material.h:97
virtual Size get_temporary_count() const =0
Returns the number of temporaries.
virtual const IValue * get_argument(Size index) const =0
Returns the value of an argument.
virtual Size get_parameter_count() const =0
Returns the number of parameters used by this compiled material.
virtual const IExpression_direct_call * get_body() const =0
Returns the body (or material root) of the compiled material.
virtual const IExpression * get_temporary(Size index) const =0
Returns a temporary.
virtual const char * get_parameter_name(Size index) const =0
Returns the name of a parameter.
This interface is used to interact with the distributed database.
Definition: idatabase.h:289
This interface represents a function call.
Definition: ifunction_call.h:52
This interface represents a function definition.
Definition: ifunction_definition.h:44
This interface represents a material instance.
Definition: imaterial_instance.h:34
@ CLASS_COMPILATION
Selects class compilation instead of instance compilation.
Definition: imaterial_instance.h:41
@ DEFAULT_OPTIONS
Default compilation options (e.g., instance compilation).
Definition: imaterial_instance.h:40
This interface can be used to obtain the MDL backends.
Definition: imdl_backend_api.h:56
@ MB_CUDA_PTX
Generate CUDA PTX code.
Definition: imdl_backend_api.h:61
@ MB_LLVM_IR
Generate LLVM IR (LLVM 12.0 compatible).
Definition: imdl_backend_api.h:62
@ MB_GLSL
Generate GLSL code.
Definition: imdl_backend_api.h:63
@ MB_HLSL
Generate HLSL code.
Definition: imdl_backend_api.h:65
Provides access to various functionality related to MDL distilling.
Definition: imdl_distiller_api.h:47
Factory for various MDL interfaces and functions.
Definition: imdl_factory.h:53
virtual IMdl_execution_context * create_execution_context()=0
Creates an execution context.
virtual IType_factory * create_type_factory(ITransaction *transaction)=0
Returns an MDL type factory for the given transaction.
virtual IExpression_factory * create_expression_factory(ITransaction *transaction)=0
Returns an MDL expression factory for the given transaction.
virtual const IString * get_db_module_name(const char *mdl_name)=0
Returns the DB name for the MDL name of a module (or file path for MDLE modules).
virtual IValue_factory * create_value_factory(ITransaction *transaction)=0
Returns an MDL value factory for the given transaction.
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
This is an object representing the MDL SDK library.
Definition: ineuray.h:44
virtual Sint32 shutdown(bool blocking=true)=0
Shuts down the library.
virtual base::IInterface * get_api_component(const base::Uuid &uuid) const =0
Returns an API component from the MDL SDK API.
virtual Sint32 start(bool blocking=true)=0
Starts the operation of the MDL SDK library.
A transaction provides a consistent view on the database.
Definition: itransaction.h:82
#define MI_BASE_DLL_FILE_EXT
The operating system specific default filename extension for shared libraries (DLLs)
Definition: config.h:340
Uint32 m_id1
First value.
Definition: uuid.h:27
Uint32 m_id2
Second value.
Definition: uuid.h:28
Uint32 m_id3
Third value.
Definition: uuid.h:29
Uint32 m_id4
Fourth value.
Definition: uuid.h:30
unsigned int Uint32
32-bit unsigned integer.
Definition: types.h:49
Uint64 Size
Unsigned integral type that is large enough to hold the size of all types.
Definition: types.h:112
float Float32
32-bit float.
Definition: types.h:51
signed int Sint32
32-bit signed integer.
Definition: types.h:46
void transform(const Vector &vec, ResultVector &result, UnaryFunctor f)
Generic transform function that applies a unary functor (return value).
Definition: function.h:234
Material_opacity
The opacity of a compiled material.
Definition: icompiled_material.h:56
@ OPACITY_TRANSPARENT
The material is transparent.
Definition: icompiled_material.h:60
@ OPACITY_OPAQUE
The material is opaque.
Definition: icompiled_material.h:58
A 128 bit representation of a universally unique identifier (UUID or GUID).
Definition: uuid.h:26
Description of target function.
Definition: imdl_backend.h:1764