Iray Programmer's Manual

Using an Iray Bridge server

You need to configure the address and port of the Iray Bridge server. See the following example program for details:

For a render request, select the render mode iray_cloud. No other changes are required.

The example shows how to create a snapshot of the uploaded scene on the server side. This operation is asynchronous. The example program simply waits for the operation to finish since there is nothing else to do. The created snapshot can be imported later using the cb_importer plugin (with the same setting for the cache directory on the server).

example_bridge_server.cpp

001 /******************************************************************************
002  * © 1986, 2014 NVIDIA Corporation. All rights reserved.
003  *****************************************************************************/
004 
005 // examples/example_bridge_server.cpp
006 //
007 // Starts listening for Iray Bridge clients. It will accept client rendering and snapshot requests.
008 //
009 // The example expects the following command line argument:
010 //
011 //   example_bridge_server <mdl_path> <path_to_disk_cache> <listen_address>
012 //
013 // mdl_path            path to the MDL modules, e.g., iray-<version>/mdl
014 // path_to_disk_cache  directory where the server can cache uploaded elements
015 // listen_address      the address to listen on, e.g., 0.0.0.0:8998
016 
017 #include <cstdio>
018 
019 #include <mi/neuraylib.h>
020 
021 // Include code shared by all examples.
022 #include "example_shared.h"
023 
024 void run_bridge_server( mi::base::Handle<mi::neuraylib::INeuray> neuray)
025 {
026     // Create a server instance
027     mi::base::Handle<mi::neuraylib::IRemote_server> bridge_server(
028 	neuray->get_api_component<mi::neuraylib::IRemote_server>());
029     bridge_server->start();
030     sleep_seconds( 60);
031 }
032 
033 void configuration( mi::base::Handle<mi::neuraylib::INeuray> neuray,
034                     const char* mdl_path,
035                     const char* disk_cache_path,
036                     const char* server_address)
037 {
038     // Configure the Remote server
039     mi::base::Handle<mi::neuraylib::IRemote_configuration> remote_configuration(
040         neuray->get_api_component<mi::neuraylib::IRemote_configuration>());
041     check_success( remote_configuration.is_valid_interface());
042     check_success( remote_configuration->set_remote_disk_cache_path( disk_cache_path) == 0);
043     check_success( remote_configuration->set_scene_export_path( disk_cache_path) == 0);
044     check_success( remote_configuration->set_remote_server_listen_address( server_address) == 0);
045 
046     // set the search path for .mdl files.
047     mi::base::Handle<mi::neuraylib::IRendering_configuration> rendering_configuration(
048         neuray->get_api_component<mi::neuraylib::IRendering_configuration>());
049     check_success( rendering_configuration.is_valid_interface());
050     check_success( rendering_configuration->add_mdl_path( mdl_path) == 0);
051 
052     // Load the FreeImage, Iray Photoreal, and cloud render plugins.
053     mi::base::Handle<mi::neuraylib::IPlugin_configuration> plugin_configuration(
054         neuray->get_api_component<mi::neuraylib::IPlugin_configuration>());
055 #ifndef MI_PLATFORM_WINDOWS
056     check_success( plugin_configuration->load_plugin_library( "freeimage.so") == 0);
057     check_success( plugin_configuration->load_plugin_library( "libiray.so") == 0);
058     check_success( plugin_configuration->load_plugin_library( "cloud_render_server.so") == 0);
059 #else
060     check_success( plugin_configuration->load_plugin_library( "freeimage.dll") == 0);
061     check_success( plugin_configuration->load_plugin_library( "libiray.dll") == 0);
062     check_success( plugin_configuration->load_plugin_library( "cloud_render_server.dll") == 0);
063 #endif
064 }
065 
066 int main( int argc, char* argv[])
067 {
068     // Collect command line parameters
069     if( argc != 4) {
070         fprintf( stderr,
071             "Usage: example_bridge_server <mdl_path> <path_to_disk_cache> <listen_address>\n");
072         keep_console_open();
073         return EXIT_FAILURE;
074     }
075     const char* mdl_path        = argv[1];
076     const char* disk_cache_path = argv[2];
077     const char* listen_address  = argv[3];
078 
079     // Access the neuray library
080     mi::base::Handle<mi::neuraylib::INeuray> neuray( load_and_get_ineuray());
081     check_success( neuray.is_valid_interface());
082 
083     // Configure the neuray library
084     configuration( neuray, mdl_path, disk_cache_path, listen_address);
085 
086     // Start the neuray library
087     check_success( neuray->start() == 0);
088 
089     // Prepare to listen to bridge clients
090     run_bridge_server( neuray);
091 
092     // Shut down the neuray library
093     check_success( neuray->shutdown() == 0);
094     neuray = 0;
095 
096     // Unload the neuray library
097     check_success( unload());
098 
099     keep_console_open();
100     return EXIT_SUCCESS;
101 }

