@@ -838,11 +838,12 @@ class FunctionTreeTracker {
838838 std::vector<Position> m_function_stack;
839839 std::vector<Position> m_before_if_block_stack;
840840 std::vector<Position> m_after_if_block_stack;
841+ std::vector<int > m_loop_depth_stack;
841842
842843public:
843844 OSL_FORCEINLINE FunctionTreeTracker () : m_top_of_stack(end_pos())
844845 {
845- push_function_call ();
846+ push_function_call (0 );
846847 }
847848
848849 FunctionTreeTracker (const FunctionTreeTracker&) = delete ;
@@ -977,11 +978,12 @@ class FunctionTreeTracker {
977978
978979 OSL_FORCEINLINE Iterator end () const { return Iterator (*this , end_pos ()); }
979980
980- OSL_FORCEINLINE void push_function_call ()
981+ OSL_FORCEINLINE void push_function_call (int loop_depth_at_function )
981982 {
982983 OSL_DEV_ONLY (std::cout << " DependencyTreeTracker push_function_call"
983984 << std::endl);
984985 m_function_stack.push_back (m_top_of_stack);
986+ m_loop_depth_stack.push_back (loop_depth_at_function);
985987 }
986988
987989 OSL_FORCEINLINE void push_if_block ()
@@ -1062,7 +1064,16 @@ class FunctionTreeTracker {
10621064
10631065 OSL_FORCEINLINE Position top_pos () const { return m_top_of_stack; }
10641066
1065- OSL_FORCEINLINE void pop_function_call ()
1067+ OSL_FORCEINLINE int loop_depth_at_start_of_call ()
1068+ {
1069+ if (m_loop_depth_stack.empty ()) {
1070+ return 0 ;
1071+ } else {
1072+ return m_loop_depth_stack.back ();
1073+ }
1074+ }
1075+
1076+ OSL_FORCEINLINE void pop_function_call (int loop_depth_at_function)
10661077 {
10671078 OSL_DEV_ONLY (std::cout << " DependencyTreeTracker pop_function_call"
10681079 << std::endl);
@@ -1090,6 +1101,9 @@ class FunctionTreeTracker {
10901101 process_exit (early_out.dtt_pos );
10911102 }
10921103 }
1104+
1105+ OSL_ASSERT (m_loop_depth_stack.back () == loop_depth_at_function);
1106+ m_loop_depth_stack.pop_back ();
10931107 }
10941108};
10951109
@@ -1214,8 +1228,11 @@ class LoopStack {
12141228
12151229 std::vector<LoopInfo> m_loop_info_by_depth;
12161230
1231+ bool is_inside_loop () const { return depth () != 0 ; }
1232+
12171233public:
1218- bool is_inside_loop () const { return !m_loop_info_by_depth.empty (); }
1234+ int depth () const { return m_loop_info_by_depth.size (); }
1235+
12191236
12201237 int current_loop_op_index () const
12211238 {
@@ -1603,7 +1620,7 @@ struct Analyzer {
16031620
16041621 OSL_NOINLINE void make_loops_control_flow_depend_on_early_out_conditions ()
16051622 {
1606- // Need change the loop control flow which is dependent upon
1623+ // Need to change the loop control flow which is dependent upon
16071624 // a conditional. By making a circular dependency between the this
16081625 // [return|exit|break|continue] operation and the conditionals value,
16091626 // any varying values in the conditional controlling
@@ -1986,9 +2003,11 @@ struct Analyzer {
19862003 // as the current block, there was no conditionals involved
19872004 OSL_DEV_ONLY (std::cout << " FUNCTION CALL BLOCK BEGIN"
19882005 << std::endl);
1989- m_execution_scope_stack.push_function_call ();
2006+ m_execution_scope_stack.push_function_call (
2007+ m_loop_stack.depth ());
19902008 discover_symbols_between (op_index + 1 , opcode.jump (0 ));
1991- m_execution_scope_stack.pop_function_call ();
2009+ m_execution_scope_stack.pop_function_call (
2010+ m_loop_stack.depth ());
19922011 OSL_DEV_ONLY (std::cout << " FUNCTION CALL BLOCK END"
19932012 << std::endl);
19942013
@@ -2020,12 +2039,16 @@ struct Analyzer {
20202039 m_execution_scope_stack.process_return (
20212040 m_conditional_symbol_stack.top_pos ());
20222041
2023- // The return will need change the loop control flow which is dependent upon
2042+ // IF AND ONLY IF, the current loop control exists inside
2043+ // the current function, because the return should only early
2044+ // out of those loops, not any higher in the call stack.
2045+ // The return will need to change the loop control flow which is dependent upon
20242046 // a conditional. By making a circular dependency between the return operation
20252047 // and the conditionals value, any varying values in the conditional controlling
20262048 // the return should flow back to the loop control variable, which might need to
20272049 // be varying so allow lanes to terminate the loop independently
2028- if (m_loop_stack.is_inside_loop ()) {
2050+ if (m_loop_stack.depth ()
2051+ > m_execution_scope_stack.loop_depth_at_start_of_call ()) {
20292052 make_loops_control_flow_depend_on_early_out_conditions ();
20302053 }
20312054 }
@@ -2037,12 +2060,18 @@ struct Analyzer {
20372060 m_execution_scope_stack.process_exit (
20382061 m_conditional_symbol_stack.top_pos ());
20392062
2040- // The exit will need change the loop control flow which is dependent upon
2063+ // IF AND ONLY IF, the current loop control exists inside
2064+ // the current function, because the return should only early
2065+ // out of those loops, not any higher in the call stack.
2066+ // A different mechanism will look for early outs when
2067+ // unwinding up the callstack.
2068+ // The exit will need to change the loop control flow which is dependent upon
20412069 // a conditional. By making a circular dependency between the exit operation
20422070 // and the conditionals value, any varying values in the conditional controlling
20432071 // the exit should flow back to the loop control variable, which might need to
20442072 // be varying so allow lanes to terminate the loop independently
2045- if (m_loop_stack.is_inside_loop ()) {
2073+ if (m_loop_stack.depth ()
2074+ > m_execution_scope_stack.loop_depth_at_start_of_call ()) {
20462075 make_loops_control_flow_depend_on_early_out_conditions ();
20472076 }
20482077 }
@@ -2095,6 +2124,10 @@ struct Analyzer {
20952124 || symbol_to_be_varying->typespec ().is_closure ()
20962125 || symbol_to_be_varying->connected ()
20972126 || symbol_to_be_varying->connected_down ());
2127+ OSL_DEV_ONLY (std::cout << " <<<< make_varying symbol: "
2128+ << symbol_to_be_varying->unmangled ().c_str ()
2129+ << " force=" << force << std::endl);
2130+
20982131 symbol_to_be_varying->make_varying ();
20992132 auto range = m_symbols_dependent_upon.equal_range (
21002133 symbol_to_be_varying);
@@ -2107,6 +2140,9 @@ struct Analyzer {
21072140 recursively_mark_varying (dependent_symbol);
21082141 }
21092142 };
2143+ OSL_DEV_ONLY (std::cout << " >>>> end make_varying symbol: "
2144+ << symbol_to_be_varying->unmangled ().c_str ()
2145+ << std::endl);
21102146 }
21112147 };
21122148
@@ -2639,6 +2675,8 @@ struct Analyzer {
26392675
26402676 OSL_NOINLINE void push_varying_of_shader_globals ()
26412677 {
2678+ OSL_DEV_ONLY (std::cout << " push_varying_of_shader_globals begin"
2679+ << std::endl);
26422680 for (auto && s : inst ()->symbols ()) {
26432681 if (s.symtype () == SymTypeGlobal) {
26442682 // TODO: now that symbol has is_uniform()
@@ -2659,10 +2697,14 @@ struct Analyzer {
26592697 // so force their dependents to get marked
26602698 recursively_mark_varying (sym_ptr, true /* force*/ );
26612699 }
2700+ OSL_DEV_ONLY (std::cout << " push_varying_of_shader_globals end"
2701+ << std::endl);
26622702 }
26632703
26642704 OSL_NOINLINE void make_renderer_outputs_varying ()
26652705 {
2706+ OSL_DEV_ONLY (std::cout << " make_renderer_outputs_varying begin"
2707+ << std::endl);
26662708 // Mark all output parameters as varying to catch
26672709 // output parameters written to by uniform variables,
26682710 // as nothing would have made them varying, however as
@@ -2679,10 +2721,14 @@ struct Analyzer {
26792721 }
26802722 }
26812723 }
2724+ OSL_DEV_ONLY (std::cout << " make_renderer_outputs_varying end"
2725+ << std::endl);
26822726 }
26832727
26842728 OSL_NOINLINE void make_interpolated_parameters_varying ()
26852729 {
2730+ OSL_DEV_ONLY (std::cout << " make_interpolated_parameters_varying begin"
2731+ << std::endl);
26862732 // Mark all interpolated parameters as varying,
26872733 // As we expect interpolated data, get_userdata will
26882734 // only provide varying values, so we must mark
@@ -2694,10 +2740,13 @@ struct Analyzer {
26942740 recursively_mark_varying (&s);
26952741 }
26962742 }
2743+ OSL_DEV_ONLY (std::cout << " make_interpolated_parameters_varying end"
2744+ << std::endl);
26972745 }
26982746
26992747 OSL_NOINLINE void make_closures_varying ()
27002748 {
2749+ OSL_DEV_ONLY (std::cout << " make_closures_varying begin" << std::endl);
27012750 // We assume that closures are always stored as varying pointers
27022751 FOREACH_SYM (Symbol & s, inst ())
27032752 {
@@ -2707,6 +2756,7 @@ struct Analyzer {
27072756 recursively_mark_varying (&s);
27082757 }
27092758 }
2759+ OSL_DEV_ONLY (std::cout << " make_closures_varying end" << std::endl);
27102760 }
27112761
27122762 OSL_NOINLINE void push_varying_of_upstream_connections ()
0 commit comments