// // Copyright 2016 Pixar // // Licensed under the Apache License, Version 2.0 (the "Apache License") // with the following modification; you may not use this file except in // compliance with the Apache License and the following modification to it: // Section 6. Trademarks. is deleted and replaced with: // // 6. Trademarks. This License does not grant permission to use the trade // names, trademarks, service marks, or product names of the Licensor // and its affiliates, except as required to comply with Section 4(c) of // the License and to reproduce the content of the NOTICE file. // // You may obtain a copy of the Apache License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the Apache License with the above modification is // distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the Apache License for the specific // language governing permissions and limitations under the Apache License. // #ifndef PXR_IMAGING_HD_RPRIM_H #define PXR_IMAGING_HD_RPRIM_H #include "pxr/pxr.h" #include "pxr/imaging/hd/api.h" #include "pxr/imaging/hd/version.h" #include "pxr/imaging/hd/changeTracker.h" #include "pxr/imaging/hd/drawItem.h" #include "pxr/imaging/hd/rprimSharedData.h" #include "pxr/imaging/hd/repr.h" #include "pxr/imaging/hd/sceneDelegate.h" #include "pxr/imaging/hd/types.h" #include "pxr/usd/sdf/path.h" #include "pxr/base/gf/range3d.h" #include "pxr/base/arch/inttypes.h" #include #include PXR_NAMESPACE_OPEN_SCOPE class HdBufferSource; class HdDrawItem; class HdMaterial; class HdRenderIndex; class HdRenderParam; using HdReprSharedPtr = std::shared_ptr; using HdBufferSourceSharedPtr = std::shared_ptr; using HdBufferSourceSharedPtrVector = std::vector; using HdBufferSpecVector = std::vector; using HdBufferArrayRangeSharedPtr = std::shared_ptr; using HdComputationSharedPtr = std::shared_ptr; using HdComputationSharedPtrVector = std::vector; /// \class HdRprim /// /// The render engine state for a given rprim from the scene graph. All data /// access (aside from local caches) is delegated to the HdSceneDelegate. /// class HdRprim { public: HD_API HdRprim(SdfPath const& id, SdfPath const& instancerId); HD_API virtual ~HdRprim(); // ---------------------------------------------------------------------- // /// \name Rprim Hydra Engine API : Pre-Sync & Sync-Phase // ---------------------------------------------------------------------- // /// Returns the set of dirty bits that should be /// added to the change tracker for this prim, when this prim is inserted. virtual HdDirtyBits GetInitialDirtyBitsMask() const = 0; /// This function gives an Rprim the chance to "early exit" from dirty /// bit propagation, delegate sync and rprim sync altogether. It is /// a temporary measure to prevent unnecessary work, like in the case of /// invisible prims. The dirty bits in the change tracker remain the same. /// See the implementation for the finer details. HD_API bool CanSkipDirtyBitPropagationAndSync(HdDirtyBits bits) const; /// This function gives an Rprim the chance to set additional dirty bits /// based on those set in the change tracker, before passing the dirty bits /// to the scene delegate. /// It calls into _PropagateDirtyBits, which gives the Rprim an opportunity /// to specify the additional data needed to process the requested changes. /// /// The return value is the new set of dirty bits. HD_API HdDirtyBits PropagateRprimDirtyBits(HdDirtyBits bits); /// Initialize the representation of this Rprim by calling _InitRepr. /// This is called prior to dirty bit propagation & sync, the first time the /// repr is used, or when the authored representation is dirty. /// /// dirtyBits is an in/out value. It is initialized to the dirty bits /// from the change tracker. InitRepr can then set additional dirty bits /// if additional data is required from the scene delegate when this /// repr is synced. HD_API void InitRepr(HdSceneDelegate* delegate, TfToken const &reprToken, HdDirtyBits *dirtyBits); /// Pull invalidated scene data and prepare/update the renderable /// representation. /// /// This function is told which scene data to pull through the /// dirtyBits parameter. The first time it's called, dirtyBits comes /// from _GetInitialDirtyBits(), which provides initial dirty state, /// but after that it's driven by invalidation tracking in the scene /// delegate. /// /// The contract for this function is that the prim can only pull on scene /// delegate buffers that are marked dirty. Scene delegates can and do /// implement just-in-time data schemes that mean that pulling on clean /// data will be at best incorrect, and at worst a crash. /// /// This function is called in parallel from worker threads, so it needs /// to be threadsafe; calls into HdSceneDelegate are ok. /// /// \param sceneDelegate The data source for this geometry item. /// \param renderParam A render delegate object that holds rendering /// parameters that scene geometry may use. /// \param dirtyBits A specifier for which scene data has changed. /// \param reprToken The representation that needs to be updated. This is /// useful for backends that support multiple display /// representations for an rprim. A given representation /// may choose to pull on a subset of the dirty state. /// \param dirtyBits On input specifies which state is dirty and can be /// pulled from the scene delegate. /// On output specifies which bits are still dirty and /// were not cleaned by the sync. virtual void Sync(HdSceneDelegate *delegate, HdRenderParam *renderParam, HdDirtyBits *dirtyBits, TfToken const &reprToken) = 0; // ---------------------------------------------------------------------- // /// \name Rprim Hydra Engine API : Execute Phase // ---------------------------------------------------------------------- // /// Returns the draw items for the requested repr token, if any. /// These draw items should be constructed and cached beforehand by Sync(). /// If no draw items exist, or reprToken cannot be found, nullptr will be /// returned. HD_API const HdRepr::DrawItemUniquePtrVector & GetDrawItems(TfToken const& reprToken) const; // ---------------------------------------------------------------------- // /// \name Rprim Hydra Engine API : Cleanup // ---------------------------------------------------------------------- // /// Finalizes object resources. This function might not delete resources, /// but it should deal with resource ownership so that the rprim is /// deletable. HD_API virtual void Finalize(HdRenderParam *renderParam); // ---------------------------------------------------------------------- // /// \name Rprim Data API // ---------------------------------------------------------------------- // /// Returns the identifier of this Rprim. This is both used in the /// RenderIndex and the SceneDelegate and acts as the associative key for /// the Rprim in both contexts. SdfPath const& GetId() const { return _sharedData.rprimID; } /// Return the unique instance id int32_t GetPrimId() const { return _primId; }; /// Set the unique instance id HD_API void SetPrimId(int32_t primId); /// Returns the identifier of the instancer (if any) for this Rprim. If this /// Rprim is not instanced, an empty SdfPath will be returned. SdfPath const& GetInstancerId() const { return _instancerId; } /// Returns the path of the material to which this Rprim is bound. The /// material object itself can be fetched from the RenderIndex using /// this identifier. SdfPath const& GetMaterialId() const { return _materialId; } /// The MaterialTag allows rprims to be organized into different /// collections based on properties of the prim's material. /// E.g. A renderer may wish to organize opaque and translucent prims /// into different collections so they can be rendered seperately. TfToken const& GetMaterialTag() const { return _sharedData.materialTag; } HdReprSelector const& GetReprSelector() const { return _authoredReprSelector; } /// Returns the render tag associated to this rprim inline TfToken GetRenderTag(HdSceneDelegate* delegate) const; /// Returns the bounds of the rprim in local, untransformed space. inline GfRange3d GetExtent(HdSceneDelegate* delegate) const; /// Primvar Query inline HdPrimvarDescriptorVector GetPrimvarDescriptors(HdSceneDelegate* delegate, HdInterpolation interpolation) const; /// Returns the names of built-in primvars, i.e. primvars that /// are part of the core geometric schema for this prim. HD_API virtual TfTokenVector const & GetBuiltinPrimvarNames() const = 0; inline VtValue GetPrimvar(HdSceneDelegate* delegate, const TfToken &name) const; HD_API VtMatrix4dArray GetInstancerTransforms(HdSceneDelegate* delegate); /// Returns true if any dirty flags are set for this rprim. HD_API bool IsDirty(HdChangeTracker &changeTracker) const; /// Is the prim itself visible bool IsVisible() const { return _sharedData.visible; } HD_API void UpdateReprSelector(HdSceneDelegate* delegate, HdDirtyBits *dirtyBits); protected: // ---------------------------------------------------------------------- // /// \name Rprim Hydra Engine API : Pre-Sync & Sync-Phase // ---------------------------------------------------------------------- // /// This callback from Rprim gives the prim an opportunity to set /// additional dirty bits based on those already set. This is done /// before the dirty bits are passed to the scene delegate, so can be /// used to communicate that extra information is needed by the prim to /// process the changes. /// /// The return value is the new set of dirty bits, which replaces the bits /// passed in. /// /// See HdRprim::PropagateRprimDirtyBits() virtual HdDirtyBits _PropagateDirtyBits(HdDirtyBits bits) const = 0; /// Initialize the given representation of this Rprim. /// This is called prior to syncing the prim, the first time the repr /// is used. /// /// reprToken is the name of the representation to initalize. /// /// dirtyBits is an in/out value. It is initialized to the dirty bits /// from the change tracker. InitRepr can then set additional dirty bits /// if additional data is required from the scene delegate when this /// repr is synced. InitRepr occurs before dirty bit propagation. /// /// See HdRprim::InitRepr() virtual void _InitRepr(TfToken const &reprToken, HdDirtyBits *dirtyBits) = 0; // ---------------------------------------------------------------------- // /// \name Rprim Shared API // ---------------------------------------------------------------------- // HD_API HdReprSharedPtr const & _GetRepr(TfToken const &reprToken) const; HD_API void _UpdateVisibility(HdSceneDelegate *sceneDelegate, HdDirtyBits *dirtyBits); /// Sets a new material binding to be used by this rprim HD_API void _SetMaterialId(HdChangeTracker &changeTracker, SdfPath const& materialId); // methods to assist allocating and migrating shared primvar ranges HD_API static bool _IsEnabledSharedVertexPrimvar(); HD_API uint64_t _ComputeSharedPrimvarId(uint64_t baseId, HdBufferSourceSharedPtrVector const &sources, HdComputationSharedPtrVector const &computations) const; private: SdfPath _instancerId; SdfPath _materialId; // Used for id renders. int32_t _primId; protected: // shared data across reprs: bufferArrayRanges, bounds, visibility HdRprimSharedData _sharedData; // authored repr selector HdReprSelector _authoredReprSelector; // total number of reprs is relatively small (less than 5 or so // in most case), we use linear container for efficiency. typedef std::vector > _ReprVector; _ReprVector _reprs; struct _ReprComparator { _ReprComparator(TfToken const &name) : _name(name) {} bool operator() (const std::pair &e) const { return _name == e.first; } private: TfToken _name; }; // Repr configuration descriptors. All concrete types (HdMesh, HdPoints ..) // have this static map to lookup descriptors for the given reprToken. // // N : # of descriptors for the repr. // template struct _ReprDescConfigs { typedef std::array DescArray; static const int MAX_DESCS = N; DescArray Find(TfToken const &reprToken) const { // linear search, we expect only a handful reprs configured. TF_FOR_ALL (it, _configs) { if (it->first == reprToken) return it->second; } TF_CODING_ERROR("Repr %s not found", reprToken.GetText()); return DescArray(); } void AddOrUpdate(TfToken const &reprToken, DescArray descs) { for (auto& config : _configs) { if (config.first == reprToken) { // Overrwrite the existing entry. config.second = descs; return; } } _configs.push_back(std::make_pair(reprToken, descs)); } std::vector > _configs; }; }; //////////////////////////////////////////////////////////////////////////////// // // Delegate API Wrappers // TfToken HdRprim::GetRenderTag(HdSceneDelegate* delegate) const { return delegate->GetRenderTag(GetId()); } GfRange3d HdRprim::GetExtent(HdSceneDelegate* delegate) const { return delegate->GetExtent(GetId()); } inline HdPrimvarDescriptorVector HdRprim::GetPrimvarDescriptors(HdSceneDelegate* delegate, HdInterpolation interpolation) const { return delegate->GetPrimvarDescriptors(GetId(), interpolation); } inline VtValue HdRprim::GetPrimvar(HdSceneDelegate* delegate, const TfToken &name) const { return delegate->Get(GetId(), name); } PXR_NAMESPACE_CLOSE_SCOPE #endif //PXR_IMAGING_HD_RPRIM_H