example_bridge_client.cpp

001 /******************************************************************************
002  * © 1986, 2014 NVIDIA Corporation. All rights reserved.
003  *****************************************************************************/
004 
005 // examples/example_bridge_client.cpp
006 //
007 // Connects to an Iray Bridge server, uploads a scene, makes a snapshot, and asks the server to
008 // render it.
009 //
010 // The example expects the following command line argument:
011 //
012 //   example_bridge_client <scene_file> <bridge_server_address>
013 //
014 // scene_file             the path to a scene file
015 // mdl_path               to the MDL modules, e.g., iray-<version>/mdl
016 // bridge_server_address  address of the bridge server on the form <ip:port>
017 //
018 // The rendered image is written to a file named "example_bridge_rendering.png".
019 
020 #include <cstdio>
021 
022 #include <mi/neuraylib.h>
023 
024 // Include code shared by all examples.
025 #include "example_shared.h"
026 // Include an implementation of IRender_target.
027 #include "example_render_target_simple.h"
028 
029 // Save snapshot ready callback implementation.
030 class Save_snapshot_ready_callback :
031     public mi::base::Interface_implement<mi::neuraylib::IRemote_ready_callback>
032 {
033 public:
034     void ready( mi::Sint32 /*async_token*/, mi::Sint32 error_code, const char* /*file_name*/)
035     {
036         if( error_code == 0)
037             fprintf( stderr, "Successfully created cb snapshot.\n");
038         else
039             fprintf( stderr, "Failed to create cb snapshot.\n");
040         m_cond.signal();
041     }
042 
043     void wait_for_commit()
044     {
045         m_cond.wait();
046     }
047 
048 private:
049     mi::base::Condition m_cond;
050 };
051 
052 // Progress callback implementation.
053 class Progress_callback : public mi::base::Interface_implement<mi::neuraylib::IProgress_callback>
054 {
055 public:
056     void progress( mi::Float64 value, const char* area, const char* message)
057     {
058         fprintf( stderr, "Progress: %.4f %s %s\n", value, area, message);
059     }
060 };
061 
062 void configuration( mi::base::Handle<mi::neuraylib::INeuray> neuray,
063                     const char* mdl_path,
064                     const char* bridge_server_address)
065 {
066     // Configure the Remote server
067     mi::base::Handle<mi::neuraylib::IRemote_configuration> remote_configuration(
068         neuray->get_api_component<mi::neuraylib::IRemote_configuration>());
069     check_success( remote_configuration.is_valid_interface());
070     check_success( remote_configuration->set_remote_address( bridge_server_address) == 0);
071 
072     // Set the search path for .mdl files.
073     mi::base::Handle<mi::neuraylib::IRendering_configuration> rendering_configuration(
074         neuray->get_api_component<mi::neuraylib::IRendering_configuration>());
075     check_success( rendering_configuration.is_valid_interface());
076     check_success( rendering_configuration->add_mdl_path( mdl_path) == 0);
077 
078     // Load the FreeImage, cloud render, and .mi importer plugins.
079     mi::base::Handle<mi::neuraylib::IPlugin_configuration> plugin_configuration(
080         neuray->get_api_component<mi::neuraylib::IPlugin_configuration>());
081 #ifndef MI_PLATFORM_WINDOWS
082     check_success( plugin_configuration->load_plugin_library( "freeimage.so") == 0);
083     check_success( plugin_configuration->load_plugin_library( "cloud_render.so") == 0);
084     check_success( plugin_configuration->load_plugin_library( "mi_importer.so") == 0);
085 #else
086     check_success( plugin_configuration->load_plugin_library( "freeimage.dll") == 0);
087     check_success( plugin_configuration->load_plugin_library( "cloud_render.dll") == 0);
088     check_success( plugin_configuration->load_plugin_library( "mi_importer.dll") == 0);
089 #endif
090 }
091 
092 void import_and_store_scene( mi::base::Handle<mi::neuraylib::INeuray> neuray,
093                              const char* scene_file)
094 {
095     // Get the database, the global scope, which is the root for all transactions,
096     // and create a transaction.
097     mi::base::Handle<mi::neuraylib::IDatabase> database
098         (neuray->get_api_component<mi::neuraylib::IDatabase>());
099     check_success( database.is_valid_interface());
100     mi::base::Handle<mi::neuraylib::IScope> scope( database->get_global_scope());
101     mi::base::Handle<mi::neuraylib::ITransaction> transaction( scope->create_transaction());
102     check_success( transaction.is_valid_interface());
103 
104     // Import the scene file
105     mi::base::Handle<mi::neuraylib::IImport_api> import_api(
106         neuray->get_api_component<mi::neuraylib::IImport_api>());
107     check_success( import_api.is_valid_interface());
108     mi::base::Handle<const mi::IString> uri( import_api->convert_filename_to_uri( scene_file));
109     mi::base::Handle<const mi::IImport_result> import_result(
110         import_api->import_elements( transaction.get(), uri->get_c_str()));
111     check_success( import_result->get_error_number() == 0);
112 
113     // Create the scene object
114     mi::base::Handle<mi::neuraylib::IScene> scene(
115         transaction->create<mi::neuraylib::IScene>("Scene"));
116     check_success( scene.is_valid_interface());
117     scene->set_rootgroup(       import_result->get_rootgroup());
118     scene->set_options(         import_result->get_options());
119     scene->set_camera_instance( import_result->get_camera_inst());
120 
121     // And store it in the database
122     transaction->store( scene.get(), "the_scene");
123     scene = 0;
124     transaction->commit();
125 }
126 
127 void rendering( mi::base::Handle<mi::neuraylib::INeuray> neuray)
128 {
129     // Get the database, the global scope, which is the root for all transactions,
130     // and create a transaction.
131     mi::base::Handle<mi::neuraylib::IDatabase> database(
132         neuray->get_api_component<mi::neuraylib::IDatabase>());
133     check_success( database.is_valid_interface());
134     mi::base::Handle<mi::neuraylib::IScope> scope( database->get_global_scope());
135     mi::base::Handle<mi::neuraylib::ITransaction> transaction( scope->create_transaction());
136     check_success( transaction.is_valid_interface());
137 
138     // Create the render context using the iray_cloud render mode.
139     mi::base::Handle<mi::neuraylib::IScene> scene(
140         transaction->edit<mi::neuraylib::IScene>( "the_scene"));
141     mi::base::Handle<mi::neuraylib::IRender_context> render_context(
142         scene->create_render_context( transaction.get(), "iray_cloud"));
143     check_success( render_context.is_valid_interface());
144     mi::base::Handle<mi::IString> scheduler_mode( transaction->create<mi::IString>());
145     scheduler_mode->set_c_str( "batch");
146     render_context->set_option( "scheduler_mode", scheduler_mode.get());
147     mi::base::Handle<mi::IString> video_format( transaction->create<mi::IString>());
148     video_format->set_c_str( "jpg");
149     render_context->set_option( "video_format", video_format.get());
150 
151     scene = 0;
152 
153     // Create the render target and render the scene
154     mi::base::Handle<mi::neuraylib::IImage_api> image_api(
155         neuray->get_api_component<mi::neuraylib::IImage_api>());
156     mi::base::Handle<mi::neuraylib::IRender_target> render_target(
157         new Render_target( image_api.get(), "Color", 512, 384));
158     check_success( render_context->render( transaction.get(), render_target.get(), 0) >= 0);
159 
160     // Write the image to disk
161     mi::base::Handle<mi::neuraylib::IExport_api> export_api(
162         neuray->get_api_component<mi::neuraylib::IExport_api>());
163     check_success( export_api.is_valid_interface());
164     mi::base::Handle<mi::neuraylib::ICanvas> canvas( render_target->get_canvas( 0));
165     export_api->export_canvas( "file:example_bridge_client.png", canvas.get());
166 
167     transaction->commit();
168 }
169 
170 void make_snapshot( mi::base::Handle<mi::neuraylib::INeuray> neuray)
171 {
172     // Get the global scope, which is the root for all transactions,
173     // and create a transaction.
174     mi::base::Handle<mi::neuraylib::IDatabase> database(
175         neuray->get_api_component<mi::neuraylib::IDatabase>());
176     mi::base::Handle<mi::neuraylib::IScope> scope( database->get_global_scope());
177     mi::base::Handle<mi::neuraylib::ITransaction> transaction( scope->create_transaction());
178 
179     // Get the Remote client interface
180     mi::base::Handle<mi::neuraylib::IRemote_client> bridge_client(
181         neuray->get_api_component<mi::neuraylib::IRemote_client>());
182     check_success( bridge_client.is_valid_interface());
183 
184     mi::base::Handle<Progress_callback> progress( new Progress_callback());
185     mi::base::Handle<Save_snapshot_ready_callback> ready( new Save_snapshot_ready_callback());
186 
187     check_success( bridge_client->create_remote_snapshot(
188         transaction.get(), "the_scene", "cb_name_on_server.cb", ready.get(), progress.get()) >= 0);
189 
190     // Wait for the ready callback.
191     ready->wait_for_commit();
192 
193     transaction->commit();
194 }
195 
196 int main( int argc, char* argv[])
197 {
198     // Collect command line parameters
199     if( argc != 4) {
200         fprintf( stderr,
201             "Usage: example_bridge_client <scene_file> <mdl_path> <bridge_server_address>\n");
202         keep_console_open();
203         return EXIT_FAILURE;
204     }
205     const char* scene_file            = argv[1];
206     const char* mdl_path              = argv[2];
207     const char* bridge_server_address = argv[3];
208 
209     // Access the neuray library
210     mi::base::Handle<mi::neuraylib::INeuray> neuray( load_and_get_ineuray());
211     check_success( neuray.is_valid_interface());
212 
213     // Configure the neuray library
214     configuration( neuray, mdl_path, bridge_server_address);
215 
216     // Start the neuray library
217     check_success( neuray->start() == 0);
218 
219     // Import the scene into the DB
220     import_and_store_scene( neuray, scene_file);
221 
222     // Upload scene and render in the cloud, then export the rendered image to disk
223     rendering( neuray);
224 
225     // Make a snapshot of the scene on the bridge server
226     make_snapshot( neuray);
227 
228     // Shut down the neuray library
229     check_success( neuray->shutdown() == 0);
230     neuray = 0;
231 
232     // Unload the neuray library
233     check_success( unload());
234 
235     keep_console_open();
236     return EXIT_SUCCESS;
237 }