| 715 | } |
| 716 | |
| 717 | static TfBits |
| 718 | _FilterTimeDependentOutputs( |
| 719 | const VdfMaskedOutputVector &timeDependentInputNodeOutputs, |
| 720 | const EfTime &oldTime, |
| 721 | const EfTime &newTime) |
| 722 | { |
| 723 | TRACE_FUNCTION(); |
| 724 | |
| 725 | // One bitset per thread. |
| 726 | const size_t numInputs = timeDependentInputNodeOutputs.size(); |
| 727 | tbb::enumerable_thread_specific<TfBits> threadBits([numInputs](){ |
| 728 | return TfBits(numInputs); |
| 729 | }); |
| 730 | |
| 731 | // For each time-dependent output, figure out if the computed value actually |
| 732 | // changes between oldTime and newTime. If so, set the corresponding bit |
| 733 | // in the bit set. |
| 734 | WorkWithScopedParallelism( |
| 735 | [&numInputs, &timeDependentInputNodeOutputs, &oldTime, &newTime, |
| 736 | &threadBits](){ |
| 737 | WorkParallelForN(numInputs,[&](size_t b, size_t e){ |
| 738 | TfBits *const bits = &threadBits.local(); |
| 739 | for (size_t i = b; i != e; ++i) { |
| 740 | const VdfNode &node = |
| 741 | timeDependentInputNodeOutputs[i].GetOutput()->GetNode(); |
| 742 | const Exec_AttributeInputNode *const inputNode = |
| 743 | dynamic_cast<const Exec_AttributeInputNode*>(&node); |
| 744 | if (!inputNode || inputNode->IsTimeVarying(oldTime, newTime)) { |
| 745 | bits->Set(i); |
| 746 | } |
| 747 | } |
| 748 | }); |
| 749 | }); |
| 750 | |
| 751 | // Combine the thread-local bit sets into a single bit set and return it. |
| 752 | TfBits result(numInputs); |
| 753 | threadBits.combine_each([&result](const TfBits &bits){ |
| 754 | result |= bits; |
| 755 | }); |
| 756 | return result; |
| 757 | } |
| 758 | |
| 759 | PXR_NAMESPACE_CLOSE_SCOPE |
no test coverage detected