|
21 | 21 | #include "renderDelegate.h" |
22 | 22 | #include "tokens.h" |
23 | 23 |
|
| 24 | +#include <pxr/imaging/hd/extComputation.h> |
| 25 | +#include <pxr/imaging/hd/version.h> |
24 | 26 | #include <pxr/usdImaging/usdImaging/delegate.h> |
| 27 | +#if !defined(HD_API_VERSION) || HD_API_VERSION < 49 |
| 28 | +#include <pxr/imaging/hd/extCompCpuComputation.h> |
| 29 | +#else |
| 30 | +#include <pxr/imaging/hdSt/extCompCpuComputation.h> |
| 31 | +#endif |
| 32 | + |
| 33 | +#include <algorithm> |
| 34 | +#include <cstring> |
| 35 | +#include <limits> |
25 | 36 |
|
26 | 37 | #ifdef MAYA_HAS_DISPLAY_LAYER_API |
27 | 38 | #include <mayaUsd/utils/util.h> |
@@ -405,6 +416,12 @@ HdReprSharedPtr MayaUsdRPrim::_InitReprCommon( |
405 | 416 |
|
406 | 417 | void MayaUsdRPrim::_PropagateDirtyBitsCommon(HdDirtyBits& bits, const ReprVector& reprs) const |
407 | 418 | { |
| 419 | + // This supports UsdSkel affecting the points position when the transform is dirty. |
| 420 | + // Done before the propagation below so the draw items see the added DirtyPoints too. |
| 421 | + if (bits & HdChangeTracker::DirtyTransform && _pointsFromSkel) { |
| 422 | + bits |= HdChangeTracker::DirtyPoints; |
| 423 | + } |
| 424 | + |
408 | 425 | if (bits & HdChangeTracker::AllDirty) { |
409 | 426 | // RPrim is dirty, propagate dirty bits to all draw items. |
410 | 427 | RenderItemFunc setDirtyBitsToItem = [bits](HdVP2DrawItem::RenderItemData& renderItemData) { |
@@ -679,6 +696,84 @@ void MayaUsdRPrim::_UpdatePrimvarSourcesGeneric( |
679 | 696 | } |
680 | 697 | } |
681 | 698 |
|
| 699 | +void MayaUsdRPrim::_UpdateComputedPrimvarSourcesGeneric( |
| 700 | + HdSceneDelegate* sceneDelegate, |
| 701 | + const TfTokenVector& requiredPrimvars, |
| 702 | + HdRprim& refThis, |
| 703 | + UpdatePrimvarInfoFunc& updatePrimvarInfo) |
| 704 | +{ |
| 705 | +#if !defined(HD_API_VERSION) || HD_API_VERSION < 49 |
| 706 | + using HdStExtCompCpuComputation = HdExtCompCpuComputation; |
| 707 | + using HdStExtCompCpuComputationSharedPtr = HdExtCompCpuComputationSharedPtr; |
| 708 | +#endif |
| 709 | + |
| 710 | + // Recomputed from scratch on every call, so that a prim which stops being skinned |
| 711 | + // (its binding removed, say) goes back to reading the authored points. |
| 712 | + _pointsFromSkel = false; |
| 713 | + |
| 714 | + const SdfPath& id = refThis.GetId(); |
| 715 | + |
| 716 | + // The compPrimvars are a description of the link between the compute system and |
| 717 | + // what we need to draw. |
| 718 | + HdExtComputationPrimvarDescriptorVector compPrimvars |
| 719 | + = sceneDelegate->GetExtComputationPrimvarDescriptors(id, HdInterpolationVertex); |
| 720 | + if (compPrimvars.empty()) { |
| 721 | + return; |
| 722 | + } |
| 723 | + |
| 724 | + const HdRenderIndex& renderIndex = sceneDelegate->GetRenderIndex(); |
| 725 | + |
| 726 | + for (const auto& primvarName : requiredPrimvars) { |
| 727 | + auto result |
| 728 | + = std::find_if(compPrimvars.begin(), compPrimvars.end(), [&](const auto& compPrimvar) { |
| 729 | + return compPrimvar.name == primvarName; |
| 730 | + }); |
| 731 | + // if there is no compute for the given required primvar then we're done! |
| 732 | + if (result == compPrimvars.end()) |
| 733 | + continue; |
| 734 | + HdExtComputationPrimvarDescriptor compPrimvar = *result; |
| 735 | + |
| 736 | + // The compPrimvar has the Id of the compute the data comes from, and the output |
| 737 | + // of the compute which contains the data. |
| 738 | + HdExtComputation const* sourceComp |
| 739 | + = static_cast<HdExtComputation const*>(renderIndex.GetSprim( |
| 740 | + HdPrimTypeTokens->extComputation, compPrimvar.sourceComputationId)); |
| 741 | + if (!sourceComp || sourceComp->GetElementCount() <= 0) |
| 742 | + continue; |
| 743 | + |
| 744 | + // Create the HdStExtCompCpuComputation objects necessary to resolve the computation. |
| 745 | + HdStExtCompCpuComputationSharedPtr cpuComputation; |
| 746 | + HdBufferSourceSharedPtrVector sources; |
| 747 | + // There is a possible data race calling CreateComputation, see |
| 748 | + // https://github.com/PixarAnimationStudios/USD/issues/1742 |
| 749 | + cpuComputation |
| 750 | + = HdStExtCompCpuComputation::CreateComputation(sceneDelegate, *sourceComp, &sources); |
| 751 | + |
| 752 | + // Immediately resolve the computation so we can fill in the primvar info. |
| 753 | + for (HdBufferSourceSharedPtr& source : sources) { |
| 754 | + source->Resolve(); |
| 755 | + } |
| 756 | + |
| 757 | + // Pull the result out of the compute and save it into the local primvar info. |
| 758 | + size_t outputIndex |
| 759 | + = cpuComputation->GetOutputIndex(compPrimvar.sourceComputationOutputName); |
| 760 | + // INVALID_OUTPUT_INDEX is declared static in USD, can't access here so re-declare |
| 761 | + constexpr size_t INVALID_OUTPUT_INDEX = std::numeric_limits<size_t>::max(); |
| 762 | + if (INVALID_OUTPUT_INDEX == outputIndex) { |
| 763 | + // Don't make the points dirty |
| 764 | + continue; |
| 765 | + } |
| 766 | + |
| 767 | + updatePrimvarInfo( |
| 768 | + primvarName, cpuComputation->GetOutputByIndex(outputIndex), HdInterpolationVertex); |
| 769 | + |
| 770 | + // Record that the points are coming from the computation. |
| 771 | + if (primvarName == HdTokens->points) { |
| 772 | + _pointsFromSkel = true; |
| 773 | + } |
| 774 | + } |
| 775 | +} |
| 776 | + |
682 | 777 | #ifdef MAYA_HAS_DISPLAY_LAYER_API |
683 | 778 | void MayaUsdRPrim::_ProcessDisplayLayerModes( |
684 | 779 | const MObject& displayLayerObj, |
@@ -838,6 +933,64 @@ void MayaUsdRPrim::_SyncDisplayLayerModesInstanced(SdfPath const& id, unsigned i |
838 | 933 | } |
839 | 934 | } |
840 | 935 |
|
| 936 | +void MayaUsdRPrim::_SyncEndCommon( |
| 937 | + HdRprim& refThis, |
| 938 | + HdSceneDelegate* delegate, |
| 939 | + HdDirtyBits* dirtyBits, |
| 940 | + TfToken const& reprToken, |
| 941 | + HdRprimSharedData& sharedData, |
| 942 | + ReprVector const& reprs) |
| 943 | +{ |
| 944 | +#if PXR_VERSION > 2111 |
| 945 | + const TfToken& renderTag = refThis.GetRenderTag(); |
| 946 | +#else |
| 947 | + const TfToken& renderTag = delegate->GetRenderTag(refThis.GetId()); |
| 948 | +#endif |
| 949 | + |
| 950 | + _SyncSharedData(sharedData, delegate, dirtyBits, reprToken, refThis, reprs, renderTag); |
| 951 | + |
| 952 | + *dirtyBits = HdChangeTracker::Clean; |
| 953 | +} |
| 954 | + |
| 955 | +void MayaUsdRPrim::_RequirePrimvar(TfTokenVector& requiredPrimvars, const TfToken& primvar) |
| 956 | +{ |
| 957 | + if (std::find(requiredPrimvars.cbegin(), requiredPrimvars.cend(), primvar) |
| 958 | + == requiredPrimvars.cend()) { |
| 959 | + requiredPrimvars.push_back(primvar); |
| 960 | + } |
| 961 | +} |
| 962 | + |
| 963 | +void MayaUsdRPrim::_CommitPositionsBuffer( |
| 964 | + MHWRender::MVertexBuffer* positionsBuffer, |
| 965 | + const VtVec3fArray& points) const |
| 966 | +{ |
| 967 | + if (!positionsBuffer) { |
| 968 | + return; |
| 969 | + } |
| 970 | + |
| 971 | + const size_t numVertices = points.size(); |
| 972 | + |
| 973 | + void* bufferData = positionsBuffer->acquire(numVertices, true); |
| 974 | + if (!bufferData) { |
| 975 | + return; |
| 976 | + } |
| 977 | + |
| 978 | + memcpy(bufferData, points.cdata(), sizeof(GfVec3f) * numVertices); |
| 979 | + |
| 980 | + // Capture class member for lambda |
| 981 | + const MString& rprimId = _rprimId; |
| 982 | + |
| 983 | + _delegate->GetVP2ResourceRegistry().EnqueueCommit([positionsBuffer, bufferData, rprimId]() { |
| 984 | + MProfilingScope profilingScope( |
| 985 | + HdVP2RenderDelegate::sProfilerCategory, |
| 986 | + MProfiler::kColorC_L2, |
| 987 | + rprimId.asChar(), |
| 988 | + "CommitPositions"); |
| 989 | + |
| 990 | + positionsBuffer->commit(bufferData); |
| 991 | + }); |
| 992 | +} |
| 993 | + |
841 | 994 | void MayaUsdRPrim::_SyncSharedData( |
842 | 995 | HdRprimSharedData& sharedData, |
843 | 996 | HdSceneDelegate* delegate, |
|
0 commit comments