void
ShaderInstance::compute_run_lazily (const ShaderGroup &group)
{
    if (shadingsys().m_lazylayers) {
        // lazylayers option turned on: unconditionally run shaders with no
        // outgoing connections ("root" nodes, including the last in the
        // group) or shaders that alter global variables (unless
        // 'lazyglobals' is turned on).
        if (shadingsys().m_lazyglobals) {
            if (group[group.nlayers()-1] == this)
                run_lazily (false);  // force run of last group
            else
                run_lazily ((outgoing_connections() && ! renderer_outputs())
                            || empty_instance() || merged_unused());
        }
        else
            run_lazily (outgoing_connections() && ! writes_globals()
                        && ! renderer_outputs());
#if 0
        // Suggested warning below... but are there use cases where people
        // want these to run (because they will extract the results they
        // want from output params)?
        if (! outgoing_connections() && ! empty_instance() &&
                ! writes_globals() && ! renderer_outputs())
            shadingsys().warning ("Layer \"%s\" (shader %s) will run even though it appears to have no used results",
                                  layername(), shadername());
#endif
    } else {
        // lazylayers option turned off: never run lazily
        run_lazily (false);
    }
}
bool
ShadingContext::execute (ShaderUse use, ShaderGroup &sgroup,
                         ShaderGlobals &ssg, bool run)
{
    DASSERT (use == ShadUseSurface);  // FIXME
    m_curuse = use;
    m_attribs = &sgroup;

    // Optimize if we haven't already
    if (sgroup.nlayers()) {
        sgroup.start_running ();
        if (! sgroup.optimized()) {
            shadingsys().optimize_group (sgroup);
            if (shadingsys().m_greedyjit && shadingsys().m_groups_to_compile_count) {
                // If we are greedily JITing, optimize/JIT everything now
                shadingsys().optimize_all_groups ();
            }
        }
        if (sgroup.does_nothing())
            return false;
    } else {
       // empty shader - nothing to do!
       return false;
    }

    // Allocate enough space on the heap
    size_t heap_size_needed = sgroup.llvm_groupdata_size();
    if (heap_size_needed > m_heap.size()) {
        if (shadingsys().debug())
            shadingsys().info ("  ShadingContext %p growing heap to %llu",
                               this, (unsigned long long) heap_size_needed);
        m_heap.resize (heap_size_needed);
    }
    // Zero out the heap memory we will be using
    if (shadingsys().m_clearmemory)
        memset (&m_heap[0], 0, heap_size_needed);

    // Set up closure storage
    m_closure_pool.clear();

    // Clear the message blackboard
    m_messages.clear ();

    // Clear miscellaneous scratch space
    m_scratch_pool.clear ();

    if (run) {
        ssg.context = this;
        ssg.Ci = NULL;
        RunLLVMGroupFunc run_func = sgroup.llvm_compiled_version();
        DASSERT (run_func);
        DASSERT (sgroup.llvm_groupdata_size() <= m_heap.size());
        run_func (&ssg, &m_heap[0]);
    }
    return true;
}
bool
ShadingContext::execute (ShaderGroup &sgroup, ShaderGlobals &ssg, bool run)
{
    m_attribs = &sgroup;

    // Optimize if we haven't already
    if (sgroup.nlayers()) {
        sgroup.start_running ();
        if (! sgroup.optimized()) {
            shadingsys().optimize_group (sgroup);
            if (shadingsys().m_greedyjit && shadingsys().m_groups_to_compile_count) {
                // If we are greedily JITing, optimize/JIT everything now
                shadingsys().optimize_all_groups ();
            }
        }
        if (sgroup.does_nothing())
            return false;
    } else {
       // empty shader - nothing to do!
       return false;
    }

    int profile = shadingsys().m_profile;
    OIIO::Timer timer (profile);

    // Allocate enough space on the heap
    size_t heap_size_needed = sgroup.llvm_groupdata_size();
    if (heap_size_needed > m_heap.size()) {
        if (shadingsys().debug())
            info ("  ShadingContext %p growing heap to %llu",
                  this, (unsigned long long) heap_size_needed);
        m_heap.resize (heap_size_needed);
    }
    // Zero out the heap memory we will be using
    if (shadingsys().m_clearmemory)
        memset (&m_heap[0], 0, heap_size_needed);

    // Set up closure storage
    m_closure_pool.clear();

    // Clear the message blackboard
    m_messages.clear ();

    // Clear miscellaneous scratch space
    m_scratch_pool.clear ();

    if (run) {
        ssg.context = this;
        ssg.renderer = renderer();
        ssg.Ci = NULL;
        RunLLVMGroupFunc run_func = sgroup.llvm_compiled_version();
        DASSERT (run_func);
        DASSERT (sgroup.llvm_groupdata_size() <= m_heap.size());
        run_func (&ssg, &m_heap[0]);
    }

    // Process any queued up error messages, warnings, printfs from shaders
    process_errors ();

    if (profile) {
        long long ticks = timer.ticks();
        shadingsys().m_stat_total_shading_time_ticks += ticks;
        sgroup.m_stat_total_shading_time_ticks += ticks;
    }

    return true;
}