Impl(
        Project&            project,
        const ParamArray&   params,
        const SearchPaths&  resource_search_paths)
      : m_project(project)
      , m_params(params)
      , m_resource_search_paths(resource_search_paths)
      , m_serial_renderer_controller(nullptr)
      , m_serial_tile_callback_factory(nullptr)
      , m_display(nullptr)
    {
        m_error_handler = new OIIOErrorHandler();
#ifndef NDEBUG
        m_error_handler->verbosity(OIIO::ErrorHandler::VERBOSE);
#endif

        RENDERER_LOG_DEBUG("creating oiio texture system...");
        m_texture_system = OIIOTextureSystemFactory::create(false);
        m_texture_system->attribute("automip", 0);
        m_texture_system->attribute("accept_untiled", 1);
        m_texture_system->attribute("accept_unmipped", 1);
        m_texture_system->attribute("gray_to_rgb", 1);
        m_texture_system->attribute("latlong_up", "y");
        m_texture_system->attribute("flip_t", 1);

        m_renderer_services = new RendererServices(
            m_project,
            reinterpret_cast<OIIO::TextureSystem&>(*m_texture_system));

        RENDERER_LOG_DEBUG("creating osl shading system...");
        m_shading_system =
            OSLShadingSystemFactory::create(
                m_renderer_services,
                m_texture_system,
                m_error_handler);
        m_shading_system->attribute("lockgeom", 1);
        m_shading_system->attribute("colorspace", "Linear");
        m_shading_system->attribute("commonspace", "world");
        m_shading_system->attribute("statistics:level", 1);
        m_shading_system->attribute(
            "raytypes",
            OSL::TypeDesc(
                OSL::TypeDesc::STRING,
                static_cast<int>(VisibilityFlags::Count)),
            VisibilityFlags::Names);
#ifndef NDEBUG
        m_shading_system->attribute("compile_report", 1);
        m_shading_system->attribute("countlayerexecs", 1);
        m_shading_system->attribute("clearmemory", 1);
#endif

        // Register appleseed's closures into OSL's shading system.
        register_closures(*m_shading_system);
    }
Beispiel #2
0
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;
}