void TextureStore::TileSwapper::load(const TileKey& key, TileRecord& record) { // Fetch the texture container. const TextureContainer& textures = key.m_assembly_uid == ~0 ? m_scene.textures() : m_assemblies[key.m_assembly_uid]->textures(); // Fetch the texture. Texture* texture = textures.get_by_uid(key.m_texture_uid); if (m_params.m_track_tile_loading) { RENDERER_LOG_DEBUG( "loading tile (" FMT_SIZE_T ", " FMT_SIZE_T ") " "from texture \"%s\"...", key.get_tile_x(), key.get_tile_y(), texture->get_name()); } // Load the tile. record.m_tile = texture->load_tile(key.get_tile_x(), key.get_tile_y()); record.m_owners = 0; // Convert the tile to the linear RGB color space. switch (texture->get_color_space()) { case ColorSpaceLinearRGB: break; case ColorSpaceSRGB: convert_tile_srgb_to_linear_rgb(*record.m_tile); break; case ColorSpaceCIEXYZ: convert_tile_ciexyz_to_linear_rgb(*record.m_tile); break; assert_otherwise; } // Track the amount of memory used by the tile cache. m_memory_size += record.m_tile->get_memory_size(); m_peak_memory_size = max(m_peak_memory_size, m_memory_size); if (m_params.m_track_store_size) { if (m_memory_size > m_params.m_memory_limit) { RENDERER_LOG_DEBUG( "texture store size is %s, exceeding capacity %s by %s", pretty_size(m_memory_size).c_str(), pretty_size(m_params.m_memory_limit).c_str(), pretty_size(m_memory_size - m_params.m_memory_limit).c_str()); } else { RENDERER_LOG_DEBUG( "texture store size is %s, below capacity %s by %s", pretty_size(m_memory_size).c_str(), pretty_size(m_params.m_memory_limit).c_str(), pretty_size(m_params.m_memory_limit - m_memory_size).c_str()); } } }
IRendererController::Status MasterRenderer::initialize_and_render_frame_sequence() { assert(m_project.get_scene()); assert(m_project.get_frame()); // Reset the abort switch. if (m_abort_switch) m_abort_switch->clear(); #ifdef WITH_OSL // Create the error handler. OIIOErrorHandler error_handler; // While debugging, we want all possible outputs. #ifndef NDEBUG error_handler.verbosity(OIIO::ErrorHandler::VERBOSE); #endif const size_t texture_cache_size = m_params.get_optional<size_t>("texture_cache_size", 256 * 1024 * 1024); // If the texture cache size changes, we have to recreate the texture system. if (texture_cache_size != m_texture_cache_size) { m_texture_cache_size = texture_cache_size; m_texture_system.reset(); } // Create the OIIO texture system, if needed. if (!m_texture_system) { m_texture_system.reset( OIIO::TextureSystem::create(false), bind(&OIIO::TextureSystem::destroy, _1)); } // Set the texture system mem limit. m_texture_system->attribute("max_memory_MB", static_cast<float>(m_texture_cache_size / 1024)); std::string search_paths; // Skip search paths for builtin projects. if (m_project.search_paths().has_root_path()) { // Setup texture / shader search paths. // In OIIO / OSL, the path priorities are the opposite of appleseed, // so we copy the paths in reverse order. const filesystem::path root_path = m_project.search_paths().get_root_path(); if (!m_project.search_paths().empty()) { for (size_t i = 0, e = m_project.search_paths().size(); i != e; ++i) { filesystem::path p(m_project.search_paths()[e - 1 - i]); if (p.is_relative()) p = root_path / p; search_paths.append(p.string()); search_paths.append(";"); } } search_paths.append(root_path.string()); } if (!search_paths.empty()) m_texture_system->attribute("searchpath", search_paths); // TODO: set other texture system options here. // Create our renderer services. RendererServices services(m_project, *m_texture_system); // Create our OSL shading system. boost::shared_ptr<OSL::ShadingSystem> shading_system( OSL::ShadingSystem::create( &services, m_texture_system.get(), &error_handler), bind(&destroy_osl_shading_system, _1, m_texture_system.get())); if (!search_paths.empty()) shading_system->attribute("searchpath:shader", search_paths); shading_system->attribute("lockgeom", 1); shading_system->attribute("colorspace", "Linear"); shading_system->attribute("commonspace", "world"); // This array needs to be kept in sync with the ShadingRay::Type enumeration. static const char* ray_type_labels[] = { "camera", "light", "shadow", "probe", "diffuse", "glossy", "specular" }; shading_system->attribute( "raytypes", OSL::TypeDesc( OSL::TypeDesc::STRING, sizeof(ray_type_labels) / sizeof(ray_type_labels[0])), ray_type_labels); #ifndef NDEBUG // While debugging, we want all possible outputs. shading_system->attribute("debug", 1); shading_system->attribute("statistics:level", 1); shading_system->attribute("compile_report", 1); shading_system->attribute("countlayerexecs", 1); shading_system->attribute("clearmemory", 1); #endif register_closures(*shading_system); #endif // WITH_OSL // We start by binding entities inputs. This must be done before creating/updating the trace context. if (!bind_scene_entities_inputs()) return IRendererController::AbortRendering; m_project.create_aov_images(); m_project.update_trace_context(); const Scene& scene = *m_project.get_scene(); Frame& frame = *m_project.get_frame(); frame.print_settings(); const TraceContext& trace_context = m_project.get_trace_context(); // Create the texture store. TextureStore texture_store(scene, m_params.child("texture_store")); // Create the light sampler. LightSampler light_sampler(scene, m_params.child("light_sampler")); // Create the shading engine. ShadingEngine shading_engine(m_params.child("shading_engine")); // // Create a lighting engine factory. // auto_ptr<IPassCallback> pass_callback; auto_ptr<ILightingEngineFactory> lighting_engine_factory; { const string value = m_params.get_required<string>("lighting_engine", "pt"); if (value == "drt") { lighting_engine_factory.reset( new DRTLightingEngineFactory( light_sampler, m_params.child("drt"))); // todo: change to "drt_lighting_engine" -- or? } else if (value == "pt") { lighting_engine_factory.reset( new PTLightingEngineFactory( light_sampler, m_params.child("pt"))); // todo: change to "pt_lighting_engine" -- or? } else if (value == "sppm") { const SPPMParameters params(m_params.child("sppm")); SPPMPassCallback* sppm_pass_callback = new SPPMPassCallback( scene, light_sampler, trace_context, texture_store, #ifdef WITH_OSL *shading_system, #endif params); pass_callback.reset(sppm_pass_callback); lighting_engine_factory.reset( new SPPMLightingEngineFactory( *sppm_pass_callback, light_sampler, params)); } else { RENDERER_LOG_ERROR( "invalid value for \"lighting_engine\" parameter: \"%s\".", value.c_str()); return IRendererController::AbortRendering; } } // // Create a sample renderer factory. // auto_ptr<ISampleRendererFactory> sample_renderer_factory; { const string value = m_params.get_required<string>("sample_renderer", "generic"); if (value == "generic") { sample_renderer_factory.reset( new GenericSampleRendererFactory( scene, frame, trace_context, texture_store, lighting_engine_factory.get(), shading_engine, #ifdef WITH_OSL *shading_system, #endif m_params.child("generic_sample_renderer"))); } else if (value == "blank") { sample_renderer_factory.reset(new BlankSampleRendererFactory()); } else if (value == "debug") { sample_renderer_factory.reset(new DebugSampleRendererFactory()); } else { RENDERER_LOG_ERROR( "invalid value for \"sample_renderer\" parameter: \"%s\".", value.c_str()); return IRendererController::AbortRendering; } } // // Create a sample generator factory. // auto_ptr<ISampleGeneratorFactory> sample_generator_factory; { const string value = m_params.get_optional<string>("sample_generator", ""); if (value == "generic") { sample_generator_factory.reset( new GenericSampleGeneratorFactory( frame, sample_renderer_factory.get())); } else if (value == "lighttracing") { sample_generator_factory.reset( new LightTracingSampleGeneratorFactory( scene, frame, trace_context, texture_store, light_sampler, #ifdef WITH_OSL *shading_system, #endif m_params.child("lighttracing_sample_generator"))); } else if (!value.empty()) { RENDERER_LOG_ERROR( "invalid value for \"sample_generator\" parameter: \"%s\".", value.c_str()); return IRendererController::AbortRendering; } } // // Create a pixel renderer factory. // auto_ptr<IPixelRendererFactory> pixel_renderer_factory; { const string value = m_params.get_optional<string>("pixel_renderer", ""); if (value == "uniform") { pixel_renderer_factory.reset( new UniformPixelRendererFactory( sample_renderer_factory.get(), m_params.child("uniform_pixel_renderer"))); } else if (value == "adaptive") { pixel_renderer_factory.reset( new AdaptivePixelRendererFactory( frame, sample_renderer_factory.get(), m_params.child("adaptive_pixel_renderer"))); } else if (!value.empty()) { RENDERER_LOG_ERROR( "invalid value for \"pixel_renderer\" parameter: \"%s\".", value.c_str()); return IRendererController::AbortRendering; } } // // Create a shading result framebuffer factory. // auto_ptr<IShadingResultFrameBufferFactory> shading_result_framebuffer_factory; { const string value = m_params.get_optional<string>("shading_result_framebuffer", "ephemeral"); if (value == "ephemeral") { shading_result_framebuffer_factory.reset( new EphemeralShadingResultFrameBufferFactory()); } else if (value == "permanent") { shading_result_framebuffer_factory.reset( new PermanentShadingResultFrameBufferFactory(frame)); } else if (!value.empty()) { RENDERER_LOG_ERROR( "invalid value for \"shading_result_framebuffer\" parameter: \"%s\".", value.c_str()); return IRendererController::AbortRendering; } } // // Create a tile renderer factory. // auto_ptr<ITileRendererFactory> tile_renderer_factory; { const string value = m_params.get_optional<string>("tile_renderer", ""); if (value == "generic") { tile_renderer_factory.reset( new GenericTileRendererFactory( frame, pixel_renderer_factory.get(), shading_result_framebuffer_factory.get(), m_params.child("generic_tile_renderer"))); } else if (value == "blank") { tile_renderer_factory.reset(new BlankTileRendererFactory()); } else if (value == "debug") { tile_renderer_factory.reset(new DebugTileRendererFactory()); } else if (!value.empty()) { RENDERER_LOG_ERROR( "invalid value for \"tile_renderer\" parameter: \"%s\".", value.c_str()); return IRendererController::AbortRendering; } } // // Create a frame renderer. // auto_release_ptr<IFrameRenderer> frame_renderer; { const string value = m_params.get_required<string>("frame_renderer", "generic"); if (value == "generic") { ParamArray params = m_params.child("generic_frame_renderer"); copy_param(params, m_params, "rendering_threads"); frame_renderer.reset( GenericFrameRendererFactory::create( frame, tile_renderer_factory.get(), m_tile_callback_factory, pass_callback.get(), params)); } else if (value == "progressive") { ParamArray params = m_params.child("progressive_frame_renderer"); copy_param(params, m_params, "rendering_threads"); frame_renderer.reset( ProgressiveFrameRendererFactory::create( m_project, sample_generator_factory.get(), m_tile_callback_factory, params)); } else { RENDERER_LOG_ERROR( "invalid value for \"frame_renderer\" parameter: \"%s\".", value.c_str()); return IRendererController::AbortRendering; } } // Execute the main rendering loop. const IRendererController::Status status = render_frame_sequence( frame_renderer.get() #ifdef WITH_OSL , *shading_system #endif ); // Print texture store performance statistics. RENDERER_LOG_DEBUG("%s", texture_store.get_statistics().to_string().c_str()); return status; }
bool ShaderGroup::create_optimized_osl_shader_group( OSL::ShadingSystem& shading_system, IAbortSwitch* abort_switch) { if (is_valid()) return true; RENDERER_LOG_DEBUG("setting up shader group \"%s\"...", get_path().c_str()); try { OSL::ShaderGroupRef shader_group_ref = shading_system.ShaderGroupBegin(get_name()); if (shader_group_ref.get() == 0) { RENDERER_LOG_ERROR("failed to setup shader group \"%s\": ShaderGroupBegin() call failed.", get_path().c_str()); return false; } for (each<ShaderContainer> i = impl->m_shaders; i; ++i) { if (is_aborted(abort_switch)) { shading_system.ShaderGroupEnd(); return true; } if (!i->add(shading_system)) return false; } for (each<ShaderConnectionContainer> i = impl->m_connections; i; ++i) { if (is_aborted(abort_switch)) { shading_system.ShaderGroupEnd(); return true; } if (!i->add(shading_system)) return false; } if (!shading_system.ShaderGroupEnd()) { RENDERER_LOG_ERROR("failed to setup shader group \"%s\": ShaderGroupEnd() call failed.", get_path().c_str()); return false; } impl->m_shader_group_ref = shader_group_ref; get_shadergroup_closures_info(shading_system); report_has_closure("bsdf", HasBSDFs); report_has_closure("emission", HasEmission); report_has_closure("transparent", HasTransparency); report_has_closure("subsurface", HasSubsurface); report_has_closure("holdout", HasHoldout); report_has_closure("debug", HasDebug); get_shadergroup_globals_info(shading_system); report_uses_global("dPdtime", UsesdPdTime); return true; } catch (const exception& e) { RENDERER_LOG_ERROR("failed to setup shader group \"%s\": %s.", get_path().c_str(), e.what()); return false; } }
void TextureStore::TileSwapper::load(const TileKey& key, TileRecord& record) { // Fetch the texture container. const TextureContainer& textures = key.m_assembly_uid == ~0 ? m_scene.textures() : m_scene.assemblies().get_by_uid(key.m_assembly_uid)->textures(); // Fetch the texture. const size_t texture_index = key.get_texture_index(); assert(texture_index < textures.size()); Texture* texture = textures.get_by_index(texture_index); #ifdef TRACK_TILE_LOADING RENDERER_LOG_DEBUG( "loading tile (" FMT_SIZE_T ", " FMT_SIZE_T ") " "from texture \"%s\"...", key.get_tile_x(), key.get_tile_y(), texture->get_name()); #endif // Load the tile. record.m_tile = texture->load_tile(key.get_tile_x(), key.get_tile_y()); record.m_owners = 0; // Convert the tile to the linear RGB color space. switch (texture->get_color_space()) { case ColorSpaceLinearRGB: break; case ColorSpaceSRGB: convert_tile_srgb_to_linear_rgb(*record.m_tile); break; case ColorSpaceCIEXYZ: convert_tile_ciexyz_to_linear_rgb(*record.m_tile); break; assert_otherwise; } // Track the amount of memory used by the tile cache. m_memory_size += dynamic_sizeof(*record.m_tile); m_max_memory_size = max(m_max_memory_size, m_memory_size); #ifdef TRACK_CACHE_SIZE if (m_memory_size > m_memory_limit) { RENDERER_LOG_DEBUG( "texture store size is %s, exceeding capacity %s by %s", pretty_size(m_memory_size).c_str(), pretty_size(m_memory_limit).c_str(), pretty_size(m_memory_size - m_memory_limit).c_str()); } else { RENDERER_LOG_DEBUG( "texture store size is %s, below capacity %s by %s", pretty_size(m_memory_size).c_str(), pretty_size(m_memory_limit).c_str(), pretty_size(m_memory_size - m_memory_limit).c_str()); } #endif }