From 2f62f227fc5640f728f81e7fe75e7f531fab7aa8 Mon Sep 17 00:00:00 2001 From: blevin Date: Thu, 25 Aug 2016 10:18:38 -0700 Subject: [PATCH 001/380] UsdVariantSet::GetVariantSelection() now respects fallbacks. (Internal change: 1644831) --- pxr/usd/lib/usd/variantSets.cpp | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/pxr/usd/lib/usd/variantSets.cpp b/pxr/usd/lib/usd/variantSets.cpp index 1da05a1868..d583609933 100644 --- a/pxr/usd/lib/usd/variantSets.cpp +++ b/pxr/usd/lib/usd/variantSets.cpp @@ -89,9 +89,19 @@ UsdVariantSet::HasAuthoredVariant(const std::string& variantName) const string UsdVariantSet::GetVariantSelection() const { - string result; - (void)HasAuthoredVariantSelection(&result); - return result; + // Scan the composed prim for variant arcs for this variant set and + // return the first selection found. This ensures that we reflect + // whatever composition process selected the variant, such as fallbacks. + TF_FOR_ALL(i, _prim.GetPrimIndex().GetNodeRange()) { + if (i->GetArcType() == PcpArcTypeVariant) { + std::pair vsel = + i->GetSite().path.GetVariantSelection(); + if (vsel.first == _variantSetName) { + return vsel.second; + } + } + } + return std::string(); } bool From f28e9d0bc53f23a4bb70dd5eef398ff6400d5551 Mon Sep 17 00:00:00 2001 From: mrawde Date: Thu, 25 Aug 2016 10:18:58 -0700 Subject: [PATCH 002/380] Add support for soft selection (mode=Object) for usd assemblies. For now, this only works on assemblies that are in "collapsed". Also, the highlight color is hardcoded to be blue since we don't have access to the falloff weight/distance at the moment. (Internal change: 1644884) --- .../maya/lib/pxrUsdMayaGL/CMakeLists.txt | 1 + .../maya/lib/pxrUsdMayaGL/batchRenderer.cpp | 98 ++++++++++--- .../maya/lib/pxrUsdMayaGL/batchRenderer.h | 7 + .../lib/pxrUsdMayaGL/softSelectHelper.cpp | 138 ++++++++++++++++++ .../maya/lib/pxrUsdMayaGL/softSelectHelper.h | 93 ++++++++++++ third_party/maya/lib/usdMaya/proxyShape.cpp | 37 +++++ third_party/maya/lib/usdMaya/proxyShape.h | 13 +- .../maya/lib/usdMaya/referenceAssembly.cpp | 2 + .../maya/lib/usdMaya/referenceAssembly.h | 15 +- 9 files changed, 375 insertions(+), 29 deletions(-) create mode 100644 third_party/maya/lib/pxrUsdMayaGL/softSelectHelper.cpp create mode 100644 third_party/maya/lib/pxrUsdMayaGL/softSelectHelper.h diff --git a/third_party/maya/lib/pxrUsdMayaGL/CMakeLists.txt b/third_party/maya/lib/pxrUsdMayaGL/CMakeLists.txt index a05e226316..a66c8d6f7e 100644 --- a/third_party/maya/lib/pxrUsdMayaGL/CMakeLists.txt +++ b/third_party/maya/lib/pxrUsdMayaGL/CMakeLists.txt @@ -27,5 +27,6 @@ pxr_shared_library(${PXR_PACKAGE} batchRenderer proxyDrawOverride proxyShapeUI + softSelectHelper ) diff --git a/third_party/maya/lib/pxrUsdMayaGL/batchRenderer.cpp b/third_party/maya/lib/pxrUsdMayaGL/batchRenderer.cpp index 5d49c0ff74..a290081567 100644 --- a/third_party/maya/lib/pxrUsdMayaGL/batchRenderer.cpp +++ b/third_party/maya/lib/pxrUsdMayaGL/batchRenderer.cpp @@ -172,6 +172,52 @@ UsdMayaGLBatchRenderer::ShapeRenderer::PrepareForQueue( } } + +// Helper function that converts the M3dView::DisplayStatus (viewport 1.0) +// into the MHWRender::DisplayStatus (viewport 2.0) +static inline +MHWRender::DisplayStatus +_ToMHWRenderDisplayStatus(const M3dView::DisplayStatus& displayStatus) +{ + // these enums are equivalent, but statically checking just in case. + static_assert(((int)M3dView::kActive == (int)MHWRender::kActive) + and ((int)M3dView::kLive == (int)MHWRender::kLive) + and ((int)M3dView::kDormant == (int)MHWRender::kDormant) + and ((int)M3dView::kInvisible == (int)MHWRender::kInvisible) + and ((int)M3dView::kHilite == (int)MHWRender::kHilite) + and ((int)M3dView::kTemplate == (int)MHWRender::kTemplate) + and ((int)M3dView::kActiveTemplate == (int)MHWRender::kActiveTemplate) + and ((int)M3dView::kActiveComponent == (int)MHWRender::kActiveComponent) + and ((int)M3dView::kLead == (int)MHWRender::kLead) + and ((int)M3dView::kIntermediateObject == (int)MHWRender::kIntermediateObject) + and ((int)M3dView::kActiveAffected == (int)MHWRender::kActiveAffected) + and ((int)M3dView::kNoStatus == (int)MHWRender::kNoStatus), + "M3dView::DisplayStatus == MHWRender::DisplayStatus"); + return MHWRender::DisplayStatus((int)displayStatus); +} + +static +bool +_GetWireframeColor( + const UsdMayaGLSoftSelectHelper& softSelectHelper, + const MDagPath& objPath, + const MHWRender::DisplayStatus& displayStatus, + MColor* mayaWireColor) +{ + // dormant objects may be included in soft selection. + if (displayStatus == MHWRender::kDormant) { + return softSelectHelper.GetFalloffColor(objPath, mayaWireColor); + } + else if ((displayStatus == MHWRender::kActive) or + (displayStatus == MHWRender::kLead) or + (displayStatus == MHWRender::kHilite)) { + *mayaWireColor = MHWRender::MGeometryUtilities::wireframeColor(objPath); + return true; + } + + return false; +} + UsdMayaGLBatchRenderer::RenderParams UsdMayaGLBatchRenderer::ShapeRenderer::GetRenderParams( const MDagPath& objPath, @@ -194,16 +240,15 @@ UsdMayaGLBatchRenderer::ShapeRenderer::GetRenderParams( // QueueShapeForDraw(...) will later break this single param set into // two, to perform a two-pass render. // - bool selected = - (displayStatus == M3dView::kActive) || - (displayStatus == M3dView::kLead) || - (displayStatus == M3dView::kHilite); - - if( selected ) + MColor mayaWireframeColor; + bool needsWire = _GetWireframeColor( + _batchRenderer->GetSoftSelectHelper(), + objPath, + _ToMHWRenderDisplayStatus(displayStatus), + &mayaWireframeColor); + + if( needsWire ) { - const MColor mayaWireframeColor = - MHWRender::MGeometryUtilities::wireframeColor(objPath); - // The legacy viewport does not support color management, // so we roll our own gamma correction via framebuffer effect. // But that means we need to pre-linearize the wireframe color @@ -227,7 +272,7 @@ UsdMayaGLBatchRenderer::ShapeRenderer::GetRenderParams( } case M3dView::kGouraudShaded: { - if( selected ) + if( needsWire ) params.drawRepr = HdTokens->refinedWireOnSurf; else params.drawRepr = HdTokens->refined; @@ -235,7 +280,7 @@ UsdMayaGLBatchRenderer::ShapeRenderer::GetRenderParams( } case M3dView::kFlatShaded: { - if( selected ) + if( needsWire ) params.drawRepr = HdTokens->wireOnSurf; else params.drawRepr = HdTokens->hull; @@ -274,15 +319,14 @@ UsdMayaGLBatchRenderer::ShapeRenderer::GetRenderParams( // QueueShapeForDraw(...) will later break this single param set into // two, to perform a two-pass render. // - bool selected = - (displayStatus == MHWRender::kActive) || - (displayStatus == MHWRender::kLead) || - (displayStatus == MHWRender::kHilite); + MColor mayaWireframeColor; + bool needsWire = _GetWireframeColor( + _batchRenderer->GetSoftSelectHelper(), + objPath, displayStatus, + &mayaWireframeColor); - if( selected ) + if( needsWire ) { - const MColor mayaWireframeColor = - MHWRender::MGeometryUtilities::wireframeColor(objPath); params.wireframeColor = GfVec4f( mayaWireframeColor.r, @@ -301,14 +345,14 @@ UsdMayaGLBatchRenderer::ShapeRenderer::GetRenderParams( if( flatShaded ) { - if( selected ) + if( needsWire ) params.drawRepr = HdTokens->wireOnSurf; else params.drawRepr = HdTokens->hull; } else if( displayStyle & MHWRender::MFrameContext::DisplayStyle::kGouraudShaded ) { - if( selected || (displayStyle & MHWRender::MFrameContext::DisplayStyle::kWireFrame) ) + if( needsWire || (displayStyle & MHWRender::MFrameContext::DisplayStyle::kWireFrame) ) params.drawRepr = HdTokens->refinedWireOnSurf; else params.drawRepr = HdTokens->refined; @@ -698,6 +742,13 @@ UsdMayaGLBatchRenderer::GetShapeRenderer( return toReturn; } +const UsdMayaGLSoftSelectHelper& +UsdMayaGLBatchRenderer::GetSoftSelectHelper() +{ + _softSelectHelper.Populate(); + return _softSelectHelper; +} + UsdMayaGLBatchRenderer::UsdMayaGLBatchRenderer() : _renderIndex(new HdRenderIndex()) , _taskDelegate(new TaskDelegate(_renderIndex, SdfPath("/mayaTask"))) @@ -1040,7 +1091,7 @@ UsdMayaGLBatchRenderer::_RenderBatches( invisedPrimPaths ); _populateQueue.clear(); - + TF_DEBUG(PXRUSDMAYAGL_QUEUE_INFO).Msg( "^^^^^^^^^^^^ POPULATE STAGE FINISH ^^^^^^^^^^^^^ (%zu)\n",_populateQueue.size()); } @@ -1052,6 +1103,11 @@ UsdMayaGLBatchRenderer::_RenderBatches( // longer valid. _selectQueue.clear(); _selectResults.clear(); + + // We've already populated with all the selection info we need. We Reset + // and the first call to GetSoftSelectHelper in the next render pass will + // re-populate it. + _softSelectHelper.Reset(); GfMatrix4d modelViewMatrix(viewMat.matrix); GfMatrix4d projectionMatrix(projectionMat.matrix); diff --git a/third_party/maya/lib/pxrUsdMayaGL/batchRenderer.h b/third_party/maya/lib/pxrUsdMayaGL/batchRenderer.h index 82dc4f95e0..1cbea4a284 100644 --- a/third_party/maya/lib/pxrUsdMayaGL/batchRenderer.h +++ b/third_party/maya/lib/pxrUsdMayaGL/batchRenderer.h @@ -28,6 +28,8 @@ #ifndef PXRUSDMAYAGL_BATCHRENDERER_H #define PXRUSDMAYAGL_BATCHRENDERER_H +#include "pxrUsdMayaGL/softSelectHelper.h" + #include "pxr/base/arch/hash.h" #include "pxr/base/tf/debug.h" #include "pxr/usd/usd/stage.h" @@ -296,6 +298,10 @@ class UsdMayaGLBatchRenderer : private boost::noncopyable const SdfPathVector& excludePrimPaths, const MDagPath& objPath ); + /// \brief Gets UsdMayaGLSoftSelectHelper that this batchRenderer maintains. + /// This should only be used by ShapeRenderer::GetRenderParams + const UsdMayaGLSoftSelectHelper& GetSoftSelectHelper(); + /// \brief Construct a new, unique BatchRenderer. In almost all cases, /// this should not be used -- use \c GlobalBatchRenderer() instead. UsdMayaGLBatchRenderer(); @@ -394,6 +400,7 @@ class UsdMayaGLBatchRenderer : private boost::noncopyable HdRenderIndexSharedPtr _renderIndex; TaskDelegateSharedPtr _taskDelegate; HdxIntersectorSharedPtr _intersector; + UsdMayaGLSoftSelectHelper _softSelectHelper; /// \brief Sole global batch renderer used by default. static UsdMayaGLBatchRenderer _sGlobalRenderer; diff --git a/third_party/maya/lib/pxrUsdMayaGL/softSelectHelper.cpp b/third_party/maya/lib/pxrUsdMayaGL/softSelectHelper.cpp new file mode 100644 index 0000000000..9fb120742d --- /dev/null +++ b/third_party/maya/lib/pxrUsdMayaGL/softSelectHelper.cpp @@ -0,0 +1,138 @@ +// +// 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. +// + +#include "pxrUsdMayaGL/softSelectHelper.h" + +#include "pxr/base/tf/stl.h" + +#include +#include +#include +#include + +UsdMayaGLSoftSelectHelper::UsdMayaGLSoftSelectHelper() + : _populated(false) +{ +} + +#define _PXRUSDMAYA_SOFTSELECT_COLORRAMP 1 + +void +UsdMayaGLSoftSelectHelper::Reset() +{ + _populated = false; + _dagPathsToWeight.clear(); +} + +void +UsdMayaGLSoftSelectHelper::Populate() +{ + // only populate if we haven't already + if (_populated) { + return; + } + + _PopulateWeights(); + _PopulateSoftSelectColorRamp(); + + _populated = true; +} + +void +UsdMayaGLSoftSelectHelper::_PopulateWeights() +{ + // we don't want to fallback to the active selection if there is no sot + // select + bool defaultToActiveSelection = false; + MRichSelection softSelect; + MGlobal::getRichSelection(softSelect, defaultToActiveSelection); + MSelectionList selection; + softSelect.getSelection(selection); + + for (MItSelectionList iter( selection, MFn::kInvalid); !iter.isDone(); iter.next() ) { + MDagPath dagPath; + MObject component; + + iter.getDagPath(dagPath, component); + // component.isNull() indcates that we're selecting a whole object, as + // opposed to a component. + if (not component.isNull()) { + continue; + } + + float weight = 0.0f; + _dagPathsToWeight[dagPath] = weight; + } +} + +void +UsdMayaGLSoftSelectHelper::_PopulateSoftSelectColorRamp() +{ + // Since in we are not able to get the real distance/weight value, we don't + // yet store the full color ramp. We just get the first color which at + // least gives feedback over which things will be influenced. + bool success = false; + MString commandResult; + + // it's really unfortunate that we have to go through this instead of having + // direct access to this. + if (MGlobal::executeCommand("softSelect -query -softSelectColorCurve", + commandResult)) { + + // parse only the first tuple. + int interp; + float r, g, b; + float position; + if (sscanf(commandResult.asChar(), + "%f,%f,%f,%f,%d", &r, &g, &b, &position, &interp) == 5) { + _wireColor = MColor(r,g,b); + success = true; + } + } + + if (not success) { + _wireColor = MColor(0.f, 0.f, 1.f); + } +} + +bool +UsdMayaGLSoftSelectHelper::GetWeight( + const MDagPath& dagPath, + float* weight) const +{ + return TfMapLookup(_dagPathsToWeight, dagPath, weight); +} + +bool +UsdMayaGLSoftSelectHelper::GetFalloffColor( + const MDagPath& dagPath, + MColor* falloffColor) const +{ + float weight = 0.f; + if (GetWeight(dagPath, &weight)) { + *falloffColor = _wireColor; + return true; + } + return false; +} diff --git a/third_party/maya/lib/pxrUsdMayaGL/softSelectHelper.h b/third_party/maya/lib/pxrUsdMayaGL/softSelectHelper.h new file mode 100644 index 0000000000..b6ac3b0f02 --- /dev/null +++ b/third_party/maya/lib/pxrUsdMayaGL/softSelectHelper.h @@ -0,0 +1,93 @@ +// +// 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. +// +/// +/// \file softSelectHelper.h +/// + +#ifndef PXRUSDMAYAGL_SOFTSELECTHELPER_H +#define PXRUSDMAYAGL_SOFTSELECTHELPER_H + +#include "pxr/base/tf/hash.h" + +#include +#include +#include +#include + +#include + +/// \class UsdMayaGLSoftSelectHelper +/// \brief Helper class to store soft ("rich") selection state while +/// computing render params for a frame. +/// +/// When rendering, we want to be able to draw things that will be influenced by +/// soft selection with a different wireframe. Querying this maya state is too +/// expensive do in the middle of the render loop so this class lets us compute +/// it once at the beginning of a frame render, and then query it later. +/// +/// While this class doesn't have anything particular to rendering, it is only +/// used by the render and is therefore here. We can move this to usdMaya if +/// we'd like to use it outside of the rendering. +class UsdMayaGLSoftSelectHelper +{ +public: + UsdMayaGLSoftSelectHelper(); + + /// \brief Clears the saved soft selection state. + void Reset(); + + /// \brief Repopulates soft selection state + void Populate(); + + /// \brief Returns true if \p dagPath is in the softSelection. Also returns + /// the \p weight. + /// + /// NOTE: until MAYA-73448 (and MAYA-73513) is fixed, the \p weight value is + /// arbitrary. + bool GetWeight(const MDagPath& dagPath, float* weight) const; + + /// \brief Returns true if \p dagPath is in the softSelection. Also returns + /// the appropriate color based on the distance/weight and the current soft + /// select color curve. It will currently always return (0, 0, 1) at the + /// moment. + bool GetFalloffColor(const MDagPath& dagPath, MColor* falloffColor) const; + +private: + + void _PopulateWeights(); + void _PopulateSoftSelectColorRamp(); + + struct _MDagPathHash { + inline size_t operator()(const MDagPath& dagPath) { + return TfHash()(std::string(dagPath.fullPathName().asChar())); + } + }; + typedef std::unordered_map _MDagPathsToWeights; + + _MDagPathsToWeights _dagPathsToWeight; + MColor _wireColor; + bool _populated; +}; + +#endif // PXRUSDMAYAGL_SOFTSELECTHELPER_H diff --git a/third_party/maya/lib/usdMaya/proxyShape.cpp b/third_party/maya/lib/usdMaya/proxyShape.cpp index b5969e3b11..c831e9ce33 100644 --- a/third_party/maya/lib/usdMaya/proxyShape.cpp +++ b/third_party/maya/lib/usdMaya/proxyShape.cpp @@ -310,6 +310,18 @@ UsdMayaProxyShape::initialize( retValue = addAttribute(psData->displayRenderGuides); CHECK_MSTATUS_AND_RETURN_IT(retValue); + psData->softSelectable = numericAttrFn.create( + "softSelectable", + "softSelectable", + MFnNumericData::kBoolean, + 0.0, + &retValue); + numericAttrFn.setKeyable(false); + numericAttrFn.setStorable(false); + numericAttrFn.setAffectsAppearance(true); + retValue = addAttribute(psData->softSelectable); + CHECK_MSTATUS_AND_RETURN_IT(retValue); + // // add attribute dependencies // @@ -907,3 +919,28 @@ UsdMayaProxyShape::~UsdMayaProxyShape() // } +MSelectionMask +UsdMayaProxyShape::getShapeSelectionMask() const +{ + if (_CanBeSoftSelected()) { + // to support soft selection (mode=Object), we need to add kSelectMeshes + // to our selection mask. + MSelectionMask::SelectionType selType = MSelectionMask::kSelectMeshes; + return MSelectionMask(selType); + } + return MPxSurfaceShape::getShapeSelectionMask(); +} + +bool +UsdMayaProxyShape::_CanBeSoftSelected() const +{ + UsdMayaProxyShape* nonConstThis = const_cast(this); + MDataBlock dataBlock = nonConstThis->forceCache(); + MStatus status; + MDataHandle softSelHandle = dataBlock.inputValue(_psData.softSelectable, &status); + if (not status) { + return false; + } + return softSelHandle.asBool(); + +} diff --git a/third_party/maya/lib/usdMaya/proxyShape.h b/third_party/maya/lib/usdMaya/proxyShape.h index 30f3b332d3..cdd11fa297 100644 --- a/third_party/maya/lib/usdMaya/proxyShape.h +++ b/third_party/maya/lib/usdMaya/proxyShape.h @@ -71,6 +71,8 @@ class UsdMayaProxyShape : public MPxSurfaceShape, MObject displayGuides; MObject displayRenderGuides; + MObject softSelectable; + // this will not change once constructed. const MTypeId typeId; const MString typeName; @@ -93,12 +95,13 @@ class UsdMayaProxyShape : public MPxSurfaceShape, PluginStaticData* psData); // Virtual function overrides - virtual void postConstructor(); + virtual void postConstructor() override; virtual MStatus compute( const MPlug& plug, - MDataBlock& dataBlock); - virtual bool isBounded() const; - virtual MBoundingBox boundingBox() const; + MDataBlock& dataBlock) override; + virtual bool isBounded() const override; + virtual MBoundingBox boundingBox() const override; + virtual MSelectionMask getShapeSelectionMask() const override; // PxrUsdMayaUsdPrimProvider overrides: UsdPrim usdPrim() const override; @@ -164,6 +167,8 @@ class UsdMayaProxyShape : public MPxSurfaceShape, bool _GetDisplayRenderGuides( MDataBlock dataBlock ) const; bool _GetTint( MDataBlock dataBlock, GfVec4f *outTintColor ) const; + bool _CanBeSoftSelected() const; + std::map _boundingBoxCache; bool _useFastPlayback; diff --git a/third_party/maya/lib/usdMaya/referenceAssembly.cpp b/third_party/maya/lib/usdMaya/referenceAssembly.cpp index 6e16be7f49..c16f8d0fb2 100644 --- a/third_party/maya/lib/usdMaya/referenceAssembly.cpp +++ b/third_party/maya/lib/usdMaya/referenceAssembly.cpp @@ -985,6 +985,8 @@ bool UsdMayaRepresentationProxyBase::activate() _OverrideProxyPlugs(shapeFn, dgMod); + dgMod.newPlugValueBool(shapeFn.findPlug(_psData.proxyShape.softSelectable, true), _proxyIsSoftSelectable); + dgMod.doIt(); _PushEditsToProxy(); diff --git a/third_party/maya/lib/usdMaya/referenceAssembly.h b/third_party/maya/lib/usdMaya/referenceAssembly.h index 8fd7f25f26..17e9e0abbc 100644 --- a/third_party/maya/lib/usdMaya/referenceAssembly.h +++ b/third_party/maya/lib/usdMaya/referenceAssembly.h @@ -234,8 +234,10 @@ class UsdMayaRepresentationBase : public MPxRepresentation class UsdMayaRepresentationProxyBase : public UsdMayaRepresentationBase { public: - UsdMayaRepresentationProxyBase(MPxAssembly *assembly, const MString &name) : - UsdMayaRepresentationBase(assembly, name) {}; + UsdMayaRepresentationProxyBase(MPxAssembly *assembly, const MString &name, + bool proxyIsSoftSelectable) : + UsdMayaRepresentationBase(assembly, name), + _proxyIsSoftSelectable(proxyIsSoftSelectable) {}; virtual bool activate(); virtual bool inactivate(); @@ -249,6 +251,7 @@ class UsdMayaRepresentationProxyBase : public UsdMayaRepresentationBase private: SdfLayerRefPtr _sessionSublayer; + bool _proxyIsSoftSelectable; }; // =========================================================== @@ -264,7 +267,11 @@ class UsdMayaRepresentationCollapsed : public UsdMayaRepresentationProxyBase // == Overrides for MPxRepresentation == UsdMayaRepresentationCollapsed(MPxAssembly *assembly, const MString &name) : - UsdMayaRepresentationProxyBase(assembly, name) {}; + + // We only support soft selection on "collapsed" proxies. While we may + // want to move proxies that are not root of the model, we suspect this + // is more likely to lead to undesired behavior. + UsdMayaRepresentationProxyBase(assembly, name, true) {}; virtual MString getType () const { return UsdMayaRepresentationCollapsed::_assemblyType; }; @@ -286,7 +293,7 @@ class UsdMayaRepresentationPlayback : public UsdMayaRepresentationProxyBase // == Overrides for MPxRepresentation == UsdMayaRepresentationPlayback(MPxAssembly *assembly, const MString &name) : - UsdMayaRepresentationProxyBase(assembly, name) {}; + UsdMayaRepresentationProxyBase(assembly, name, false) {}; virtual MString getType () const { return UsdMayaRepresentationPlayback::_assemblyType; }; From 7c20dd34a1d0f57f8333deed63d0984ab34c2aee Mon Sep 17 00:00:00 2001 From: gitamohr Date: Thu, 25 Aug 2016 10:19:45 -0700 Subject: [PATCH 003/380] usd: Destroy some data structures asynchronously. (Internal change: 1644908) --- pxr/usd/lib/usd/crateFile.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/pxr/usd/lib/usd/crateFile.cpp b/pxr/usd/lib/usd/crateFile.cpp index d9dbe8cfce..d032e6320d 100644 --- a/pxr/usd/lib/usd/crateFile.cpp +++ b/pxr/usd/lib/usd/crateFile.cpp @@ -58,6 +58,7 @@ #include "pxr/base/vt/value.h" #include "pxr/base/work/arenaDispatcher.h" #include "pxr/base/work/dispatcher.h" +#include "pxr/base/work/utils.h" #include "pxr/usd/sdf/assetPath.h" #include "pxr/usd/sdf/layerOffset.h" #include "pxr/usd/sdf/listOp.h" @@ -1361,6 +1362,8 @@ CrateFile::_WritePaths(_Writer &w) // Write the total # of paths. w.WriteAs(_paths.size()); _WritePathTree(w, pathToIndexTable.begin(), pathToIndexTable.end()); + + WorkSwapDestroyAsync(pathToIndexTable); } template @@ -1583,6 +1586,8 @@ CrateFile::_ReadTokens(Reader reader) p += strlen(p) + 1; } wd.Wait(); + + WorkSwapDestroyAsync(chars); } template From 058788e64770f26047ca3e33b82d7e786849261e Mon Sep 17 00:00:00 2001 From: gitamohr Date: Thu, 25 Aug 2016 10:19:51 -0700 Subject: [PATCH 004/380] usd: Don't store relationship target specs in usdc data. (Internal change: 1644911) --- pxr/usd/lib/usd/crateData.cpp | 86 ++++++++++++++++++++++++++++++----- 1 file changed, 74 insertions(+), 12 deletions(-) diff --git a/pxr/usd/lib/usd/crateData.cpp b/pxr/usd/lib/usd/crateData.cpp index e0e13b199d..0610c7b4db 100644 --- a/pxr/usd/lib/usd/crateData.cpp +++ b/pxr/usd/lib/usd/crateData.cpp @@ -36,6 +36,8 @@ #include "pxr/base/work/utils.h" #include "pxr/base/work/loops.h" +#include "pxr/usd/sdf/schema.h" + #include #include @@ -150,14 +152,47 @@ class Usd_CrateDataImpl return false; } + inline bool _HasTargetSpec(SdfPath const &path) const { + // We don't store target specs to save space, since in Usd we don't have + // any fields that may be set on them. Their presence is determined by + // whether or not they appear in their owning relationship's Added or + // Explicit items. + SdfPath parentPath = path.GetParentPath(); + if (parentPath.IsPrimPropertyPath()) { + VtValue targetPaths; + if (Has(SdfAbstractDataSpecId(&parentPath), + SdfFieldKeys->TargetPaths, &targetPaths) and + targetPaths.IsHolding()) { + auto const &listOp = targetPaths.UncheckedGet(); + if (listOp.IsExplicit()) { + auto const &items = listOp.GetExplicitItems(); + return std::find( + items.begin(), items.end(), path) != items.end(); + } else { + auto const &items = listOp.GetAddedItems(); + return std::find( + items.begin(), items.end(), path) != items.end(); + } + } + } + return false; + } + inline bool HasSpec(const SdfAbstractDataSpecId &id) const { const SdfPath &path = id.GetFullSpecPath(); + if (ARCH_UNLIKELY(path.IsTargetPath())) { + return _HasTargetSpec(path); + } return _hashData ? _hashData->find(path) != _hashData->end() : _flatData.find(path) != _flatData.end(); } inline void EraseSpec(const SdfAbstractDataSpecId &id) { + if (ARCH_UNLIKELY(id.GetFullSpecPath().IsTargetPath())) { + // Do nothing, we do not store target specs. + return; + } if (_MaybeMoveToHashTable()) { _hashLastSet = nullptr; TF_VERIFY(_hashData->erase(id.GetFullSpecPath()), @@ -175,6 +210,11 @@ class Usd_CrateDataImpl inline void MoveSpec(const SdfAbstractDataSpecId& oldId, const SdfAbstractDataSpecId& newId) { + if (ARCH_UNLIKELY(oldId.GetFullSpecPath().IsTargetPath())) { + // Do nothing, we do not store target specs. + return; + } + SdfPath const &oldPath = oldId.GetFullSpecPath(); SdfPath const &newPath = newId.GetFullSpecPath(); @@ -211,8 +251,13 @@ class Usd_CrateDataImpl inline SdfSpecType GetSpecType(const SdfAbstractDataSpecId &id) const { SdfPath const &path = id.GetFullSpecPath(); - if (path == SdfPath::AbsoluteRootPath()) + if (path == SdfPath::AbsoluteRootPath()) { return SdfSpecTypePseudoRoot; + } + if (path.IsTargetPath()) { + return _HasTargetSpec(path) ? + SdfSpecTypeRelationshipTarget : SdfSpecTypeUnknown; + } if (_hashData) { auto i = _hashData->find(path); return i == _hashData->end() ? @@ -222,19 +267,18 @@ class Usd_CrateDataImpl if (i == _flatData.end()) return SdfSpecTypeUnknown; // Don't look up in the table if we can tell the type from the path. - if (path.IsPrimPath()) - return SdfSpecTypePrim; - // In Usd, target paths may only ever identify relationship targets, - // since Usd does not have support for attribute connections. - if (path.IsTargetPath()) - return SdfSpecTypeRelationshipTarget; - return _flatTypes[i - _flatData.begin()].type; + return path.IsPrimPath() ? SdfSpecTypePrim : + _flatTypes[i - _flatData.begin()].type; } inline void CreateSpec(const SdfAbstractDataSpecId &id, SdfSpecType specType) { if (not TF_VERIFY(specType != SdfSpecTypeUnknown)) return; + if (id.GetFullSpecPath().IsTargetPath()) { + // Do nothing, we do not store relationship target specs in usd. + return; + } if (_MaybeMoveToHashTable()) { // No need to blow the _hashLastSet cache here, since inserting into // the table won't invalidate existing references. @@ -255,6 +299,7 @@ class Usd_CrateDataImpl inline void _VisitSpecs(SdfAbstractData const &data, SdfAbstractDataSpecVisitor* visitor) const { + // XXX: Is it important to present relationship target specs here? if (_hashData) { for (auto const &p: *_hashData) { if (not visitor->VisitSpec( @@ -383,6 +428,12 @@ class Usd_CrateDataImpl Erase(id, fieldName); return; } + if (id.GetFullSpecPath().IsTargetPath()) { + TF_CODING_ERROR("Cannot set fields on relationship target specs: " + "<%s>:%s = %s", id.GetFullSpecPath().GetText(), + fieldName.GetText(), TfStringify(value).c_str()); + return; + } _hashData ? _SetHelper(*_hashData, id, _hashLastSet, fieldName, value) : _SetHelper(_flatData, id, _flatLastSet, fieldName, value); @@ -563,10 +614,16 @@ class Usd_CrateDataImpl vector fields; vector fieldSets; _crateFile->RemoveStructuralData(specs, fields, fieldSets); - - // Allocate all the spec data structures in the hashtable first, so we - // can populate fields in parallel without locking. - vector<_FlatSpecData *> specDataPtrs; + + // Remove any target specs, we do not store target specs in Usd, but old + // files could contain them. + specs.erase( + remove_if( + specs.begin(), specs.end(), + [this](CrateFile::Spec const &spec) { + return _crateFile->GetPath(spec.pathIndex).IsTargetPath(); + }), + specs.end()); // Sort by path fast-less-than, need same order that _Table will // store. @@ -591,6 +648,7 @@ class Usd_CrateDataImpl result_type operator()(CrateFile::Spec const &spec) const { result_type r; r.first = crateFile->GetPath(spec.pathIndex); + TF_AXIOM(!r.first.IsTargetPath()); return r; } CrateFile *crateFile; @@ -606,6 +664,10 @@ class Usd_CrateDataImpl _flatData); } + // Allocate all the spec data structures in the hashtable first, so we + // can populate fields in parallel without locking. + vector<_FlatSpecData *> specDataPtrs; + // Create all the specData entries and store pointers to them. dispatcher.Run([this, &specs, &specDataPtrs]() { // XXX Won't need first two tags when bug #132031 is addressed From b6b4141dbf2db7c7a0698a432e7a7e5ff02b483d Mon Sep 17 00:00:00 2001 From: stevelavietes Date: Thu, 25 Aug 2016 10:20:11 -0700 Subject: [PATCH 005/380] adjust error handling of InitUsdInArgs 1) make sure errors are handled as errors 2) don't silently reset isolatePath to stage root on failure (Internal change: 1644931) --- .../katana/lib/usdKatana/usdInArgs.cpp | 7 +- third_party/katana/lib/usdKatana/usdInArgs.h | 14 +- .../katana/plugin/pxrUsdIn/pxrUsdIn.cpp | 159 ++++++++++++------ 3 files changed, 127 insertions(+), 53 deletions(-) diff --git a/third_party/katana/lib/usdKatana/usdInArgs.cpp b/third_party/katana/lib/usdKatana/usdInArgs.cpp index 8fc93f1a54..e51fddcecd 100644 --- a/third_party/katana/lib/usdKatana/usdInArgs.cpp +++ b/third_party/katana/lib/usdKatana/usdInArgs.cpp @@ -39,7 +39,8 @@ PxrUsdKatanaUsdInArgs::PxrUsdKatanaUsdInArgs( double shutterClose, const std::vector& motionSampleTimes, const StringListMap& extraAttributesOrNamespaces, - bool verbose) : + bool verbose, + const char * errorMessage) : _stage(stage), _rootLocation(rootLocation), _isolatePath(isolatePath), @@ -52,6 +53,10 @@ PxrUsdKatanaUsdInArgs::PxrUsdKatanaUsdInArgs( _extraAttributesOrNamespaces(extraAttributesOrNamespaces), _verbose(verbose) { + if (errorMessage) + { + _errorMessage = errorMessage; + } } PxrUsdKatanaUsdInArgs::~PxrUsdKatanaUsdInArgs() diff --git a/third_party/katana/lib/usdKatana/usdInArgs.h b/third_party/katana/lib/usdKatana/usdInArgs.h index 1c5a192a27..9faef1134e 100644 --- a/third_party/katana/lib/usdKatana/usdInArgs.h +++ b/third_party/katana/lib/usdKatana/usdInArgs.h @@ -57,7 +57,8 @@ class PxrUsdKatanaUsdInArgs : public TfRefBase double shutterClose, const std::vector& motionSampleTimes, const StringListMap& extraAttributesOrNamespaces, - bool verbose) { + bool verbose, + const char * errorMessage = 0) { return TfCreateRefPtr(new PxrUsdKatanaUsdInArgs( stage, rootLocation, @@ -69,7 +70,8 @@ class PxrUsdKatanaUsdInArgs : public TfRefBase shutterClose, motionSampleTimes, extraAttributesOrNamespaces, - verbose)); + verbose, + errorMessage)); } // bounds computation is kind of important, so we centralize it here. @@ -129,6 +131,9 @@ class PxrUsdKatanaUsdInArgs : public TfRefBase return _bboxCaches.local(); } + const std::string & GetErrorMessage() { + return _errorMessage; + } private: PxrUsdKatanaUsdInArgs( @@ -142,7 +147,8 @@ class PxrUsdKatanaUsdInArgs : public TfRefBase double shutterClose, const std::vector& motionSampleTimes, const StringListMap& extraAttributesOrNamespaces, - bool verbose); + bool verbose, + const char * errorMessage = 0); ~PxrUsdKatanaUsdInArgs(); @@ -166,6 +172,8 @@ class PxrUsdKatanaUsdInArgs : public TfRefBase typedef tbb::enumerable_thread_specific< std::vector > _ThreadLocalBBoxCaches; _ThreadLocalBBoxCaches _bboxCaches; + + std::string _errorMessage; }; diff --git a/third_party/katana/plugin/pxrUsdIn/pxrUsdIn.cpp b/third_party/katana/plugin/pxrUsdIn/pxrUsdIn.cpp index 320cc2694b..db6eb88444 100644 --- a/third_party/katana/plugin/pxrUsdIn/pxrUsdIn.cpp +++ b/third_party/katana/plugin/pxrUsdIn/pxrUsdIn.cpp @@ -104,6 +104,12 @@ class PxrUsdInOp : public FnKat::GeolibOp ERROR("Could not initialize PxrUsdIn usdInArgs."); return; } + + if (not usdInArgs->GetErrorMessage().empty()) + { + ERROR(usdInArgs->GetErrorMessage().c_str()); + return; + } if (interface.atRoot()) { interface.stopChildTraversal(); @@ -473,26 +479,80 @@ class PxrUsdInOp : public FnKat::GeolibOp return buffer.str(); } + + // utility to make it easier to exit earlier from InitUsdInArgs + struct ArgsBuilder + { + UsdStageRefPtr stage; + std::string rootLocation; + std::string isolatePath; + SdfPathSet variantSelections; + std::string ignoreLayerRegex; + double currentTime; + double shutterOpen; + double shutterClose; + std::vector motionSampleTimes; + PxrUsdKatanaUsdInArgs::StringListMap extraAttributesOrNamespaces; + bool verbose; + const char * errorMessage; + + + ArgsBuilder() + : currentTime(0.0) + , shutterOpen(0.0) + , shutterClose(0.0) + , verbose(false) + , errorMessage(0) + { + } + + PxrUsdKatanaUsdInArgsRefPtr build() + { + return PxrUsdKatanaUsdInArgs::New( + stage, + rootLocation, + isolatePath, + variantSelections, + ignoreLayerRegex, + currentTime, + shutterOpen, + shutterClose, + motionSampleTimes, + extraAttributesOrNamespaces, + verbose, + errorMessage); + } + + PxrUsdKatanaUsdInArgsRefPtr buildWithError(std::string errorStr) + { + errorMessage = errorStr.c_str(); + return build(); + } + + }; + + static PxrUsdKatanaUsdInArgsRefPtr InitUsdInArgs(const FnKat::GeolibCookInterface &interface, FnKat::GroupAttribute & additionalOpArgs) { + ArgsBuilder ab; + FnKat::StringAttribute usdFileAttr = interface.getOpArg("fileName"); if (not usdFileAttr.isValid()) { - FnLogInfo("Missing fileName attr."); - return TfNullPtr; + return ab.buildWithError("PxrUsdIn: USD fileName not specified."); } std::string fileName = usdFileAttr.getValue(); - std::string rootLocation = FnKat::StringAttribute( + ab.rootLocation = FnKat::StringAttribute( interface.getOpArg("location")).getValue( interface.getRootLocationPath(), false); std::string variants = FnKat::StringAttribute( interface.getOpArg("variants")).getValue("", false); - std::string sessionLocation = rootLocation; + std::string sessionLocation = ab.rootLocation; FnKat::StringAttribute sessionLocationAttr = interface.getOpArg("sessionLocation"); if (sessionLocationAttr.isValid()) { @@ -502,31 +562,32 @@ class PxrUsdInOp : public FnKat::GeolibOp variants += GetVariantStringFromSession( interface.getOpArg("session"), sessionLocation); - SdfPathSet variantSelections; + std::set selStrings = TfStringTokenizeToSet(variants); TF_FOR_ALL(selString, selStrings) { std::string errMsg; if (SdfPath::IsValidPathString(*selString, &errMsg)) { SdfPath varSelPath(*selString); if (varSelPath.IsPrimVariantSelectionPath()) { - variantSelections.insert( SdfPath(*selString) ); + ab.variantSelections.insert( SdfPath(*selString) ); continue; } - } - FnLogWarn(TfStringPrintf("Bad variant selection \"%s\"", - selString->c_str()).c_str()); - return TfNullPtr; + } + + return ab.buildWithError( + TfStringPrintf("PxrUsdIn: Bad variant selection \"%s\"", + selString->c_str()).c_str()); } - std::string ignoreLayerRegex = FnKat::StringAttribute( + ab.ignoreLayerRegex = FnKat::StringAttribute( interface.getOpArg("ignoreLayerRegex")).getValue("", false); - bool verbose = FnKat::IntAttribute( + ab.verbose = FnKat::IntAttribute( interface.getOpArg("verbose")).getValue(0, false); FnKat::GroupAttribute systemArgs(interface.getOpArg("system")); - double currentTime = + ab.currentTime = FnKat::FloatAttribute(systemArgs.getChildByName( "timeSlice.currentTime")).getValue(0, false); @@ -534,16 +595,14 @@ class PxrUsdInOp : public FnKat::GeolibOp FnKat::IntAttribute(systemArgs.getChildByName( "timeSlice.numSamples")).getValue(1, false); - double shutterOpen = + ab.shutterOpen = FnKat::FloatAttribute(systemArgs.getChildByName( "timeSlice.shutterOpen")).getValue(0, false); - double shutterClose = + ab.shutterClose = FnKat::FloatAttribute(systemArgs.getChildByName( "timeSlice.shutterClose")).getValue(0, false); - std::vector motionSampleTimes; - std::string motionSampleStr = FnKat::StringAttribute( interface.getOpArg("motionSampleTimes")).getValue("", false); @@ -552,7 +611,7 @@ class PxrUsdInOp : public FnKat::GeolibOp // if (numSamples < 2 or motionSampleStr.empty()) { - motionSampleTimes.push_back(0); + ab.motionSampleTimes.push_back(0); } else { @@ -561,20 +620,19 @@ class PxrUsdInOp : public FnKat::GeolibOp for (std::vector::iterator it = tokens.begin(); it != tokens.end(); ++it) { - motionSampleTimes.push_back(std::stod(*it)); + ab.motionSampleTimes.push_back(std::stod(*it)); } } - UsdStageRefPtr stage = + ab.stage = UsdKatanaCache::GetInstance().GetStage( fileName, - variantSelections, - ignoreLayerRegex, + ab.variantSelections, + ab.ignoreLayerRegex, true /* forcePopulate */); - if (not stage) { - FnLogInfo("No stage."); - return TfNullPtr; + if (not ab.stage) { + return ab.buildWithError("PxrUsdIn: USD Stage cannot be loaded."); } if (FnAttribute::StringAttribute( @@ -582,25 +640,26 @@ class PxrUsdInOp : public FnKat::GeolibOp ).getValue("expanded", false) == "as sources and instances") { additionalOpArgs = FnKat::GroupAttribute("masterMapping", - PxrUsdKatanaUtils::BuildInstanceMasterMapping(stage), true); + PxrUsdKatanaUtils::BuildInstanceMasterMapping(ab.stage), true); } - std::string isolatePath = FnKat::StringAttribute( + ab.isolatePath = FnKat::StringAttribute( interface.getOpArg("isolatePath")).getValue("", false); // if the specified isolatePath is not a valid prim, clear it out - if (not isolatePath.empty() and not stage->GetPrimAtPath(SdfPath(isolatePath))) + if (not ab.isolatePath.empty() and not ab.stage->GetPrimAtPath(SdfPath(ab.isolatePath))) { - FnLogWarn("Invalid isolatePath: " << isolatePath); - isolatePath = ""; + std::ostringstream errorBuffer; + errorBuffer << "PxrUsdIn: Invalid isolatePath: " << ab.isolatePath << "."; + return ab.buildWithError(errorBuffer.str()); } // get extra attributes or namespaces if they exist // - PxrUsdKatanaUsdInArgs::StringListMap extraAttributesOrNamespaces; + FnKat::StringAttribute extraAttributesOrNamespacesAttr = interface.getOpArg("extraAttributesOrNamespaces"); @@ -622,39 +681,28 @@ class PxrUsdInOp : public FnKat::GeolibOp } pystring::split(value, tokens, ":", 1); - extraAttributesOrNamespaces[tokens[0]].push_back(value); + ab.extraAttributesOrNamespaces[tokens[0]].push_back(value); } } // always include userProperties if not explicitly included. - if (extraAttributesOrNamespaces.find("userProperties") - == extraAttributesOrNamespaces.end()) + if (ab.extraAttributesOrNamespaces.find("userProperties") + == ab.extraAttributesOrNamespaces.end()) { - extraAttributesOrNamespaces["userProperties"].push_back( + ab.extraAttributesOrNamespaces["userProperties"].push_back( "userProperties"); } else { // if it is there, enforce that it includes only the top-level attr std::vector & userPropertiesNames = - extraAttributesOrNamespaces["userProperties"]; + ab.extraAttributesOrNamespaces["userProperties"]; userPropertiesNames.clear(); userPropertiesNames.push_back("userProperties"); } - - return PxrUsdKatanaUsdInArgs::New( - stage, - rootLocation, - isolatePath, - variantSelections, - ignoreLayerRegex, - currentTime, - shutterOpen, - shutterClose, - motionSampleTimes, - extraAttributesOrNamespaces, - verbose); + + return ab.build(); } private: @@ -737,6 +785,19 @@ class PxrUsdInBootstrapOp : public FnKat::GeolibOp FnKat::GroupAttribute additionalOpArgs; PxrUsdKatanaUsdInArgsRefPtr usdInArgs = PxrUsdInOp::InitUsdInArgs(interface, additionalOpArgs); + + if (not usdInArgs) { + ERROR("Could not initialize PxrUsdIn usdInArgs."); + return; + } + + if (not usdInArgs->GetErrorMessage().empty()) + { + ERROR(usdInArgs->GetErrorMessage().c_str()); + return; + } + + FnKat::GroupAttribute opArgs = FnKat::GroupBuilder() .update(interface.getOpArg()) From 09765f2c5e237598b85ccd58ec2e3b2b0971c4ae Mon Sep 17 00:00:00 2001 From: mattyjams Date: Thu, 25 Aug 2016 10:20:47 -0700 Subject: [PATCH 006/380] export color sets (including displayColor and displayOpacity) as indexed primvars (Internal change: 1644986) --- .../maya/lib/usdMaya/MayaMeshWriter.cpp | 199 +++-- third_party/maya/lib/usdMaya/MayaMeshWriter.h | 84 ++- .../lib/usdMaya/MayaMeshWriter_PrimVars.cpp | 683 ++++++++++++------ .../lib/usdMaya/MayaNurbsSurfaceWriter.cpp | 28 +- third_party/maya/lib/usdMaya/util.cpp | 313 +++++--- third_party/maya/lib/usdMaya/util.h | 56 +- 6 files changed, 925 insertions(+), 438 deletions(-) diff --git a/third_party/maya/lib/usdMaya/MayaMeshWriter.cpp b/third_party/maya/lib/usdMaya/MayaMeshWriter.cpp index d84d0ce3e2..b5a503b1eb 100644 --- a/third_party/maya/lib/usdMaya/MayaMeshWriter.cpp +++ b/third_party/maya/lib/usdMaya/MayaMeshWriter.cpp @@ -25,6 +25,8 @@ #include "usdMaya/meshUtil.h" +#include "pxr/base/gf/vec3f.h" +#include "pxr/base/tf/staticTokens.h" #include "pxr/usd/usdGeom/mesh.h" #include "pxr/usd/usdGeom/pointBased.h" #include "pxr/usd/usdUtils/pipeline.h" @@ -33,6 +35,19 @@ #include #include +TF_DEFINE_PRIVATE_TOKENS(_tokens, + ((DisplayColorColorSetName, "displayColor")) + ((DisplayOpacityColorSetName, "displayOpacity")) +); + + +const GfVec3f MayaMeshWriter::_ShaderDefaultRGB = GfVec3f(0.5); +const float MayaMeshWriter::_ShaderDefaultAlpha = 0.0; + +const GfVec3f MayaMeshWriter::_ColorSetDefaultRGB = GfVec3f(0.0); +const float MayaMeshWriter::_ColorSetDefaultAlpha = 0.0; + + MayaMeshWriter::MayaMeshWriter( MDagPath & iDag, UsdStageRefPtr stage, @@ -41,7 +56,6 @@ MayaMeshWriter::MayaMeshWriter( { } - //virtual UsdPrim MayaMeshWriter::write(const UsdTimeCode &usdTime) { @@ -214,106 +228,153 @@ bool MayaMeshWriter::writeMeshAttrs(const UsdTimeCode &usdTime, UsdGeomMesh &pri if (getArgs().exportColorSets) { status = lMesh.getColorSetNames(colorSetNames); } - // shaderColor is used in our pipeline as displayColor. - // shaderColor is used to fill faces where the colorset is not assigned - MColorArray shaderColors; - MObjectArray shaderObjs; - + VtArray shadersRGBData; - TfToken shadersRGBInterp; VtArray shadersAlphaData; - TfToken shadersAlphaInterp; - - // If exportDisplayColor is set to true or we have color sets, - // gather color & opacity from the shader including per face - // assignment. Color set require this to initialize unauthored/unpainted faces - if (getArgs().exportDisplayColor or colorSetNames.length()>0) { - PxrUsdMayaUtil::GetLinearShaderColor(lMesh, numPolygons, - &shadersRGBData, &shadersRGBInterp, - &shadersAlphaData, &shadersAlphaInterp); + TfToken shadersInterpolation; + VtArray shadersAssignmentIndices; + + // If we're exporting displayColor or we have color sets, gather colors and + // opacities from the shaders assigned to the mesh and/or its faces. + // If we find a displayColor color set, the shader colors and opacities + // will be used to fill in unauthored/unpainted faces in the color set. + if (getArgs().exportDisplayColor or colorSetNames.length() > 0) { + PxrUsdMayaUtil::GetLinearShaderColor(lMesh, + &shadersRGBData, + &shadersAlphaData, + &shadersInterpolation, + &shadersAssignmentIndices); } - for (unsigned int i=0; i < colorSetNames.length(); i++) { + for (unsigned int i=0; i < colorSetNames.length(); ++i) { - bool isDisplayColor=false; + bool isDisplayColor = false; - if (colorSetNames[i]=="displayColor") { - if (not getArgs().exportDisplayColor) + if (colorSetNames[i] == _tokens->DisplayColorColorSetName.GetText()) { + if (not getArgs().exportDisplayColor) { continue; + } isDisplayColor=true; } - if (colorSetNames[i]=="displayOpacity") { - MGlobal::displayWarning("displayOpacity on mesh:" + lMesh.fullPathName() + - " is a reserved PrimVar name in USD. Skipping..."); + if (colorSetNames[i] == _tokens->DisplayOpacityColorSetName.GetText()) { + MGlobal::displayWarning("Mesh \"" + lMesh.fullPathName() + + "\" has a color set named \"" + + MString(_tokens->DisplayOpacityColorSetName.GetText()) + + "\" which is a reserved Primvar name in USD. Skipping..."); continue; } VtArray RGBData; - TfToken RGBInterp; - VtArray RGBAData; - TfToken RGBAInterp; VtArray AlphaData; - TfToken AlphaInterp; + TfToken interpolation; + VtArray assignmentIndices; + int unassignedValueIndex = -1; MFnMesh::MColorRepresentation colorSetRep; - bool clamped=false; - - // If displayColor uses shaderValues for non authored areas - // and allow RGB and Alpha to have different interpolation - // For all other colorSets the non authored values are set - // to (1,1,1,1) and RGB and Alpha will have the same interplation - // since they will be emitted as a Vec4f - if (not _GetMeshColorSetData( lMesh, colorSetNames[i], - isDisplayColor, - shadersRGBData, shadersAlphaData, - &RGBData, &RGBInterp, - &RGBAData, &RGBAInterp, - &AlphaData, &AlphaInterp, - &colorSetRep, &clamped)) { + bool clamped = false; + + if (not _GetMeshColorSetData(lMesh, + colorSetNames[i], + isDisplayColor, + shadersRGBData, + shadersAlphaData, + shadersAssignmentIndices, + &RGBData, + &AlphaData, + &interpolation, + &assignmentIndices, + &colorSetRep, + &clamped)) { MGlobal::displayWarning("Unable to retrieve colorSet data: " + - colorSetNames[i] + " on mesh: "+ lMesh.fullPathName() + ". Skipping..."); + colorSetNames[i] + " on mesh: " + lMesh.fullPathName() + + ". Skipping..."); continue; } + PxrUsdMayaUtil::AddUnassignedColorAndAlphaIfNeeded( + &RGBData, + &AlphaData, + &assignmentIndices, + &unassignedValueIndex, + _ColorSetDefaultRGB, + _ColorSetDefaultAlpha); + if (isDisplayColor) { // We tag the resulting displayColor/displayOpacity primvar as - // authored to make sure we reconstruct the colorset on import - // The RGB is also convererted From DisplayToLinear - - - _setDisplayPrimVar( primSchema, colorSetRep, - RGBData, RGBInterp, - AlphaData, AlphaInterp, - clamped, true); + // authored to make sure we reconstruct the color set on import. + _addDisplayPrimvars(primSchema, + colorSetRep, + RGBData, + AlphaData, + interpolation, + assignmentIndices, + unassignedValueIndex, + clamped, + true); } else { TfToken colorSetNameToken = TfToken( - PxrUsdMayaUtil::SanitizeColorSetName( - std::string(colorSetNames[i].asChar()))); + PxrUsdMayaUtil::SanitizeColorSetName( + std::string(colorSetNames[i].asChar()))); if (colorSetRep == MFnMesh::kAlpha) { - _createAlphaPrimVar(primSchema, colorSetNameToken, - AlphaData, AlphaInterp, clamped); + _createAlphaPrimVar(primSchema, + colorSetNameToken, + AlphaData, + interpolation, + assignmentIndices, + unassignedValueIndex, + clamped); } else if (colorSetRep == MFnMesh::kRGB) { - _createRGBPrimVar(primSchema, colorSetNameToken, - RGBData, RGBInterp, clamped); + _createRGBPrimVar(primSchema, + colorSetNameToken, + RGBData, + interpolation, + assignmentIndices, + unassignedValueIndex, + clamped); } else if (colorSetRep == MFnMesh::kRGBA) { - _createRGBAPrimVar(primSchema, colorSetNameToken, - RGBAData, RGBAInterp, clamped); + _createRGBAPrimVar(primSchema, + colorSetNameToken, + RGBData, + AlphaData, + interpolation, + assignmentIndices, + unassignedValueIndex, + clamped); } } } - // Set displayColor and displayOpacity only if they are NOT authored already - // Since this primvar will come from the shader and not a colorset, - // we are not adding the clamp attribute as custom data - // If a displayColor/displayOpacity is added, it's not considered authored - // we don't need to reconstruct this as a colorset since it orgininated - // from bound shader[s], so the authored flag is set to false - // Given that this RGB is for display, we do DisplayToLinear conversion + + // _addDisplayPrimvars() will only author displayColor and displayOpacity + // if no authored opinions exist, so the code below only has an effect if + // we did NOT find a displayColor color set above. if (getArgs().exportDisplayColor) { - _setDisplayPrimVar( primSchema, MFnMesh::kRGBA, - shadersRGBData, shadersRGBInterp, - shadersAlphaData, shadersAlphaInterp, - false, false); + // Using the shader default values (an alpha of zero, in particular) + // results in Gprims rendering the same way in usdview as they do in + // Maya (i.e. unassigned components are invisible). + int unassignedValueIndex = -1; + PxrUsdMayaUtil::AddUnassignedColorAndAlphaIfNeeded( + &shadersRGBData, + &shadersAlphaData, + &shadersAssignmentIndices, + &unassignedValueIndex, + _ShaderDefaultRGB, + _ShaderDefaultAlpha); + + // Since these colors come from the shaders and not a colorset, we are + // not adding the clamp attribute as custom data. We also don't need to + // reconstruct a color set from them on import since they originated + // from the bound shader(s), so the authored flag is set to false. + _addDisplayPrimvars(primSchema, + MFnMesh::kRGBA, + shadersRGBData, + shadersAlphaData, + shadersInterpolation, + shadersAssignmentIndices, + unassignedValueIndex, + false, + false); } + return true; } diff --git a/third_party/maya/lib/usdMaya/MayaMeshWriter.h b/third_party/maya/lib/usdMaya/MayaMeshWriter.h index f8515444a0..56c74e4399 100644 --- a/third_party/maya/lib/usdMaya/MayaMeshWriter.h +++ b/third_party/maya/lib/usdMaya/MayaMeshWriter.h @@ -21,18 +21,17 @@ // KIND, either express or implied. See the Apache License for the specific // language governing permissions and limitations under the Apache License. // -#ifndef _usdExport_MayaMeshWriter_h_ -#define _usdExport_MayaMeshWriter_h_ +#ifndef PXRUSDMAYA_MAYAMESHWRITER_H +#define PXRUSDMAYA_MAYAMESHWRITER_H #include "usdMaya/MayaTransformWriter.h" + #include class UsdGeomMesh; class UsdGeomGprim; -class MFnLambertShader; -class MFnMesh; class MString; -class MColorArray; + // Writes an MFnMesh as a poly mesh OR a subd mesh class MayaMeshWriter : public MayaTransformWriter @@ -57,18 +56,20 @@ class MayaMeshWriter : public MayaTransformWriter MStatus _GetMeshUVSetData( MFnMesh& m, MString uvSetName, VtArray *uvArray, TfToken *interpolation); - + bool _GetMeshColorSetData( - MFnMesh& m, + MFnMesh& mesh, MString colorSet, bool isDisplayColor, const VtArray& shadersRGBData, const VtArray& shadersAlphaData, - VtArray *RGBData, TfToken *RGBInterp, - VtArray *RGBAData, TfToken *RGBAInterp, - VtArray *AlphaData, TfToken *AlphaInterp, - MFnMesh::MColorRepresentation *colorSetRep, - bool *clamped); + const VtArray& shadersAssignmentIndices, + VtArray* colorSetRGBData, + VtArray* colorSetAlphaData, + TfToken* interpolation, + VtArray* colorSetAssignmentIndices, + MFnMesh::MColorRepresentation* colorSetRep, + bool* clamped); static MStatus _CompressUVs(const MFnMesh& m, @@ -83,25 +84,56 @@ class MayaMeshWriter : public MayaTransformWriter const MFloatArray& uArray, const MFloatArray& vArray, VtArray *uvArray); - bool _createAlphaPrimVar( UsdGeomGprim &primSchema, const TfToken name, - const VtArray& data, TfToken interpolation, - bool clamped); + bool _createAlphaPrimVar(UsdGeomGprim &primSchema, + const TfToken& name, + const VtArray& data, + const TfToken& interpolation, + const VtArray& assignmentIndices, + const int unassignedValueIndex, + bool clamped); - bool _createRGBPrimVar( UsdGeomGprim &primSchema, const TfToken name, - const VtArray& data, TfToken interpolation, + bool _createRGBPrimVar(UsdGeomGprim &primSchema, + const TfToken& name, + const VtArray& data, + const TfToken& interpolation, + const VtArray& assignmentIndices, + const int unassignedValueIndex, + bool clamped); + + bool _createRGBAPrimVar(UsdGeomGprim &primSchema, + const TfToken& name, + const VtArray& rgbData, + const VtArray& alphaData, + const TfToken& interpolation, + const VtArray& assignmentIndices, + const int unassignedValueIndex, bool clamped); - bool _createRGBAPrimVar( UsdGeomGprim &primSchema, const TfToken name, - const VtArray& RGBAData, TfToken RGBAInterp, - bool clamped); + /// Adds displayColor and displayOpacity primvars using the given color, + /// alpha, and assignment data if the \p primSchema does not already have + /// authored opinions for them. + bool _addDisplayPrimvars( + UsdGeomGprim &primSchema, + const MFnMesh::MColorRepresentation colorRep, + const VtArray& RGBData, + const VtArray& AlphaData, + const TfToken& interpolation, + const VtArray& assignmentIndices, + const int unassignedValueIndex, + const bool clamped, + const bool authored); + + /// Default values to use when collecting colors based on shader values + /// and an object or component has no assigned shader. + static const GfVec3f _ShaderDefaultRGB; + static const float _ShaderDefaultAlpha; - bool _setDisplayPrimVar( UsdGeomGprim &primSchema, - MFnMesh::MColorRepresentation colorRep, - VtArray RGBData, TfToken RGBInterp, - VtArray AlphaData, TfToken AlphaInterp, - bool clamped, bool authored); + /// Default values to use when collecting colors from a color set and a + /// component has no authored value. + static const GfVec3f _ColorSetDefaultRGB; + static const float _ColorSetDefaultAlpha; }; typedef shared_ptr < MayaMeshWriter > MayaMeshWriterPtr; -#endif // _usdExport_MayaMeshWriter_h_ +#endif // PXRUSDMAYA_MAYAMESHWRITER_H diff --git a/third_party/maya/lib/usdMaya/MayaMeshWriter_PrimVars.cpp b/third_party/maya/lib/usdMaya/MayaMeshWriter_PrimVars.cpp index 073536d5c4..00afbb03cf 100644 --- a/third_party/maya/lib/usdMaya/MayaMeshWriter_PrimVars.cpp +++ b/third_party/maya/lib/usdMaya/MayaMeshWriter_PrimVars.cpp @@ -23,100 +23,186 @@ // #include "usdMaya/MayaMeshWriter.h" +#include "pxr/base/gf/gamma.h" #include "pxr/base/gf/math.h" #include "pxr/base/gf/transform.h" -#include "pxr/base/gf/gamma.h" - #include "pxr/usd/usdGeom/mesh.h" -#include +#include #include #include -#include -#include -#include -#include -#include #include -#include -#include #include -// This function tries to compress facevarying data to uniform, vertex or constant -// Loop over all elements and invalidate any of the 3 conditions -// Copy uniform and vertex values into a temporary array -// At the end resize to 1 or copy those temporary array into the resulting data -template -static void compressFVPrimvar(MFnMesh& m, VtArray *data, TfToken *interpolation) +#include + + +template +struct ValueHash +{ + std::size_t operator() (const T& value) const { + return hash_value(value); + } +}; + +template +struct ValuesEqual +{ + bool operator() (const T& a, const T& b) const { + return GfIsClose(a, b, 1e-9); + } +}; + +// This function condenses distinct indices that point to the same color values +// (the combination of RGB AND Alpha) to all point to the same index for that +// value. This will potentially shrink the data arrays. +static +void +_MergeEquivalentColorSetValues( + VtArray* colorSetRGBData, + VtArray* colorSetAlphaData, + VtArray* colorSetAssignmentIndices) { - std::vector valueOnVertex; - std::vector valueOnFace; - VtArray vertexValue; - VtArray faceValue; - - bool isConstant=true; - bool isUniform=true; - bool isVertex=true; - int numVertices = m.numVertices(); - int numPolygons = m.numPolygons(); - valueOnVertex.resize(numVertices, false); - valueOnFace.resize(numPolygons, false); - vertexValue.resize(numVertices); - faceValue.resize(numPolygons); - - MItMeshFaceVertex itFV( m.object() ); - int fvi=0; - for( itFV.reset(); !itFV.isDone(); itFV.next() ) { - int faceId=itFV.faceId(); - int vertId=itFV.vertId(); - // Validate if constant by checking against the first element - if (isConstant && fvi>0) { - if (not GfIsClose((*data)[0], (*data)[fvi], 1e-9)) { - isConstant=false; + if (not colorSetRGBData or not colorSetAlphaData or not colorSetAssignmentIndices) { + return; + } + + const size_t numValues = colorSetRGBData->size(); + if (numValues == 0) { + return; + } + + if (colorSetAlphaData->size() != numValues) { + TF_CODING_ERROR("Unequal sizes for color (%zu) and alpha (%zu)", + colorSetRGBData->size(), colorSetAlphaData->size()); + } + + // We maintain a map of values (color AND alpha together) to those values' + // indices in our unique value arrays (color and alpha separate). + std::unordered_map, ValuesEqual > valuesSet; + VtArray uniqueColors; + VtArray uniqueAlphas; + VtArray uniqueIndices; + + for (size_t i = 0; i < colorSetAssignmentIndices->size(); ++i) { + int index = (*colorSetAssignmentIndices)[i]; + + if (index < 0 or index >= numValues) { + // This is an unassigned or otherwise unknown index, so just keep it. + uniqueIndices.push_back(index); + continue; + } + + const GfVec3f color = (*colorSetRGBData)[index]; + const float alpha = (*colorSetAlphaData)[index]; + const GfVec4f value(color[0], color[1], color[2], alpha); + + int uniqueIndex = -1; + + auto inserted = valuesSet.insert( + std::pair(value, + uniqueColors.size())); + if (inserted.second) { + // This is a new value, so add it to the arrays. + uniqueColors.push_back(GfVec3f(value[0], value[1], value[2])); + uniqueAlphas.push_back(value[3]); + uniqueIndex = uniqueColors.size() - 1; + } else { + // This is an existing value, so re-use the original's index. + uniqueIndex = inserted.first->second; + } + + uniqueIndices.push_back(uniqueIndex); + } + + // If we reduced the number of values by merging, copy the results back. + if (uniqueColors.size() < numValues) { + (*colorSetRGBData) = uniqueColors; + (*colorSetAlphaData) = uniqueAlphas; + (*colorSetAssignmentIndices) = uniqueIndices; + } +} + +// This function tries to compress faceVarying primvar indices to uniform, +// vertex, or constant interpolation if possible. This will potentially shrink +// the indices array and will update the interpolation if any compression was +// possible. +static +void +_CompressFaceVaryingPrimvarIndices( + const MFnMesh& mesh, + TfToken *interpolation, + VtArray* assignmentIndices) +{ + if (not interpolation or + not assignmentIndices or + assignmentIndices->size() == 0) { + return; + } + + int numPolygons = mesh.numPolygons(); + VtArray uniformAssignments; + uniformAssignments.assign((size_t)numPolygons, -2); + + int numVertices = mesh.numVertices(); + VtArray vertexAssignments; + vertexAssignments.assign((size_t)numVertices, -2); + + // We assume that the data is constant/uniform/vertex until we can + // prove otherwise that two components have differing values. + bool isConstant = true; + bool isUniform = true; + bool isVertex = true; + + MItMeshFaceVertex itFV(mesh.object()); + unsigned int fvi = 0; + for (itFV.reset(); not itFV.isDone(); itFV.next(), ++fvi) { + int faceIndex = itFV.faceId(); + int vertexIndex = itFV.vertId(); + + int assignedIndex = (*assignmentIndices)[fvi]; + + if (isConstant) { + if (assignedIndex != (*assignmentIndices)[0]) { + isConstant = false; } } - // Validate if uniform by storing the first value on a given face - // and the if already stored, check if being a different value - // on the same face + if (isUniform) { - if (valueOnFace[faceId]) { - if (not GfIsClose(faceValue[faceId], - (*data)[fvi], 1e-9)) { - isUniform=false; - } - } else { - valueOnFace[faceId]=true; - faceValue[faceId]=(*data)[fvi]; + if (uniformAssignments[faceIndex] < -1) { + // No value for this face yet, so store one. + uniformAssignments[faceIndex] = assignedIndex; + } else if (assignedIndex != uniformAssignments[faceIndex]) { + isUniform = false; } } - // Validate if vertex by storing the first value on a given vertex - // and the if already stored, check if being a different value - // on the same vertex + if (isVertex) { - if (valueOnVertex[vertId]) { - if (not GfIsClose(vertexValue[vertId], - (*data)[fvi], 1e-9)) { - isVertex=false; - } - } else { - valueOnVertex[vertId]=true; - vertexValue[vertId]=(*data)[fvi]; + if (vertexAssignments[vertexIndex] < -1) { + // No value for this vertex yet, so store one. + vertexAssignments[vertexIndex] = assignedIndex; + } else if (assignedIndex != vertexAssignments[vertexIndex]) { + isVertex = false; } } - fvi++; + + if (not isConstant and not isUniform and not isVertex) { + // No compression will be possible, so stop trying. + break; + } } - + if (isConstant) { - data->resize(1); - *interpolation=UsdGeomTokens->constant; + assignmentIndices->resize(1); + *interpolation = UsdGeomTokens->constant; } else if (isUniform) { - *data=faceValue; - *interpolation=UsdGeomTokens->uniform; + *assignmentIndices = uniformAssignments; + *interpolation = UsdGeomTokens->uniform; } else if(isVertex) { - *data=vertexValue; - *interpolation=UsdGeomTokens->vertex; + *assignmentIndices = vertexAssignments; + *interpolation = UsdGeomTokens->vertex; } else { - *interpolation=UsdGeomTokens->faceVarying; + *interpolation = UsdGeomTokens->faceVarying; } } @@ -124,108 +210,183 @@ static inline GfVec3f _LinearColorFromColorSet( const MColor& mayaColor, - bool isDisplayColor) + bool shouldConvertToLinear) { // we assume all color sets except displayColor are in linear space. // if we got a color from colorSetData and we're a displayColor, we // need to convert it to linear. GfVec3f c(mayaColor[0], mayaColor[1], mayaColor[2]); - if (isDisplayColor) { + if (shouldConvertToLinear) { return GfConvertDisplayToLinear(c); } return c; } -// Collect values from the colorset -// If gathering for displayColor, set the unpainted values to -// the underlying shaders values, else set to 1,1,1,1 -// Values are gathered per "facevertex" but then the data -// is compressed to constant, uniform and vertex if possible -// RGB and Alpha data are compressed independently -// RGBA data is compressed as a single Vec4f array -// NOTE: We could only fill RGB and Alpha and then -// do a merge, compress and unmerge if RGBA is needed -// but for code simplicity we always fill the 3 arrays +/// Collect values from the color set named \p colorSet. +/// If \p isDisplayColor is true and this color set represents displayColor, +/// the unauthored/unpainted values in the color set will be filled in using +/// the shader values in \p shadersRGBData and \p shadersAlphaData if available. +/// Values are gathered per face vertex, but then the data is compressed to +/// vertex, uniform, or constant interpolation if possible. +/// Unauthored/unpainted values will be given the index -1. bool MayaMeshWriter::_GetMeshColorSetData( - MFnMesh& m, - MString colorSet, - bool isDisplayColor, - const VtArray& shadersRGBData, - const VtArray& shadersAlphaData, - VtArray *RGBData, TfToken *RGBInterp, - VtArray *RGBAData, TfToken *RGBAInterp, - VtArray *AlphaData, TfToken *AlphaInterp, - MFnMesh::MColorRepresentation *colorSetRep, - bool *clamped) + MFnMesh& mesh, + MString colorSet, + bool isDisplayColor, + const VtArray& shadersRGBData, + const VtArray& shadersAlphaData, + const VtArray& shadersAssignmentIndices, + VtArray* colorSetRGBData, + VtArray* colorSetAlphaData, + TfToken* interpolation, + VtArray* colorSetAssignmentIndices, + MFnMesh::MColorRepresentation* colorSetRep, + bool* clamped) { - // If there are no colors, return immediately as failure - if (m.numColors(colorSet)==0) { + // If there are no colors, return immediately as failure. + if (mesh.numColors(colorSet) == 0) { return false; } - - // Get ColorSet representation and clamping - *colorSetRep = m.getColorRepresentation(colorSet); - *clamped = m.isColorClamped(colorSet); - + MColorArray colorSetData; - const MColor unsetColor(-FLT_MAX,-FLT_MAX,-FLT_MAX,-FLT_MAX); - if (m.getFaceVertexColors (colorSetData, &colorSet, &unsetColor) - == MS::kFailure) { + const MColor unsetColor(-FLT_MAX, -FLT_MAX, -FLT_MAX, -FLT_MAX); + if (mesh.getFaceVertexColors(colorSetData, &colorSet, &unsetColor) + == MS::kFailure) { return false; } - // Resize the returning containers with FaceVertex amounts - RGBData->resize(colorSetData.length()); - AlphaData->resize(colorSetData.length()); - RGBAData->resize(colorSetData.length()); - - // Loop over every face vertex to populate colorArray - MItMeshFaceVertex itFV( m.object() ); - int fvi=0; - for( itFV.reset(); !itFV.isDone(); itFV.next() ) { - // Initialize RGBData and AlphaData to (1,1,1,1) and then - // if isDisplayColor from shader values (constant or uniform) - GfVec3f RGBValue=GfVec3f(1.0,1.0,1.0); - float AlphaValue=1; - - // NOTE, shadersRGBData is already linear - if (isDisplayColor && shadersRGBData.size() == static_cast(m.numPolygons())) { - RGBValue=shadersRGBData[itFV.faceId()]; - } else if (isDisplayColor && shadersRGBData.size()==1) { - RGBValue=shadersRGBData[0]; + if (colorSetData.length() == 0) { + return false; + } + + // Get the color set representation and clamping. + *colorSetRep = mesh.getColorRepresentation(colorSet); + *clamped = mesh.isColorClamped(colorSet); + + // We'll populate the assignment indices for every face vertex, but we'll + // only push values into the data if the face vertex has a value. All face + // vertices are initially unassigned/unauthored. + colorSetRGBData->clear(); + colorSetAlphaData->clear(); + colorSetAssignmentIndices->assign((size_t)colorSetData.length(), -1); + *interpolation = UsdGeomTokens->faceVarying; + + // Loop over every face vertex to populate the value arrays. + MItMeshFaceVertex itFV(mesh.object()); + unsigned int fvi = 0; + for (itFV.reset(); not itFV.isDone(); itFV.next(), ++fvi) { + // If this is a displayColor color set, we may need to fallback on the + // bound shader colors/alphas for this face in some cases. In + // particular, if the color set is alpha-only, we fallback on the + // shader values for the color. If the color set is RGB-only, we + // fallback on the shader values for alpha only. If there's no authored + // color for this face vertex, we use both the color AND alpha values + // from the shader. + bool useShaderColorFallback = false; + bool useShaderAlphaFallback = false; + if (isDisplayColor) { + if (colorSetData[fvi] == unsetColor) { + useShaderColorFallback = true; + useShaderAlphaFallback = true; + } else if (*colorSetRep == MFnMesh::kAlpha) { + // The color set does not provide color, so fallback on shaders. + useShaderColorFallback = true; + } else if (*colorSetRep == MFnMesh::kRGB) { + // The color set does not provide alpha, so fallback on shaders. + useShaderAlphaFallback = true; + } } - if (isDisplayColor && shadersAlphaData.size() == static_cast(m.numPolygons())) { - AlphaValue=shadersAlphaData[itFV.faceId()]; - } else if (isDisplayColor && shadersAlphaData.size()==1) { - AlphaValue=shadersAlphaData[0]; + + // If we're exporting displayColor and we use the value from the color + // set, we need to convert it to linear. + bool convertDisplayColorToLinear = isDisplayColor; + + // Shader values for the mesh could be constant + // (shadersAssignmentIndices is empty) or uniform. + int faceIndex = itFV.faceId(); + if (useShaderColorFallback) { + // There was no color value in the color set to use, so we use the + // shader color, or the default color if there is no shader color. + // This color will already be in linear space, so don't convert it + // again. + convertDisplayColorToLinear = false; + + int valueIndex = -1; + if (shadersAssignmentIndices.empty()) { + if (shadersRGBData.size() == 1) { + valueIndex = 0; + } + } else if (faceIndex >= 0 and faceIndex < shadersAssignmentIndices.size()) { + int tmpIndex = shadersAssignmentIndices[faceIndex]; + if (tmpIndex >= 0 and tmpIndex < shadersRGBData.size()) { + valueIndex = tmpIndex; + } + } + if (valueIndex >= 0) { + colorSetData[fvi][0] = shadersRGBData[valueIndex][0]; + colorSetData[fvi][1] = shadersRGBData[valueIndex][1]; + colorSetData[fvi][2] = shadersRGBData[valueIndex][2]; + } else { + // No shader color to fallback on. Use the default shader color. + colorSetData[fvi][0] = _ShaderDefaultRGB[0]; + colorSetData[fvi][1] = _ShaderDefaultRGB[1]; + colorSetData[fvi][2] = _ShaderDefaultRGB[2]; + } } - // Assign retrieved color set values - // unauthored color set values are ==unsetColor - // for those we use the previously initialized values - if (colorSetData[fvi]!=unsetColor) { - if ((*colorSetRep) == MFnMesh::kAlpha) { - AlphaValue=colorSetData[fvi][3]; - } else if ((*colorSetRep) == MFnMesh::kRGB) { - RGBValue=_LinearColorFromColorSet(colorSetData[fvi], isDisplayColor); - AlphaValue=1; - } else if ((*colorSetRep) == MFnMesh::kRGBA) { - RGBValue=_LinearColorFromColorSet(colorSetData[fvi], isDisplayColor); - AlphaValue=colorSetData[fvi][3]; + if (useShaderAlphaFallback) { + int valueIndex = -1; + if (shadersAssignmentIndices.empty()) { + if (shadersAlphaData.size() == 1) { + valueIndex = 0; + } + } else if (faceIndex >= 0 and faceIndex < shadersAssignmentIndices.size()) { + int tmpIndex = shadersAssignmentIndices[faceIndex]; + if (tmpIndex >= 0 and tmpIndex < shadersAlphaData.size()) { + valueIndex = tmpIndex; + } + } + if (valueIndex >= 0) { + colorSetData[fvi][3] = shadersAlphaData[valueIndex]; + } else { + // No shader alpha to fallback on. Use the default shader alpha. + colorSetData[fvi][3] = _ShaderDefaultAlpha; } } - (*RGBData)[fvi]=RGBValue; - (*AlphaData)[fvi]=AlphaValue; - (*RGBAData)[fvi]=GfVec4f(RGBValue[0], RGBValue[1], - RGBValue[2], AlphaValue); - fvi++; - } - compressFVPrimvar(m, RGBData, RGBInterp); - compressFVPrimvar(m, AlphaData, AlphaInterp); - compressFVPrimvar(m, RGBAData, RGBAInterp); + + // If we have a color/alpha value, add it to the data to be returned. + if (colorSetData[fvi] != unsetColor) { + GfVec3f rgbValue = _ColorSetDefaultRGB; + float alphaValue = _ColorSetDefaultAlpha; + + if (useShaderColorFallback or + (*colorSetRep == MFnMesh::kRGB) or + (*colorSetRep == MFnMesh::kRGBA)) { + rgbValue = _LinearColorFromColorSet(colorSetData[fvi], + convertDisplayColorToLinear); + } + if (useShaderAlphaFallback or + (*colorSetRep == MFnMesh::kAlpha) or + (*colorSetRep == MFnMesh::kRGBA)) { + alphaValue = colorSetData[fvi][3]; + } + + colorSetRGBData->push_back(rgbValue); + colorSetAlphaData->push_back(alphaValue); + (*colorSetAssignmentIndices)[fvi] = colorSetRGBData->size() - 1; + } + } + + _MergeEquivalentColorSetValues(colorSetRGBData, + colorSetAlphaData, + colorSetAssignmentIndices); + _CompressFaceVaryingPrimvarIndices(mesh, + interpolation, + colorSetAssignmentIndices); + return true; } -// We assumed that primvars in USD are always unclamped so we add the +// We assumed that primvars in USD are always unclamped so we add the // clamped custom data ONLY when clamping is set to true in the colorset static void SetPVCustomData(UsdAttribute obj, bool clamped) { @@ -236,107 +397,189 @@ static void SetPVCustomData(UsdAttribute obj, bool clamped) bool MayaMeshWriter::_createAlphaPrimVar( - UsdGeomGprim &primSchema, const TfToken name, - const VtArray& data, TfToken interpolation, - bool clamped) + UsdGeomGprim &primSchema, + const TfToken& name, + const VtArray& data, + const TfToken& interpolation, + const VtArray& assignmentIndices, + const int unassignedValueIndex, + bool clamped) { - unsigned int numValues=data.size(); - if (numValues==0) return false; - TfToken interp=interpolation; - if (numValues==1 && interp==UsdGeomTokens->constant) { - interp=TfToken(); - } - UsdGeomPrimvar colorSet = primSchema.CreatePrimvar(name, - SdfValueTypeNames->FloatArray, - interp ); - colorSet.Set(data); - SetPVCustomData(colorSet.GetAttr(), clamped); + unsigned int numValues = data.size(); + if (numValues == 0) { + return false; + } + + TfToken interp = interpolation; + if (numValues == 1 and interp == UsdGeomTokens->constant) { + interp = TfToken(); + } + + UsdGeomPrimvar primVar = + primSchema.CreatePrimvar(name, + SdfValueTypeNames->FloatArray, + interp); + + primVar.Set(data); + + if (not assignmentIndices.empty()) { + primVar.SetIndices(assignmentIndices); + if (unassignedValueIndex != primVar.GetUnauthoredValuesIndex()) { + primVar.SetUnauthoredValuesIndex(unassignedValueIndex); + } + } + + SetPVCustomData(primVar.GetAttr(), clamped); + return true; } bool MayaMeshWriter::_createRGBPrimVar( - UsdGeomGprim &primSchema, const TfToken name, - const VtArray& data, TfToken interpolation, - bool clamped) + UsdGeomGprim &primSchema, + const TfToken& name, + const VtArray& data, + const TfToken& interpolation, + const VtArray& assignmentIndices, + const int unassignedValueIndex, + bool clamped) { - unsigned int numValues=data.size(); - if (numValues==0) return false; - TfToken interp=interpolation; - if (numValues==1 && interp==UsdGeomTokens->constant) { - interp=TfToken(); - } - UsdGeomPrimvar colorSet = primSchema.CreatePrimvar(name, - SdfValueTypeNames->Color3fArray, - interp ); - colorSet.Set(data); - SetPVCustomData(colorSet.GetAttr(), clamped); + unsigned int numValues = data.size(); + if (numValues == 0) { + return false; + } + + TfToken interp = interpolation; + if (numValues == 1 and interp == UsdGeomTokens->constant) { + interp = TfToken(); + } + + UsdGeomPrimvar primVar = + primSchema.CreatePrimvar(name, + SdfValueTypeNames->Color3fArray, + interp); + + primVar.Set(data); + + if (not assignmentIndices.empty()) { + primVar.SetIndices(assignmentIndices); + if (unassignedValueIndex != primVar.GetUnauthoredValuesIndex()) { + primVar.SetUnauthoredValuesIndex(unassignedValueIndex); + } + } + + SetPVCustomData(primVar.GetAttr(), clamped); + return true; } bool MayaMeshWriter::_createRGBAPrimVar( - UsdGeomGprim &primSchema, const TfToken name, - const VtArray& RGBAData, TfToken RGBAInterp, - bool clamped) + UsdGeomGprim &primSchema, + const TfToken& name, + const VtArray& rgbData, + const VtArray& alphaData, + const TfToken& interpolation, + const VtArray& assignmentIndices, + const int unassignedValueIndex, + bool clamped) { - unsigned int numValues=RGBAData.size(); - if (numValues==0) return false; - TfToken interp=RGBAInterp; - if (numValues==1 && interp==UsdGeomTokens->constant) { - interp=TfToken(); - } - UsdGeomPrimvar colorSet = primSchema.CreatePrimvar(name, - SdfValueTypeNames->Float4Array, - interp ); - colorSet.Set(RGBAData); - SetPVCustomData(colorSet.GetAttr(), clamped); + unsigned int numValues = rgbData.size(); + if (numValues == 0 or numValues != alphaData.size()) { + return false; + } + + TfToken interp = interpolation; + if (numValues == 1 and interp == UsdGeomTokens->constant) { + interp = TfToken(); + } + + UsdGeomPrimvar primVar = + primSchema.CreatePrimvar(name, + SdfValueTypeNames->Color4fArray, + interp); + + VtArray rgbaData(numValues); + for (size_t i = 0; i < rgbaData.size(); ++i) { + rgbaData[i] = GfVec4f(rgbData[i][0], rgbData[i][1], rgbData[i][2], + alphaData[i]); + } + + primVar.Set(rgbaData); + + if (not assignmentIndices.empty()) { + primVar.SetIndices(assignmentIndices); + if (unassignedValueIndex != primVar.GetUnauthoredValuesIndex()) { + primVar.SetUnauthoredValuesIndex(unassignedValueIndex); + } + } + + SetPVCustomData(primVar.GetAttr(), clamped); + return true; } -bool MayaMeshWriter::_setDisplayPrimVar( - UsdGeomGprim &primSchema, - MFnMesh::MColorRepresentation colorRep, - VtArray RGBData, TfToken RGBInterp, - VtArray AlphaData, TfToken AlphaInterp, - bool clamped, bool authored) +bool MayaMeshWriter::_addDisplayPrimvars( + UsdGeomGprim &primSchema, + const MFnMesh::MColorRepresentation colorRep, + const VtArray& RGBData, + const VtArray& AlphaData, + const TfToken& interpolation, + const VtArray& assignmentIndices, + const int unassignedValueIndex, + const bool clamped, + const bool authored) { - + // If we already have an authored value, don't try to write a new one. UsdAttribute colorAttr = primSchema.GetDisplayColorAttr(); if (not colorAttr.HasAuthoredValueOpinion() and not RGBData.empty()) { UsdGeomPrimvar displayColor = primSchema.GetDisplayColorPrimvar(); - if (RGBInterp != displayColor.GetInterpolation()) - displayColor.SetInterpolation(RGBInterp); + if (interpolation != displayColor.GetInterpolation()) { + displayColor.SetInterpolation(interpolation); + } displayColor.Set(RGBData); - bool authRGB=authored; - if (colorRep == MFnMesh::kAlpha) { authRGB=false; } + if (not assignmentIndices.empty()) { + displayColor.SetIndices(assignmentIndices); + if (unassignedValueIndex != displayColor.GetUnauthoredValuesIndex()) { + displayColor.SetUnauthoredValuesIndex(unassignedValueIndex); + } + } + bool authRGB = authored; + if (colorRep == MFnMesh::kAlpha) { + authRGB = false; + } if (authRGB) { colorAttr.SetCustomDataByKey(TfToken("Authored"), VtValue(authRGB)); SetPVCustomData(colorAttr, clamped); } } - - UsdAttribute alphaAttr = primSchema.GetDisplayOpacityAttr(); - // if we already have an authored value, don't try to write a new one. - if (not alphaAttr.HasAuthoredValueOpinion()) { - - if (not AlphaData.empty()) { - // we consider a single alpha value that is 1.0 to be the "default" - // value. We only want to write values that are not the "default". - bool hasDefaultAlpha = AlphaData.size() == 1 and GfIsClose(AlphaData[0], 1.0, 1e-9); - if (not hasDefaultAlpha) { - UsdGeomPrimvar displayOpacity = primSchema.GetDisplayOpacityPrimvar(); - if (AlphaInterp != displayOpacity.GetInterpolation()) - displayOpacity.SetInterpolation(AlphaInterp); - displayOpacity.Set(AlphaData); - bool authAlpha=authored; - if (colorRep == MFnMesh::kRGB) { authAlpha=false; } - if (authAlpha) { - alphaAttr.SetCustomDataByKey(TfToken("Authored"), VtValue(authAlpha)); - SetPVCustomData(alphaAttr, clamped); + UsdAttribute alphaAttr = primSchema.GetDisplayOpacityAttr(); + if (not alphaAttr.HasAuthoredValueOpinion() and not AlphaData.empty()) { + // we consider a single alpha value that is 1.0 to be the "default" + // value. We only want to write values that are not the "default". + bool hasDefaultAlpha = AlphaData.size() == 1 and GfIsClose(AlphaData[0], 1.0, 1e-9); + if (not hasDefaultAlpha) { + UsdGeomPrimvar displayOpacity = primSchema.GetDisplayOpacityPrimvar(); + if (interpolation != displayOpacity.GetInterpolation()) { + displayOpacity.SetInterpolation(interpolation); + } + displayOpacity.Set(AlphaData); + if (not assignmentIndices.empty()) { + displayOpacity.SetIndices(assignmentIndices); + if (unassignedValueIndex != displayOpacity.GetUnauthoredValuesIndex()) { + displayOpacity.SetUnauthoredValuesIndex(unassignedValueIndex); } } + bool authAlpha = authored; + if (colorRep == MFnMesh::kRGB) { + authAlpha = false; + } + if (authAlpha) { + alphaAttr.SetCustomDataByKey(TfToken("Authored"), VtValue(authAlpha)); + SetPVCustomData(alphaAttr, clamped); + } } } + return true; } diff --git a/third_party/maya/lib/usdMaya/MayaNurbsSurfaceWriter.cpp b/third_party/maya/lib/usdMaya/MayaNurbsSurfaceWriter.cpp index 0545375ec4..0433bd9943 100644 --- a/third_party/maya/lib/usdMaya/MayaNurbsSurfaceWriter.cpp +++ b/third_party/maya/lib/usdMaya/MayaNurbsSurfaceWriter.cpp @@ -89,24 +89,34 @@ bool MayaNurbsSurfaceWriter::writeNurbsSurfaceAttrs( // shader assignment possible. if (getArgs().exportDisplayColor) { VtArray RGBData; - TfToken RGBInterp; VtArray AlphaData; - TfToken AlphaInterp; - if (PxrUsdMayaUtil::GetLinearShaderColor(nurbs, 0, - &RGBData, &RGBInterp, - &AlphaData, &AlphaInterp)) { + TfToken interpolation; + VtArray assignmentIndices; + if (PxrUsdMayaUtil::GetLinearShaderColor(nurbs, + &RGBData, + &AlphaData, + &interpolation, + &assignmentIndices)) { if (RGBData.size()>0) { UsdGeomPrimvar dispColor = primSchema.GetDisplayColorPrimvar(); - if (RGBInterp != dispColor.GetInterpolation()) - dispColor.SetInterpolation(RGBInterp); + if (interpolation != dispColor.GetInterpolation()) { + dispColor.SetInterpolation(interpolation); + } dispColor.Set(RGBData); + if (not assignmentIndices.empty()) { + dispColor.SetIndices(assignmentIndices); + } } if (AlphaData.size() > 0 && GfIsClose(AlphaData[0], 1.0, 1e-9)==false) { UsdGeomPrimvar dispOpacity = primSchema.GetDisplayOpacityPrimvar(); - if (AlphaInterp != dispOpacity.GetInterpolation()) - dispOpacity.SetInterpolation(AlphaInterp); + if (interpolation != dispOpacity.GetInterpolation()) { + dispOpacity.SetInterpolation(interpolation); + } dispOpacity.Set(AlphaData); + if (not assignmentIndices.empty()) { + dispOpacity.SetIndices(assignmentIndices); + } } } } diff --git a/third_party/maya/lib/usdMaya/util.cpp b/third_party/maya/lib/usdMaya/util.cpp index 0f6ab04560..b19ace60a4 100644 --- a/third_party/maya/lib/usdMaya/util.cpp +++ b/third_party/maya/lib/usdMaya/util.cpp @@ -24,20 +24,23 @@ #include "usdMaya/util.h" #include "pxr/base/gf/gamma.h" +#include "pxr/base/tf/hashmap.h" #include "pxr/usd/usdGeom/mesh.h" +#include +#include +#include #include +#include #include #include +#include +#include #include -#include -#include +#include #include #include -#include -#include -#include -#include + // return seconds per frame double PxrUsdMayaUtil::spf() @@ -435,47 +438,82 @@ std::string PxrUsdMayaUtil::SanitizeColorSetName(const std::string& name) return name.substr(namePos); } -// Get array (constant or per face) of attached shaders -// Pass numFaces==0 if retrieving shaders on a non polymesh -static bool +// Get array (constant or per component) of attached shaders +// Pass a non-zero value for numComponents when retrieving shaders on an object +// that supports per-component shader assignment (e.g. faces of a polymesh). +// In this case, shaderObjs will be the length of the number of shaders +// assigned to the object. assignmentIndices will be the length of +// numComponents, with values indexing into shaderObjs. +// When numComponents is zero, shaderObjs will be of length 1 and +// assignmentIndices will be empty. +static +bool _getAttachedMayaShaderObjects( - const MFnDagNode &node, const int numFaces, MObjectArray *shaderObjs) + const MFnDagNode &node, + const unsigned int numComponents, + MObjectArray *shaderObjs, + VtArray *assignmentIndices) { bool hasShader=false; MStatus status; - MObjectArray sgObjs; + + // This structure maps shader object names to their indices in the + // shaderObjs array. We use this to make sure that we add each unique + // shader to shaderObjs only once. + TfHashMap shaderPlugsMap; + + shaderObjs->clear(); + assignmentIndices->clear(); + + MObjectArray setObjs; MObjectArray compObjs; - node.getConnectedSetsAndMembers(0, sgObjs, compObjs, true); // Assuming that not using instancing - // If we have one shader connected we return a single shader - // If there are multiple shaders, we return an per face array of connected shaders - if (sgObjs.length()==1 or numFaces==0) { - shaderObjs->setLength(1); - } else if (sgObjs.length()>1) { - shaderObjs->setLength(numFaces); - } - for (unsigned int i=0; i < sgObjs.length(); ++i) { + node.getConnectedSetsAndMembers(0, setObjs, compObjs, true); // Assuming that not using instancing + + // If we have multiple components and either multiple sets or one set with + // only a subset of the object in it, we'll keep track of the assignments + // for all components in assignmentIndices. We initialize all of the + // assignments as unassigned using a value of -1. + if (numComponents > 1 and + (setObjs.length() > 1 or + (setObjs.length() == 1 and not compObjs[0].isNull()))) { + assignmentIndices->assign((size_t)numComponents, -1); + } + + for (unsigned int i=0; i < setObjs.length(); ++i) { // Get associated Set and Shading Group - MFnSet setFn( sgObjs[i], &status ); + MFnSet setFn(setObjs[i], &status); MPlug seSurfaceShaderPlg = setFn.findPlug("surfaceShader", &status); // Find connection shader->shadingGroup MPlugArray plgCons; seSurfaceShaderPlg.connectedTo(plgCons, true, false, &status); - MObject shaderObj; - if ( plgCons.length() > 0 ) { - hasShader = true; - shaderObj = plgCons[0].node(); - } - // If we have multiple shaders, we assign them per face - if (sgObjs.length()>1 and numFaces>0) { - MItMeshPolygon faceIt( node.dagPath(), compObjs[i] ); - for ( faceIt.reset() ; !faceIt.isDone() ; faceIt.next() ){ - (*shaderObjs)[faceIt.index()]=shaderObj; + if (plgCons.length() == 0) { + continue; + } + + hasShader = true; + MPlug shaderPlug = plgCons[0]; + MObject shaderObj = shaderPlug.node(); + + auto inserted = shaderPlugsMap.insert( + std::pair(shaderPlug.name().asChar(), + shaderObjs->length())); + if (inserted.second) { + shaderObjs->append(shaderObj); + } + + // If we are tracking per-component assignments, mark all components of + // this set as assigned to this shader. + if (not assignmentIndices->empty()) { + size_t shaderIndex = inserted.first->second; + + MItMeshPolygon faceIt(node.dagPath(), compObjs[i]); + for (faceIt.reset(); not faceIt.isDone(); faceIt.next()) { + (*assignmentIndices)[faceIt.index()] = shaderIndex; } - } else { - (*shaderObjs)[0]=shaderObj; } } + return hasShader; } @@ -546,99 +584,168 @@ _GetColorAndTransparencyFromDepNode( } static void -_getMayaShadersColor(const int numFaces, const MObjectArray &shaderObjs, - VtArray *RGBData, TfToken *RGBInterp, - VtArray *AlphaData, TfToken *AlphaInterp) +_getMayaShadersColor( + const MObjectArray &shaderObjs, + VtArray *RGBData, + VtArray *AlphaData) { MStatus status; - bool constantRGB=true; - bool constantAlpha=true; - if (RGBData) RGBData->resize(shaderObjs.length()); - if (AlphaData) AlphaData->resize(shaderObjs.length()); - for (unsigned int i=0; i < shaderObjs.length(); ++i) { + + if (shaderObjs.length() == 0) { + return; + } + + if (RGBData) { + RGBData->resize(shaderObjs.length()); + } + if (AlphaData) { + AlphaData->resize(shaderObjs.length()); + } + + for (unsigned int i = 0; i < shaderObjs.length(); ++i) { // Initialize RGB and Alpha to (1,1,1,1) if (RGBData) { (*RGBData)[i][0] = 1.0; (*RGBData)[i][1] = 1.0; (*RGBData)[i][2] = 1.0; } - if (AlphaData) { (*AlphaData)[i] = 1.0; } - if (!shaderObjs[i].isNull()) { - - // first, we assume the shader is a lambert and try that API. if - // not, we try our next best guess. - bool gotValues = _GetColorAndTransparencyFromLambert( - shaderObjs[i], - RGBData ? &(*RGBData)[i] : NULL, - AlphaData ? &(*AlphaData)[i] : NULL) - - or _GetColorAndTransparencyFromDepNode( - shaderObjs[i], - RGBData ? &(*RGBData)[i] : NULL, - AlphaData ? &(*AlphaData)[i] : NULL); - - if (gotValues) { - if (RGBData) { - for (int j = 0; j<3; j++) { - if (GfIsClose((*RGBData)[0][j], - (*RGBData)[i][j], 1e-9)==false) { - constantRGB=false; - } - } - } - if (AlphaData) { - if (GfIsClose((*AlphaData)[0], (*AlphaData)[i], 1e-9)==false) { - constantAlpha=false; - } - } - } - else { - MGlobal::displayError("Failed to get shaders colors at index: " + - MString(TfStringPrintf("%d", i).c_str()) + - ". Unable to retrieve ShaderBaseColor."); - } - } else { - MGlobal::displayError("Invalid Maya Shader Object at index: " + - MString(TfStringPrintf("%d", i).c_str()) + - ". Unable to retrieve ShaderBaseColor."); + if (AlphaData) { + (*AlphaData)[i] = 1.0; } - } - // If RGB or Alpha are constant, resize the array to 1 - if (RGBData) { - if (constantRGB) { - RGBData->resize(1); - *RGBInterp=UsdGeomTokens->constant; - } else if (RGBData->size() == static_cast(numFaces)) { - *RGBInterp=UsdGeomTokens->uniform; + + if (shaderObjs[i].isNull()) { + MGlobal::displayError("Invalid Maya Shader Object at index: " + + MString(TfStringPrintf("%d", i).c_str()) + + ". Unable to retrieve ShaderBaseColor."); + continue; } - } - if (AlphaData) { - if (constantAlpha) { - AlphaData->resize(1); - *AlphaInterp=UsdGeomTokens->constant; - } else if (AlphaData->size() == static_cast(numFaces)) { - *AlphaInterp=UsdGeomTokens->uniform; + + // first, we assume the shader is a lambert and try that API. if + // not, we try our next best guess. + bool gotValues = _GetColorAndTransparencyFromLambert( + shaderObjs[i], + RGBData ? &(*RGBData)[i] : NULL, + AlphaData ? &(*AlphaData)[i] : NULL) + + or _GetColorAndTransparencyFromDepNode( + shaderObjs[i], + RGBData ? &(*RGBData)[i] : NULL, + AlphaData ? &(*AlphaData)[i] : NULL); + + if (not gotValues) { + MGlobal::displayError("Failed to get shaders colors at index: " + + MString(TfStringPrintf("%d", i).c_str()) + + ". Unable to retrieve ShaderBaseColor."); } } } +static bool -PxrUsdMayaUtil::GetLinearShaderColor( +_GetLinearShaderColor( const MFnDagNode& node, - const int numFaces, - VtArray *RGBData, TfToken *RGBInterp, - VtArray *AlphaData, TfToken *AlphaInterp) + const unsigned int numComponents, + VtArray *RGBData, + VtArray *AlphaData, + TfToken *interpolation, + VtArray *assignmentIndices) { MObjectArray shaderObjs; - if (_getAttachedMayaShaderObjects(node, numFaces, &shaderObjs)) { - _getMayaShadersColor(numFaces, shaderObjs, - RGBData, RGBInterp, - AlphaData, AlphaInterp); + if (_getAttachedMayaShaderObjects(node, numComponents, &shaderObjs, assignmentIndices)) { + if (assignmentIndices and interpolation) { + if (assignmentIndices->empty()) { + *interpolation = UsdGeomTokens->constant; + } else { + *interpolation = UsdGeomTokens->uniform; + } + } + + _getMayaShadersColor(shaderObjs, RGBData, AlphaData); + return true; } + return false; } +bool +PxrUsdMayaUtil::GetLinearShaderColor( + const MFnDagNode& node, + VtArray *RGBData, + VtArray *AlphaData, + TfToken *interpolation, + VtArray *assignmentIndices) +{ + return _GetLinearShaderColor(node, + 0, + RGBData, + AlphaData, + interpolation, + assignmentIndices); +} + +bool +PxrUsdMayaUtil::GetLinearShaderColor( + const MFnMesh& mesh, + VtArray *RGBData, + VtArray *AlphaData, + TfToken *interpolation, + VtArray *assignmentIndices) +{ + unsigned int numComponents = mesh.numPolygons(); + return _GetLinearShaderColor(mesh, + numComponents, + RGBData, + AlphaData, + interpolation, + assignmentIndices); +} + +bool +PxrUsdMayaUtil::AddUnassignedColorAndAlphaIfNeeded( + VtArray* RGBData, + VtArray* AlphaData, + VtArray* assignmentIndices, + int* unassignedValueIndex, + const GfVec3f& defaultRGB, + const float defaultAlpha) +{ + if (not assignmentIndices or assignmentIndices->empty()) { + return false; + } + + if (RGBData and AlphaData and (RGBData->size() != AlphaData->size())) { + TF_CODING_ERROR("Unequal sizes for color (%zu) and opacity (%zu)", + RGBData->size(), AlphaData->size()); + } + + *unassignedValueIndex = -1; + + for (size_t i=0; i < assignmentIndices->size(); ++i) { + if ((*assignmentIndices)[i] >= 0) { + // This component has an assignment, so skip it. + continue; + } + + // We found an unassigned index. Add unassigned values to RGBData and + // AlphaData if we haven't already. + if (*unassignedValueIndex < 0) { + if (RGBData) { + RGBData->push_back(defaultRGB); + } + if (AlphaData) { + AlphaData->push_back(defaultAlpha); + } + *unassignedValueIndex = RGBData->size() - 1; + } + + // Assign the component the unassigned value index. + (*assignmentIndices)[i] = *unassignedValueIndex; + } + + return true; +} + MPlug PxrUsdMayaUtil::GetConnected(const MPlug& plug) { diff --git a/third_party/maya/lib/usdMaya/util.h b/third_party/maya/lib/usdMaya/util.h index e75cbf2a17..eef55e3d4b 100644 --- a/third_party/maya/lib/usdMaya/util.h +++ b/third_party/maya/lib/usdMaya/util.h @@ -29,16 +29,12 @@ #include "pxr/usd/usd/timeCode.h" #include -#include #include +#include +#include #include #include -#include -#include -#include -#include -class MFnDependencyNode; namespace PxrUsdMayaUtil { @@ -154,14 +150,52 @@ std::string SanitizeName(const std::string& name); // This to allow various pipeline to sanitize the colorset name for output std::string SanitizeColorSetName(const std::string& name); -// Get the basecolor from the bound shader. Returned colors will be in linear -// color space. +/// Get the base colors and opacities from the shader(s) bound to \p node. +/// Returned colors will be in linear color space. +/// +/// A single value for each of color and alpha will be returned, +/// interpolation will be constant, and assignmentIndices will be empty. +/// bool GetLinearShaderColor( const MFnDagNode& node, - const int numFaces, - VtArray *RGBData, TfToken *RGBInterp, - VtArray *AlphaData, TfToken *AlphaInterp); + VtArray *RGBData, + VtArray *AlphaData, + TfToken *interpolation, + VtArray *assignmentIndices); +/// Get the base colors and opacities from the shader(s) bound to \p mesh. +/// Returned colors will be in linear color space. +/// +/// If the entire mesh has a single shader assignment, a single value for each +/// of color and alpha will be returned, interpolation will be constant, and +/// assignmentIndices will be empty. +/// +/// Otherwise, a color and alpha value will be returned for each shader +/// assigned to any face of the mesh. \p assignmentIndices will be the length +/// of the number of faces with values indexing into the color and alpha arrays +/// representing per-face assignments. Faces with no assigned shader will have +/// a value of -1 in \p assignmentIndices. \p interpolation will be uniform. +/// +bool GetLinearShaderColor( + const MFnMesh& mesh, + VtArray *RGBData, + VtArray *AlphaData, + TfToken *interpolation, + VtArray *assignmentIndices); + +/// If any components in \p assignmentIndices are unassigned (-1), the given +/// default values will be added to RGBData and AlphaData and all of those +/// components will be assigned that index, which is returned in +/// \p unassignedValueIndex. +/// Returns true if unassigned values were added and indices were updated, or +/// false otherwise. +bool AddUnassignedColorAndAlphaIfNeeded( + VtArray* RGBData, + VtArray* AlphaData, + VtArray* assignmentIndices, + int* unassignedValueIndex, + const GfVec3f& defaultRGB, + const float defaultAlpha); MPlug GetConnected(const MPlug& plug); From b9b7a05a9551e8b1e7748b8b4113ffc95fa51bde Mon Sep 17 00:00:00 2001 From: c64kernal Date: Thu, 25 Aug 2016 10:20:56 -0700 Subject: [PATCH 007/380] Fix tripped verify when trying to use a surfaceShader with an error. Before this fix, when a user passed in a shader to Hydra with an error in it, we raised a failed verify. With this change, we now issue a warning to the user and fallback to the default surface shader. This allows the system to continue functioning so that users can more easily iterate on their hardware shaders. (Internal change: 1644990) --- pxr/imaging/lib/hd/drawBatch.cpp | 41 +++++++++++++++++++++++++++--- pxr/imaging/lib/hd/drawBatch.h | 2 +- pxr/imaging/lib/hd/glslProgram.cpp | 8 +++--- 3 files changed, 44 insertions(+), 7 deletions(-) diff --git a/pxr/imaging/lib/hd/drawBatch.cpp b/pxr/imaging/lib/hd/drawBatch.cpp index f7148b965e..859bd4ff03 100644 --- a/pxr/imaging/lib/hd/drawBatch.cpp +++ b/pxr/imaging/lib/hd/drawBatch.cpp @@ -28,9 +28,11 @@ #include "pxr/imaging/hd/codeGen.h" #include "pxr/imaging/hd/commandBuffer.h" #include "pxr/imaging/hd/geometricShader.h" +#include "pxr/imaging/hd/glslfxShader.h" #include "pxr/imaging/hd/glslProgram.h" #include "pxr/imaging/hd/lightingShader.h" #include "pxr/imaging/hd/mesh.h" +#include "pxr/imaging/hd/package.h" #include "pxr/imaging/hd/perfLog.h" #include "pxr/imaging/hd/renderPassState.h" #include "pxr/imaging/hd/renderPassShader.h" @@ -198,9 +200,38 @@ Hd_DrawBatch::_GetDrawingProgram(HdRenderPassStateSharedPtr const &state, shaders[2] = overrideShader ? overrideShader : firstDrawItem->GetSurfaceShader(); - _program.CompileShader(firstDrawItem, + if (not _program.CompileShader(firstDrawItem, + firstDrawItem->GetGeometricShader(), + shaders, indirect)) { + + // If we failed to compile the surface shader, replace it with the + // fallback surface shader and try again. + // XXX: Note that we only say "surface shader" here because it is + // currently the only one that we allow customization for. We + // expect all the other shaders to compile or else the shipping + // code is broken and needs to be fixed. When we open up more + // shaders for customization, we will need to check them as well. + + typedef boost::shared_ptr GlfGLSLFXSharedPtr; + typedef boost::shared_ptr + HdSurfaceShaderSharedPtr; + + GlfGLSLFXSharedPtr glslSurfaceFallback = + GlfGLSLFXSharedPtr( + new GlfGLSLFX(HdPackageFallbackSurfaceShader())); + + HdSurfaceShaderSharedPtr fallbackSurface = + HdSurfaceShaderSharedPtr( + new HdGLSLFXShader(glslSurfaceFallback)); + + shaders[2] = fallbackSurface; + + bool res = _program.CompileShader(firstDrawItem, firstDrawItem->GetGeometricShader(), shaders, indirect); + // We expect the fallback shader to always compile. + TF_VERIFY(res); + } _shaderHash = shaderHash; } @@ -208,7 +239,7 @@ Hd_DrawBatch::_GetDrawingProgram(HdRenderPassStateSharedPtr const &state, return _program; } -void +bool Hd_DrawBatch::_DrawingProgram::CompileShader( HdDrawItem const *drawItem, Hd_GeometricShaderPtr const &geometricShader, @@ -220,7 +251,7 @@ Hd_DrawBatch::_DrawingProgram::CompileShader( // glew has to be intialized if (not glLinkProgram) - return; + return false; // determine binding points and populate metaData HdBindingRequestVector customBindings; @@ -266,8 +297,12 @@ Hd_DrawBatch::_DrawingProgram::CompileShader( if (_glslProgram) { _resourceBinder.IntrospectBindings(_glslProgram->GetProgram().GetId()); + } else { + // Failed to compile and link a valid glsl program. + return false; } } + return true; } /* virtual */ diff --git a/pxr/imaging/lib/hd/drawBatch.h b/pxr/imaging/lib/hd/drawBatch.h index d62c630601..5f31e39f3b 100644 --- a/pxr/imaging/lib/hd/drawBatch.h +++ b/pxr/imaging/lib/hd/drawBatch.h @@ -97,7 +97,7 @@ class Hd_DrawBatch { public: _DrawingProgram() {} - void CompileShader( + bool CompileShader( HdDrawItem const *drawItem, Hd_GeometricShaderSharedPtr const &geometricShader, HdShaderSharedPtrVector const &shaders, diff --git a/pxr/imaging/lib/hd/glslProgram.cpp b/pxr/imaging/lib/hd/glslProgram.cpp index cb9b61d68a..91d32390ae 100644 --- a/pxr/imaging/lib/hd/glslProgram.cpp +++ b/pxr/imaging/lib/hd/glslProgram.cpp @@ -129,8 +129,9 @@ HdGLSLProgram::CompileShader(GLenum type, std::string logString; if (not HdGLUtils::GetShaderCompileStatus(shader, &logString)) { - TF_CODING_ERROR("Failed to compile shader (%s): \n%s", - shaderType, logString.c_str()); + // XXX:validation + TF_WARN("Failed to compile shader (%s): \n%s", + shaderType, logString.c_str()); } // attach the shader to the program @@ -167,7 +168,8 @@ HdGLSLProgram::Link() std::string logString; bool success = true; if (not HdGLUtils::GetProgramLinkStatus(program, &logString)) { - TF_CODING_ERROR("Failed to link shader: \n%s", logString.c_str()); + // XXX:validation + TF_WARN("Failed to link shader: \n%s", logString.c_str()); success = false; } From 22c987df458bc7a37b852b325f10e83e19450591 Mon Sep 17 00:00:00 2001 From: shen-chen Date: Thu, 25 Aug 2016 10:21:15 -0700 Subject: [PATCH 008/380] Fix view space issue for Katana USD VMP. (Internal change: 1645082) --- third_party/katana/plugin/vmp_usd/usdVMP.cpp | 30 +++++++++++++++++++- third_party/katana/plugin/vmp_usd/usdVMP.h | 2 ++ 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/third_party/katana/plugin/vmp_usd/usdVMP.cpp b/third_party/katana/plugin/vmp_usd/usdVMP.cpp index 19c9d0beb9..1842b92829 100644 --- a/third_party/katana/plugin/vmp_usd/usdVMP.cpp +++ b/third_party/katana/plugin/vmp_usd/usdVMP.cpp @@ -173,6 +173,20 @@ USDVMP::deepSetup(FnKat::ViewerModifierInput& input) // We are taking over all drawing for this location. input.overrideHostGeometry(); + + // store the view matrix + FnKat::DoubleAttribute mAttr = input.getDisplayMatrix(VIEW); + if (mAttr.isValid()) { + FnKat::DoubleConstVector vm = mAttr.getNearestSample(0.f); + _viewMatrix = + GfMatrix4d(GfRotation(GfVec3d(-1,0,0), 90), GfVec3d(0)) + * GfMatrix4d(vm[0], vm[1], vm[2], vm[3], + vm[4], vm[5], vm[6], vm[7], + vm[8], vm[9], vm[10], vm[11], + vm[12], vm[13], vm[14], vm[15]); + } else { + _viewMatrix = GfMatrix4d(1); + } } @@ -261,7 +275,17 @@ USDVMP::draw(FnKat::ViewerModifierInput& input) glGetIntegerv(GL_CURRENT_PROGRAM, &oldProgram); if (TF_VERIFY(_renderer)) { - _renderer->SetCameraStateFromOpenGL(); + // Copy camera from GL state, Katana does not provide it directly + GfMatrix4d modelViewMatrix, projectionMatrix; + GfVec4d viewport; + glGetDoublev(GL_MODELVIEW_MATRIX, modelViewMatrix.GetArray()); + glGetDoublev(GL_PROJECTION_MATRIX, projectionMatrix.GetArray()); + glGetDoublev(GL_VIEWPORT, &viewport[0]); + + _renderer->SetCameraState(_viewMatrix, projectionMatrix, viewport); + + GfMatrix4d modelMatrix = modelViewMatrix * (_viewMatrix.GetInverse()); + _renderer->SetRootTransform(modelMatrix); glPushAttrib(GL_LIGHTING_BIT | GL_ENABLE_BIT); @@ -272,7 +296,11 @@ USDVMP::draw(FnKat::ViewerModifierInput& input) glLightfv(GL_LIGHT0, GL_AMBIENT, params); } + glMatrixMode(GL_MODELVIEW); + glPushMatrix(); + glLoadMatrixd(_viewMatrix.GetArray()); _renderer->SetLightingStateFromOpenGL(); + glPopMatrix(); glPopAttrib(); diff --git a/third_party/katana/plugin/vmp_usd/usdVMP.h b/third_party/katana/plugin/vmp_usd/usdVMP.h index b75bfd42ce..2df9ead7bf 100644 --- a/third_party/katana/plugin/vmp_usd/usdVMP.h +++ b/third_party/katana/plugin/vmp_usd/usdVMP.h @@ -100,6 +100,8 @@ class USDVMP : public FnKat::ViewerModifier UsdImagingGLSharedPtr _renderer; UsdImagingGL::RenderParams _params; UsdPrim _prim; + + GfMatrix4d _viewMatrix; }; #endif From 1ab065224038b72ede3a7a6c2906beaa4443ac8b Mon Sep 17 00:00:00 2001 From: pixar-oss Date: Thu, 25 Aug 2016 10:21:47 -0700 Subject: [PATCH 009/380] When building the normals attribute, use data from the current time sample only, to avoid errors when point counts vary over time. (Internal change: 1645182) --- .../katana/lib/usdKatana/readPoints.cpp | 20 ++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/third_party/katana/lib/usdKatana/readPoints.cpp b/third_party/katana/lib/usdKatana/readPoints.cpp index 273fa0f6e9..dad489e1ad 100644 --- a/third_party/katana/lib/usdKatana/readPoints.cpp +++ b/third_party/katana/lib/usdKatana/readPoints.cpp @@ -49,6 +49,24 @@ _GetVelocityAttr( return velocitiesBuilder.build(); } +static FnKat::Attribute +_GetNormalsAttr(const UsdGeomPoints& points, double currentTime) +{ + VtVec3fArray normals; + if (not points.GetNormalsAttr().Get(&normals, currentTime)) + { + return FnKat::Attribute(); + } + + // float attribute list with a width of 3 + FnKat::FloatBuilder normalsBuilder(3); + std::vector normalsVec; + PxrUsdKatanaUtils::ConvertArrayToVector(normals, &normalsVec); + normalsBuilder.set(normalsVec); + + return normalsBuilder.build(); +} + static FnKat::Attribute _GetWidthAttr(const UsdGeomPoints& points, double currentTime) { @@ -102,7 +120,7 @@ PxrUsdKatanaReadPoints( } // normals - FnKat::Attribute normalsAttr = PxrUsdKatanaGeomGetNormalAttr(points, data); + FnKat::Attribute normalsAttr = _GetNormalsAttr(points, currentTime); if (normalsAttr.isValid()) { geometryBuilder.set("point.N", normalsAttr); From 68bdd36e392c6e257aac9cea4d9ea90abf85c9c0 Mon Sep 17 00:00:00 2001 From: spiffmon Date: Thu, 25 Aug 2016 10:21:56 -0700 Subject: [PATCH 010/380] Add overview.dox for UsdUI. (Internal change: 1645454) --- pxr/usd/lib/usdUI/overview.dox | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 pxr/usd/lib/usdUI/overview.dox diff --git a/pxr/usd/lib/usdUI/overview.dox b/pxr/usd/lib/usdUI/overview.dox new file mode 100644 index 0000000000..70b9675411 --- /dev/null +++ b/pxr/usd/lib/usdUI/overview.dox @@ -0,0 +1,22 @@ +/*! +\page usdUI_page_front UsdUI: USD UI Schemas +\if ( PIXAR_MFB_BUILD ) +\mainpage UsdUI: USD UI Schemas +\publicLib +\endif + +\section usdUI_overview Overview + +This module provides schemas for encoding information on USD prims +for client graphical user interface tools to use in deciding how to +organize and present the prims in GUI layouts. This information does +\em not guide the 3D rendering of a data contained in ascene, rather it's +about how to visualize the nodes in the graph that comprises a UsdStage. + +The primary classes are: + +\li UsdUINodeGraphNodeAPI - encodes layout information for prims that +participate in an interconnected (via relationships) graph, as would +prims in a shading network. + +*/ From c74660cc02e8235b31ceaa3ca1490cbcabc7d7ba Mon Sep 17 00:00:00 2001 From: gitamohr Date: Thu, 25 Aug 2016 10:22:06 -0700 Subject: [PATCH 011/380] usd: Cache whether or not a prim has a payload in the prim's flags. Prep work for properly dynamically including newly added payloads. Also some minor flag population cleanup. (Internal change: 1645500) --- pxr/usd/lib/usd/prim.cpp | 2 +- pxr/usd/lib/usd/primData.cpp | 34 +++++++++++++++++----------------- pxr/usd/lib/usd/primData.h | 3 +++ pxr/usd/lib/usd/primFlags.h | 4 ++++ 4 files changed, 25 insertions(+), 18 deletions(-) diff --git a/pxr/usd/lib/usd/prim.cpp b/pxr/usd/lib/usd/prim.cpp index 64b64f9241..dd5741ebc1 100644 --- a/pxr/usd/lib/usd/prim.cpp +++ b/pxr/usd/lib/usd/prim.cpp @@ -481,7 +481,7 @@ UsdPrim::HasAuthoredReferences() const bool UsdPrim::HasPayload() const { - return GetPrimIndex().HasPayload(); + return _Prim()->HasPayload(); } bool diff --git a/pxr/usd/lib/usd/primData.cpp b/pxr/usd/lib/usd/primData.cpp index d688c2363b..98142905af 100644 --- a/pxr/usd/lib/usd/primData.cpp +++ b/pxr/usd/lib/usd/primData.cpp @@ -110,10 +110,7 @@ Usd_PrimData::_ComposeAndCacheFlags(Usd_PrimDataConstPtr parent, _flags[Usd_PrimLoadedFlag] = true; _flags[Usd_PrimModelFlag] = true; _flags[Usd_PrimGroupFlag] = true; - _flags[Usd_PrimAbstractFlag] = false; _flags[Usd_PrimDefinedFlag] = true; - _flags[Usd_PrimClipsFlag] = false; - _flags[Usd_PrimInstanceFlag] = false; _flags[Usd_PrimMasterFlag] = isMasterPrim; } else { @@ -123,10 +120,14 @@ Usd_PrimData::_ComposeAndCacheFlags(Usd_PrimDataConstPtr parent, self.GetMetadata(SdfFieldKeys->Active, &active); _flags[Usd_PrimActiveFlag] = active; + // Cache whether or not this prim has a payload. + bool hasPayload = _primIndex->HasPayload(); + _flags[Usd_PrimHasPayloadFlag] = hasPayload; + // An active prim is loaded if it's loadable and in the load set, or // it's not loadable and its parent is loaded. - _flags[Usd_PrimLoadedFlag] = active and - (self.HasPayload() ? + _flags[Usd_PrimLoadedFlag] = active && + (hasPayload ? _stage->_GetPcpCache()->IsPayloadIncluded(_primIndex->GetPath()) : parent->IsLoaded()); @@ -134,20 +135,19 @@ Usd_PrimData::_ComposeAndCacheFlags(Usd_PrimDataConstPtr parent, // children (groups or otherwise). So if our parent is not a Model // Group, then this prim cannot be a model (or a model group). // Otherwise we look up the kind metadata and consult the kind registry. - _flags[Usd_PrimGroupFlag] = _flags[Usd_PrimModelFlag] = false; + bool isGroup = false, isModel = false; if (parent->IsGroup()) { static TfToken kindToken("kind"); TfToken kind; self.GetMetadata(kindToken, &kind); - // Use the kind registry to determine model/groupness. if (not kind.IsEmpty()) { - _flags[Usd_PrimGroupFlag] = - KindRegistry::IsA(kind, KindTokens->group); - _flags[Usd_PrimModelFlag] = _flags[Usd_PrimGroupFlag] or - KindRegistry::IsA(kind, KindTokens->model); + isGroup = KindRegistry::IsA(kind, KindTokens->group); + isModel = isGroup or KindRegistry::IsA(kind, KindTokens->model); } } + _flags[Usd_PrimGroupFlag] = isGroup; + _flags[Usd_PrimModelFlag] = isModel; // Get specifier. SdfSpecifier specifier = GetSpecifier(); @@ -156,12 +156,12 @@ Usd_PrimData::_ComposeAndCacheFlags(Usd_PrimDataConstPtr parent, _flags[Usd_PrimAbstractFlag] = parent->IsAbstract() or specifier == SdfSpecifierClass; - // This prim is defined if its parent is defined and its specifier is - // defining. - const bool specifierIsDefining = SdfIsDefiningSpecifier(specifier); - _flags[Usd_PrimDefinedFlag] = - parent->IsDefined() and specifierIsDefining; - _flags[Usd_PrimHasDefiningSpecifierFlag] = specifierIsDefining; + // Cache whether or not this prim has an authored defining specifier. + const bool isDefiningSpec = SdfIsDefiningSpecifier(specifier); + _flags[Usd_PrimHasDefiningSpecifierFlag] = isDefiningSpec; + + // This prim is defined if its parent is and its specifier is defining. + _flags[Usd_PrimDefinedFlag] = isDefiningSpec && parent->IsDefined(); // The presence of clips that may affect attributes on this prim // is computed and set in UsdStage. Default to false. diff --git a/pxr/usd/lib/usd/primData.h b/pxr/usd/lib/usd/primData.h index 056ca7277b..cc4a55d7cf 100644 --- a/pxr/usd/lib/usd/primData.h +++ b/pxr/usd/lib/usd/primData.h @@ -119,6 +119,9 @@ class Usd_PrimData return _flags[Usd_PrimHasDefiningSpecifierFlag]; } + /// Return true if this prim has one or more payload composition arcs. + bool HasPayload() const { return _flags[Usd_PrimHasPayloadFlag]; } + /// Return true if this prim is an instance of a shared master prim, /// false otherwise. bool IsInstance() const { return _flags[Usd_PrimInstanceFlag]; } diff --git a/pxr/usd/lib/usd/primFlags.h b/pxr/usd/lib/usd/primFlags.h index 5833462a9b..8031128051 100644 --- a/pxr/usd/lib/usd/primFlags.h +++ b/pxr/usd/lib/usd/primFlags.h @@ -81,6 +81,7 @@ // Enum for cached flags on prims. enum Usd_PrimFlags { + // Flags for use with predicates. Usd_PrimActiveFlag, Usd_PrimLoadedFlag, Usd_PrimModelFlag, @@ -88,6 +89,9 @@ enum Usd_PrimFlags { Usd_PrimAbstractFlag, Usd_PrimDefinedFlag, Usd_PrimHasDefiningSpecifierFlag, + + // Flags for internal use. + Usd_PrimHasPayloadFlag, Usd_PrimClipsFlag, Usd_PrimDeadFlag, Usd_PrimInstanceFlag, From edc6e350ad1419e69c7cd647e9e02630bc57fe71 Mon Sep 17 00:00:00 2001 From: gitamohr Date: Thu, 25 Aug 2016 10:22:12 -0700 Subject: [PATCH 012/380] usd: Use remove_copy_if instead of copying and remove_if. (Internal change: 1645503) --- pxr/usd/lib/usd/stage.cpp | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/pxr/usd/lib/usd/stage.cpp b/pxr/usd/lib/usd/stage.cpp index eb87874cdd..7d6c98fa72 100644 --- a/pxr/usd/lib/usd/stage.cpp +++ b/pxr/usd/lib/usd/stage.cpp @@ -506,7 +506,7 @@ UsdStage::_InstantiateStage(const SdfLayerRefPtr &rootLayer, TfDebug::IsEnabled(USD_STAGE_INSTANTIATION_TIME); if (usdInstantiationTimeDebugCodeActive) { - stopwatch = TfStopwatch(); + stopwatch = TfStopwatch(); stopwatch->Start(); } @@ -2915,13 +2915,11 @@ UsdStage::_HandleLayersDidChange( otherChangedPaths.clear(); } - SdfPathVector otherChangedPathsVec(otherChangedPaths.begin(), - otherChangedPaths.end()); - - otherChangedPathsVec.erase( - remove_if(otherChangedPathsVec.begin(), otherChangedPathsVec.end(), - bind(&UsdStage::_IsObjectElidedFromStage, this, _1)), - otherChangedPathsVec.end()); + SdfPathVector otherChangedPathsVec; + otherChangedPathsVec.reserve(otherChangedPaths.size()); + remove_copy_if(otherChangedPaths.begin(), otherChangedPaths.end(), + back_inserter(otherChangedPathsVec), + bind(&UsdStage::_IsObjectElidedFromStage, this, _1)); // Now we want to remove all elements of otherChangedPathsVec that are // prefixed by elements in pathsToRecompose. From 63007ba8af208d032d759b67e890586bc1a74b35 Mon Sep 17 00:00:00 2001 From: gitamohr Date: Thu, 25 Aug 2016 10:22:16 -0700 Subject: [PATCH 013/380] usd: Add a comment regarding why we don't need to zero _flags. (Internal change: 1645520) --- pxr/usd/lib/usd/primData.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/pxr/usd/lib/usd/primData.cpp b/pxr/usd/lib/usd/primData.cpp index 98142905af..c026fdff33 100644 --- a/pxr/usd/lib/usd/primData.cpp +++ b/pxr/usd/lib/usd/primData.cpp @@ -103,6 +103,10 @@ void Usd_PrimData::_ComposeAndCacheFlags(Usd_PrimDataConstPtr parent, bool isMasterPrim) { + // We do not have to clear _flags here since in the pseudo root or instance + // master case the values never change, and in the ordinary prim case we set + // every flag. + // Special-case the root (the only prim which has no parent) and // instancing masters. if (ARCH_UNLIKELY(not parent or isMasterPrim)) { From aa223b413ffb93b8409050790a5b8b820c6beaeb Mon Sep 17 00:00:00 2001 From: gitamohr Date: Thu, 25 Aug 2016 10:22:24 -0700 Subject: [PATCH 014/380] usd: Fix a miscategorized prim flag enum. (Internal change: 1645523) --- pxr/usd/lib/usd/primFlags.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pxr/usd/lib/usd/primFlags.h b/pxr/usd/lib/usd/primFlags.h index 8031128051..ec278254a1 100644 --- a/pxr/usd/lib/usd/primFlags.h +++ b/pxr/usd/lib/usd/primFlags.h @@ -89,12 +89,12 @@ enum Usd_PrimFlags { Usd_PrimAbstractFlag, Usd_PrimDefinedFlag, Usd_PrimHasDefiningSpecifierFlag, + Usd_PrimInstanceFlag, // Flags for internal use. Usd_PrimHasPayloadFlag, Usd_PrimClipsFlag, Usd_PrimDeadFlag, - Usd_PrimInstanceFlag, Usd_PrimMasterFlag, Usd_PrimNumFlags }; From e37e7fdd88602519ff1ee3d16cb93dc70735b9d1 Mon Sep 17 00:00:00 2001 From: superfunc Date: Thu, 25 Aug 2016 10:22:30 -0700 Subject: [PATCH 015/380] [UsdMaya] Fix up compiler warnings. (Internal change: 1645597) --- .../maya/lib/pxrUsdMayaGL/softSelectHelper.h | 2 +- .../maya/lib/usdMaya/MayaMeshWriter_PrimVars.cpp | 15 ++++++++++----- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/third_party/maya/lib/pxrUsdMayaGL/softSelectHelper.h b/third_party/maya/lib/pxrUsdMayaGL/softSelectHelper.h index b6ac3b0f02..ca65b92e31 100644 --- a/third_party/maya/lib/pxrUsdMayaGL/softSelectHelper.h +++ b/third_party/maya/lib/pxrUsdMayaGL/softSelectHelper.h @@ -79,7 +79,7 @@ class UsdMayaGLSoftSelectHelper void _PopulateSoftSelectColorRamp(); struct _MDagPathHash { - inline size_t operator()(const MDagPath& dagPath) { + inline size_t operator()(const MDagPath& dagPath) const { return TfHash()(std::string(dagPath.fullPathName().asChar())); } }; diff --git a/third_party/maya/lib/usdMaya/MayaMeshWriter_PrimVars.cpp b/third_party/maya/lib/usdMaya/MayaMeshWriter_PrimVars.cpp index 00afbb03cf..f2c5ccf926 100644 --- a/third_party/maya/lib/usdMaya/MayaMeshWriter_PrimVars.cpp +++ b/third_party/maya/lib/usdMaya/MayaMeshWriter_PrimVars.cpp @@ -87,7 +87,7 @@ _MergeEquivalentColorSetValues( for (size_t i = 0; i < colorSetAssignmentIndices->size(); ++i) { int index = (*colorSetAssignmentIndices)[i]; - if (index < 0 or index >= numValues) { + if (index < 0 or static_cast(index) >= numValues) { // This is an unassigned or otherwise unknown index, so just keep it. uniqueIndices.push_back(index); continue; @@ -316,9 +316,12 @@ bool MayaMeshWriter::_GetMeshColorSetData( if (shadersRGBData.size() == 1) { valueIndex = 0; } - } else if (faceIndex >= 0 and faceIndex < shadersAssignmentIndices.size()) { + } else if (faceIndex >= 0 and + static_cast(faceIndex) < shadersAssignmentIndices.size()) { + int tmpIndex = shadersAssignmentIndices[faceIndex]; - if (tmpIndex >= 0 and tmpIndex < shadersRGBData.size()) { + if (tmpIndex >= 0 and + static_cast(tmpIndex) < shadersRGBData.size()) { valueIndex = tmpIndex; } } @@ -339,9 +342,11 @@ bool MayaMeshWriter::_GetMeshColorSetData( if (shadersAlphaData.size() == 1) { valueIndex = 0; } - } else if (faceIndex >= 0 and faceIndex < shadersAssignmentIndices.size()) { + } else if (faceIndex >= 0 and + static_cast(faceIndex) < shadersAssignmentIndices.size()) { int tmpIndex = shadersAssignmentIndices[faceIndex]; - if (tmpIndex >= 0 and tmpIndex < shadersAlphaData.size()) { + if (tmpIndex >= 0 and + static_cast(tmpIndex) < shadersAlphaData.size()) { valueIndex = tmpIndex; } } From e90bcce264d35d84f739a78b734f49a5a27b9f27 Mon Sep 17 00:00:00 2001 From: s-baron Date: Thu, 25 Aug 2016 10:51:41 -0700 Subject: [PATCH 016/380] [garch] Moved glPlatformDebugContext into garch (Internal change: 1645824) (Internal change: 1646184) (Internal change: 1646387) --- pxr/imaging/lib/garch/CMakeLists.txt | 10 ++++ pxr/imaging/lib/garch/__init__.py | 40 +++++++++++++++ .../glPlatformDebugContext.cpp | 50 ++++++++++--------- .../{glfq => garch}/glPlatformDebugContext.h | 20 ++++---- pxr/imaging/lib/garch/module.cpp | 29 +++++++++++ pxr/imaging/lib/garch/moduleDeps.cpp | 42 ++++++++++++++++ .../wrapPlatformDebugContext.cpp | 8 +-- pxr/imaging/lib/glfq/CMakeLists.txt | 5 +- pxr/imaging/lib/glfq/__init__.py | 3 +- pxr/imaging/lib/glfq/glDebugContext.cpp | 6 +-- pxr/imaging/lib/glfq/glDebugContext.h | 4 +- pxr/imaging/lib/glfq/module.cpp | 1 - 12 files changed, 171 insertions(+), 47 deletions(-) create mode 100644 pxr/imaging/lib/garch/__init__.py rename pxr/imaging/lib/{glfq => garch}/glPlatformDebugContext.cpp (80%) rename pxr/imaging/lib/{glfq => garch}/glPlatformDebugContext.h (77%) create mode 100644 pxr/imaging/lib/garch/module.cpp create mode 100644 pxr/imaging/lib/garch/moduleDeps.cpp rename pxr/imaging/lib/{glfq => garch}/wrapPlatformDebugContext.cpp (89%) diff --git a/pxr/imaging/lib/garch/CMakeLists.txt b/pxr/imaging/lib/garch/CMakeLists.txt index bccc65bed6..1bbfd4e605 100644 --- a/pxr/imaging/lib/garch/CMakeLists.txt +++ b/pxr/imaging/lib/garch/CMakeLists.txt @@ -16,6 +16,7 @@ endif() pxr_shared_library(garch LIBRARIES arch + tf ${Boost_SYSTEM_LIBRARY} ${OPENGL_gl_LIBRARY} ${APPKIT_LIBRARY} @@ -25,6 +26,7 @@ pxr_shared_library(garch PUBLIC_CLASSES glPlatformContext + glPlatformDebugContext PUBLIC_HEADERS gl.h @@ -34,5 +36,13 @@ pxr_shared_library(garch ${GLPLATFORMCONTEXT_H} CPPFILES + moduleDeps.cpp ${GLPLATFORMCONTEXT_CPP} + + PYMODULE_CPPFILES + module.cpp + wrapPlatformDebugContext.cpp + + PYTHON_FILES + __init__.py ) diff --git a/pxr/imaging/lib/garch/__init__.py b/pxr/imaging/lib/garch/__init__.py new file mode 100644 index 0000000000..5968f1ab70 --- /dev/null +++ b/pxr/imaging/lib/garch/__init__.py @@ -0,0 +1,40 @@ +# +# 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. +# +""" +garch + +""" + +import _garch +from pxr import Tf +Tf.PrepareModule(_garch, locals()) +del _garch, Tf + +try: + from . import __DOC + __DOC.Execute(locals()) + del __DOC +except Exception: + pass + diff --git a/pxr/imaging/lib/glfq/glPlatformDebugContext.cpp b/pxr/imaging/lib/garch/glPlatformDebugContext.cpp similarity index 80% rename from pxr/imaging/lib/glfq/glPlatformDebugContext.cpp rename to pxr/imaging/lib/garch/glPlatformDebugContext.cpp index 15a4afcaf0..c91aa5a29c 100644 --- a/pxr/imaging/lib/glfq/glPlatformDebugContext.cpp +++ b/pxr/imaging/lib/garch/glPlatformDebugContext.cpp @@ -21,7 +21,7 @@ // KIND, either express or implied. See the Apache License for the specific // language governing permissions and limitations under the Apache License. // -#include "pxr/imaging/glfq/glPlatformDebugContext.h" +#include "pxr/imaging/garch/glPlatformDebugContext.h" #include "pxr/imaging/garch/gl.h" #include "pxr/base/tf/diagnostic.h" @@ -30,7 +30,7 @@ /* static */ bool -GlfQGLPlatformDebugContext::IsEnabledDebugOutput() +GarchGLPlatformDebugContext::IsEnabledDebugOutput() { static bool isEnabledDebugOutput = TfGetenvBool("GLF_ENABLE_DEBUG_OUTPUT", false); @@ -39,7 +39,7 @@ GlfQGLPlatformDebugContext::IsEnabledDebugOutput() /* static */ bool -GlfQGLPlatformDebugContext::IsEnabledCoreProfile() +GarchGLPlatformDebugContext::IsEnabledCoreProfile() { static bool isEnabledCoreProfile = TfGetenvBool("GLF_ENABLE_CORE_PROFILE", false); @@ -54,12 +54,12 @@ GlfQGLPlatformDebugContext::IsEnabledCoreProfile() #include #include -class GlfQGLPlatformDebugContextPrivate { +class GarchGLPlatformDebugContextPrivate { public: - GlfQGLPlatformDebugContextPrivate( + GarchGLPlatformDebugContextPrivate( int majorVersion, int minorVersion, bool coreProfile, bool directRendering); - ~GlfQGLPlatformDebugContextPrivate(); + ~GarchGLPlatformDebugContextPrivate(); void MakeCurrent(); @@ -67,7 +67,7 @@ class GlfQGLPlatformDebugContextPrivate { GLXContext _ctx; }; -GlfQGLPlatformDebugContextPrivate::GlfQGLPlatformDebugContextPrivate( +GarchGLPlatformDebugContextPrivate::GarchGLPlatformDebugContextPrivate( int majorVersion, int minorVersion, bool coreProfile, bool directRendering) : _dpy(NULL) @@ -128,7 +128,7 @@ GlfQGLPlatformDebugContextPrivate::GlfQGLPlatformDebugContextPrivate( _dpy = shareDisplay; } -GlfQGLPlatformDebugContextPrivate::~GlfQGLPlatformDebugContextPrivate() +GarchGLPlatformDebugContextPrivate::~GarchGLPlatformDebugContextPrivate() { if (_dpy and _ctx) { glXDestroyContext(_dpy, _ctx); @@ -136,7 +136,7 @@ GlfQGLPlatformDebugContextPrivate::~GlfQGLPlatformDebugContextPrivate() } void -GlfQGLPlatformDebugContextPrivate::MakeCurrent() +GarchGLPlatformDebugContextPrivate::MakeCurrent() { glXMakeCurrent(glXGetCurrentDisplay(), glXGetCurrentDrawable(), _ctx); } @@ -153,12 +153,12 @@ void *GlfqSelectCoreProfileMacVisual() #if defined(ARCH_OS_DARWIN) // XXX: implement debug context -class GlfQGLPlatformDebugContextPrivate { +class GarchGLPlatformDebugContextPrivate { public: - GlfQGLPlatformDebugContextPrivate( + GarchGLPlatformDebugContextPrivate( int majorVersion, int minorVersion, bool coreProfile, bool directRendering) {} - ~GlfQGLPlatformDebugContextPrivate() {} + ~GarchGLPlatformDebugContextPrivate() {} void MakeCurrent() {} }; @@ -173,12 +173,12 @@ void *GlfqSelectCoreProfileMacVisual(); // extern obj-c #if defined(ARCH_OS_WINDOWS) // XXX: implement debug context -class GlfQGLPlatformDebugContextPrivate { +class GarchGLPlatformDebugContextPrivate { public: - GlfQGLPlatformDebugContextPrivate( + GarchGLPlatformDebugContextPrivate( int majorVersion, int minorVersion, bool coreProfile, bool directRendering) {} - ~GlfQGLPlatformDebugContextPrivate() {} + ~GarchGLPlatformDebugContextPrivate() {} void MakeCurrent() {} }; @@ -193,7 +193,7 @@ void *GlfqSelectCoreProfileMacVisual() //////////////////////////////////////////////////////////// -GlfQGLPlatformDebugContext::GlfQGLPlatformDebugContext(int majorVersion, +GarchGLPlatformDebugContext::GarchGLPlatformDebugContext(int majorVersion, int minorVersion, bool coreProfile, bool directRendering) @@ -201,25 +201,25 @@ GlfQGLPlatformDebugContext::GlfQGLPlatformDebugContext(int majorVersion, , _coreProfile(coreProfile) { - if (not GlfQGLPlatformDebugContext::IsEnabledDebugOutput()) { + if (not GarchGLPlatformDebugContext::IsEnabledDebugOutput()) { return; } - _private.reset(new GlfQGLPlatformDebugContextPrivate(majorVersion, + _private.reset(new GarchGLPlatformDebugContextPrivate(majorVersion, minorVersion, coreProfile, directRendering)); } -GlfQGLPlatformDebugContext::~GlfQGLPlatformDebugContext() +GarchGLPlatformDebugContext::~GarchGLPlatformDebugContext() { // nothing } /* virtual */ void -GlfQGLPlatformDebugContext::makeCurrent() +GarchGLPlatformDebugContext::makeCurrent() { - if (not GlfQGLPlatformDebugContext::IsEnabledDebugOutput()) { + if (not GarchGLPlatformDebugContext::IsEnabledDebugOutput()) { return; } @@ -231,11 +231,13 @@ GlfQGLPlatformDebugContext::makeCurrent() } void* -GlfQGLPlatformDebugContext::chooseMacVisual() +GarchGLPlatformDebugContext::chooseMacVisual() { if (_coreProfile or - GlfQGLPlatformDebugContext::IsEnabledCoreProfile()) { - return GlfqSelectCoreProfileMacVisual(); + GarchGLPlatformDebugContext::IsEnabledCoreProfile()) { + // XXX: move selectVisual to garch + //return GlfqSelectCoreProfileMacVisual(); + return nullptr; } else { return nullptr; } diff --git a/pxr/imaging/lib/glfq/glPlatformDebugContext.h b/pxr/imaging/lib/garch/glPlatformDebugContext.h similarity index 77% rename from pxr/imaging/lib/glfq/glPlatformDebugContext.h rename to pxr/imaging/lib/garch/glPlatformDebugContext.h index b2b65bbb57..d723f29921 100644 --- a/pxr/imaging/lib/glfq/glPlatformDebugContext.h +++ b/pxr/imaging/lib/garch/glPlatformDebugContext.h @@ -21,29 +21,29 @@ // KIND, either express or implied. See the Apache License for the specific // language governing permissions and limitations under the Apache License. // -#ifndef GLFQ_GLPLATFORM_DEBUG_CONTEXT_H -#define GLFQ_GLPLATFORM_DEBUG_CONTEXT_H +#ifndef GARCH_GLPLATFORM_DEBUG_CONTEXT_H +#define GARCH_GLPLATFORM_DEBUG_CONTEXT_H #include "pxr/base/tf/declarePtrs.h" #include "pxr/base/tf/weakBase.h" #include -class GlfQGLPlatformDebugContextPrivate; +class GarchGLPlatformDebugContextPrivate; -TF_DECLARE_WEAK_PTRS(GlfQGLPlatformDebugContext); +TF_DECLARE_WEAK_PTRS(GarchGLPlatformDebugContext); -/// \class GlfQGLPlatformDebugContext +/// \class GarchGLPlatformDebugContext /// /// Platform specific context (e.g. X11/GLX) which supports debug output. /// -class GlfQGLPlatformDebugContext : public TfWeakBase { +class GarchGLPlatformDebugContext : public TfWeakBase { public: - GlfQGLPlatformDebugContext(int majorVersion, + GarchGLPlatformDebugContext(int majorVersion, int minorVersion, bool coreProfile, bool directRenderering); - virtual ~GlfQGLPlatformDebugContext(); + virtual ~GarchGLPlatformDebugContext(); static bool IsEnabledDebugOutput(); static bool IsEnabledCoreProfile(); @@ -52,8 +52,8 @@ class GlfQGLPlatformDebugContext : public TfWeakBase { void *chooseMacVisual(); public: - boost::scoped_ptr _private; + boost::scoped_ptr _private; bool _coreProfile; }; -#endif // GLFQ_GLPLATFORM_DEBUG_CONTEXT_H +#endif // GARCH_GLPLATFORM_DEBUG_CONTEXT_H diff --git a/pxr/imaging/lib/garch/module.cpp b/pxr/imaging/lib/garch/module.cpp new file mode 100644 index 0000000000..33017b8623 --- /dev/null +++ b/pxr/imaging/lib/garch/module.cpp @@ -0,0 +1,29 @@ +// +// 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. +// +#include "pxr/base/tf/pyModule.h" + +TF_WRAP_MODULE +{ + TF_WRAP( PlatformDebugContext ); +} diff --git a/pxr/imaging/lib/garch/moduleDeps.cpp b/pxr/imaging/lib/garch/moduleDeps.cpp new file mode 100644 index 0000000000..e8e58ca9d0 --- /dev/null +++ b/pxr/imaging/lib/garch/moduleDeps.cpp @@ -0,0 +1,42 @@ +// +// 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. +// +//////////////////////////////////////////////////////////////////////// +// This file is generated by the makeScriptModuleLoader script. Do not +// edit directly. + +#include "pxr/base/tf/registryManager.h" +#include "pxr/base/tf/scriptModuleLoader.h" +#include "pxr/base/tf/token.h" + +#include + +TF_REGISTRY_FUNCTION(TfScriptModuleLoader) { + std::vector reqs; + reqs.reserve(2); + reqs.push_back(TfToken("arch")); + reqs.push_back(TfToken("tf")); + TfScriptModuleLoader::GetInstance(). + RegisterLibrary(TfToken("garch"), TfToken("pxr.Garch"), reqs); +} + diff --git a/pxr/imaging/lib/glfq/wrapPlatformDebugContext.cpp b/pxr/imaging/lib/garch/wrapPlatformDebugContext.cpp similarity index 89% rename from pxr/imaging/lib/glfq/wrapPlatformDebugContext.cpp rename to pxr/imaging/lib/garch/wrapPlatformDebugContext.cpp index ac9620eb72..bbdffab651 100644 --- a/pxr/imaging/lib/glfq/wrapPlatformDebugContext.cpp +++ b/pxr/imaging/lib/garch/wrapPlatformDebugContext.cpp @@ -21,7 +21,7 @@ // KIND, either express or implied. See the Apache License for the specific // language governing permissions and limitations under the Apache License. // -#include "pxr/imaging/glfq/glPlatformDebugContext.h" +#include "pxr/imaging/garch/glPlatformDebugContext.h" #include "pxr/base/tf/makePyConstructor.h" #include "pxr/base/tf/pyPtrHelpers.h" @@ -30,18 +30,18 @@ using namespace boost::python; -static GlfQGLPlatformDebugContextPtr +static GarchGLPlatformDebugContextPtr _New(int majorVersion, int minorVersion, bool coreProfile, bool directRendering) { return TfCreateWeakPtr(new - GlfQGLPlatformDebugContext(majorVersion, minorVersion, + GarchGLPlatformDebugContext(majorVersion, minorVersion, coreProfile, directRendering)); } void wrapPlatformDebugContext() { - typedef GlfQGLPlatformDebugContext This; + typedef GarchGLPlatformDebugContext This; class_, boost::noncopyable>("GLPlatformDebugContext", no_init) diff --git a/pxr/imaging/lib/glfq/CMakeLists.txt b/pxr/imaging/lib/glfq/CMakeLists.txt index 1bdb8ea74b..d14a99f4b4 100644 --- a/pxr/imaging/lib/glfq/CMakeLists.txt +++ b/pxr/imaging/lib/glfq/CMakeLists.txt @@ -23,16 +23,17 @@ pxr_shared_library(glfq Qt4::QtOpenGL Qt4::QtXml Qt4::QtNetwork + ${Boost_SYSTEM_LIBRARY} ${OPENGL_gl_LIBRARY} ${GLEW_LIBRARY} ${COCOA_LIBRARY} INCLUDE_DIRS + ${Boost_INCLUDE_DIRS} ${GLEW_INCLUDE_DIR} PUBLIC_CLASSES glDebugContext - glPlatformDebugContext CPPFILES moduleDeps.cpp @@ -40,8 +41,8 @@ pxr_shared_library(glfq PYMODULE_CPPFILES module.cpp - wrapPlatformDebugContext.cpp PYTHON_FILES __init__.py + ) diff --git a/pxr/imaging/lib/glfq/__init__.py b/pxr/imaging/lib/glfq/__init__.py index ce96e90eac..ca14ab81b3 100644 --- a/pxr/imaging/lib/glfq/__init__.py +++ b/pxr/imaging/lib/glfq/__init__.py @@ -43,9 +43,10 @@ def create(self, shareContext): return QtOpenGL.QGLContext.create(self, shareContext) def makeCurrent(self): + from pxr import Garch QtOpenGL.QGLContext.makeCurrent(self) if not self._platformContext: - self._platformContext = GLPlatformDebugContext( + self._platformContext = Garch.GLPlatformDebugContext( self.format().majorVersion(), self.format().minorVersion(), self.format().profile() == QtOpenGL.QGLFormat.CoreProfile, diff --git a/pxr/imaging/lib/glfq/glDebugContext.cpp b/pxr/imaging/lib/glfq/glDebugContext.cpp index 27acd991ff..90eb140702 100644 --- a/pxr/imaging/lib/glfq/glDebugContext.cpp +++ b/pxr/imaging/lib/glfq/glDebugContext.cpp @@ -22,7 +22,7 @@ // language governing permissions and limitations under the Apache License. // #include "pxr/imaging/glfq/glDebugContext.h" -#include "pxr/imaging/glfq/glPlatformDebugContext.h" +#include "pxr/imaging/garch/glPlatformDebugContext.h" #include "pxr/base/tf/diagnostic.h" @@ -52,7 +52,7 @@ GlfQGLDebugContext::makeCurrent() Parent::makeCurrent(); if (not _platformContext) { _platformContext.reset(new - GlfQGLPlatformDebugContext( + GarchGLPlatformDebugContext( format().majorVersion(), format().minorVersion(), format().profile() == QGLFormat::CoreProfile, @@ -70,7 +70,7 @@ GlfQGLDebugContext::chooseMacVisual(GDHandle handle) { if (not _platformContext) { _platformContext.reset(new - GlfQGLPlatformDebugContext( + GarchGLPlatformDebugContext( format().majorVersion(), format().minorVersion(), format().profile() == QGLFormat::CoreProfile, diff --git a/pxr/imaging/lib/glfq/glDebugContext.h b/pxr/imaging/lib/glfq/glDebugContext.h index 9afff349ba..0a438fc20b 100644 --- a/pxr/imaging/lib/glfq/glDebugContext.h +++ b/pxr/imaging/lib/glfq/glDebugContext.h @@ -32,7 +32,7 @@ #include -class GlfQGLPlatformDebugContext; +class GarchGLPlatformDebugContext; TF_DECLARE_WEAK_PTRS(GlfQGLDebugContext); @@ -60,7 +60,7 @@ class GlfQGLDebugContext : public QGLContext, public TfWeakBase { #endif public: - boost::scoped_ptr _platformContext; + boost::scoped_ptr _platformContext; }; #endif // GLFQ_GL_DEBUG_CONTEXT_H diff --git a/pxr/imaging/lib/glfq/module.cpp b/pxr/imaging/lib/glfq/module.cpp index 33017b8623..70395ad5c5 100644 --- a/pxr/imaging/lib/glfq/module.cpp +++ b/pxr/imaging/lib/glfq/module.cpp @@ -25,5 +25,4 @@ TF_WRAP_MODULE { - TF_WRAP( PlatformDebugContext ); } From e35c21bfdf1d3a3e4a26890c7b17d451c1194a6a Mon Sep 17 00:00:00 2001 From: s-baron Date: Thu, 25 Aug 2016 10:53:12 -0700 Subject: [PATCH 017/380] [hd] Fallback behavior for textures with invalid filepaths This change adds a black fallback texture for the case where a usd-imaged UV texture is missing a valid filepath. Note that ptex fallbacks are not currently implemented. (Internal change: 1645825) --- pxr/imaging/lib/hd/texture.cpp | 57 ++++++++------- pxr/imaging/lib/hd/textureResource.cpp | 36 +++++++++- pxr/imaging/lib/hd/textureResource.h | 2 + pxr/usdImaging/lib/usdImaging/delegate.cpp | 84 ++++++++++++++++++++++ 4 files changed, 152 insertions(+), 27 deletions(-) diff --git a/pxr/imaging/lib/hd/texture.cpp b/pxr/imaging/lib/hd/texture.cpp index fbb878a863..336d798889 100644 --- a/pxr/imaging/lib/hd/texture.cpp +++ b/pxr/imaging/lib/hd/texture.cpp @@ -23,6 +23,8 @@ // #include "pxr/imaging/hd/texture.h" +#include "pxr/imaging/glf/textureRegistry.h" +#include "pxr/imaging/glf/uvTextureStorage.h" #include "pxr/imaging/hd/bufferArrayRange.h" #include "pxr/imaging/hd/resource.h" #include "pxr/imaging/hd/resourceRegistry.h" @@ -67,33 +69,38 @@ HdTexture::Sync() bits & HdChangeTracker::DirtyParams or bits & HdChangeTracker::DirtyTexture) { - HdTextureResourceSharedPtr texResource = - delegate->GetTextureResource(id); -#if 0 - if (texResource->GetTexelsTextureId() == 0) { - // fail to load a texture. use fallback default - - if (texResource->IsPtex()) { - const size_t defaultPtexId = 0x48510398a84ebf94; - HdInstance - defaultTexInstance = resourceRegistry->RegisterTextureResource(defaultPtexId); - if (defaultTexInstance.IsFirstInstance()) { - HdTextureResourceSharedPtr defaultTexResource(new Hd_DefaultPtexTextureResource()); - defaultTexInstance.SetValue(defaultTexResource); - } - texResource = defaultTexInstance.GetValue(); - } else { - const size_t defaultUVId = 0x48510398a84ebf95; - HdInstance - defaultTexInstance = resourceRegistry->RegisterTextureResource(defaultUVId); - if (defaultTexInstance.IsFirstInstance()) { - HdTextureResourceSharedPtr defaultTexResource(new Hd_DefaultUVTextureResource()); - defaultTexInstance.SetValue(defaultTexResource); + HdTextureResourceSharedPtr texResource; + if (texID == HdTextureResource::ComputeFallbackUVHash()) { + GlfUVTextureStorageRefPtr texPtr = + GlfUVTextureStorage::New(1,1,VtValue(GfVec3d(0.0, 0.0, 0.0))); + GlfTextureHandleRefPtr texture = + GlfTextureRegistry::GetInstance().GetTextureHandle(texPtr); + texture->AddMemoryRequest(0); + texResource = HdTextureResourceSharedPtr( + new HdSimpleTextureResource(texture, false)); + } else if (texID == HdTextureResource::ComputeFallbackPtexHash()) { + texResource = + delegate->GetTextureResource(id); + // Hacky Ptex Fallback Implementation (nonfunctional) + // For future reference + /*if (texResource->GetTexelsTextureId() == 0) { + // fail to load a texture. use fallback default + if (texResource->IsPtex()) { + const size_t defaultPtexId = 0x48510398a84ebf94; + HdInstance + defaultTexInstance = resourceRegistry->RegisterTextureResource(defaultPtexId); + if (defaultTexInstance.IsFirstInstance()) { + HdTextureResourceSharedPtr defaultTexResource(new Hd_DefaultPtexTextureResource()); + defaultTexInstance.SetValue(defaultTexResource); + } + texResource = defaultTexInstance.GetValue(); } - texResource = defaultTexInstance.GetValue(); - } + }*/ + } else { + texResource = + delegate->GetTextureResource(id); } -#endif + texInstance.SetValue(texResource); } } diff --git a/pxr/imaging/lib/hd/textureResource.cpp b/pxr/imaging/lib/hd/textureResource.cpp index bd2ba3d433..ccabb38eee 100644 --- a/pxr/imaging/lib/hd/textureResource.cpp +++ b/pxr/imaging/lib/hd/textureResource.cpp @@ -30,7 +30,13 @@ #include "pxr/imaging/hd/renderContextCaps.h" #include "pxr/imaging/glf/baseTexture.h" #include "pxr/imaging/glf/ptexTexture.h" -#include "pxr/imaging/glf/uvTexture.h" + +TF_DEFINE_PRIVATE_TOKENS( + _tokens, + + ((fallbackPtexPath, "PtExNoNsEnSe")) + ((fallbackUVPath, "UvNoNsEnSe")) +); HdTextureResource::~HdTextureResource() { @@ -49,6 +55,32 @@ HdTextureResource::ComputeHash(TfToken const &sourceFile) return hash; } +/* static */ +HdTextureResource::ID +HdTextureResource::ComputeFallbackPtexHash() +{ + HD_TRACE_FUNCTION(); + + uint32_t hash = 0; + std::string const &filename = _tokens->fallbackPtexPath.GetString(); + hash = ArchHash(filename.c_str(), filename.size(), hash); + + return hash; +} + +/* static */ +HdTextureResource::ID +HdTextureResource::ComputeFallbackUVHash() +{ + HD_TRACE_FUNCTION(); + + uint32_t hash = 0; + std::string const &filename = _tokens->fallbackUVPath.GetString(); + hash = ArchHash(filename.c_str(), filename.size(), hash); + + return hash; +} + // HdSimpleTextureResource implementation HdSimpleTextureResource::HdSimpleTextureResource( @@ -125,7 +157,7 @@ GLuint HdSimpleTextureResource::GetTexelsTextureId() return TfDynamic_cast(_texture)->GetTexelsTextureName(); } - return TfDynamic_cast(_texture)->GetGlTextureName(); + return TfDynamic_cast(_texture)->GetGlTextureName(); } GLuint HdSimpleTextureResource::GetTexelsSamplerId() diff --git a/pxr/imaging/lib/hd/textureResource.h b/pxr/imaging/lib/hd/textureResource.h index 2de082bf7a..12b0d02d4f 100644 --- a/pxr/imaging/lib/hd/textureResource.h +++ b/pxr/imaging/lib/hd/textureResource.h @@ -43,6 +43,8 @@ class HdTextureResource { /// Returns the hash value of the texture for \a sourceFile static ID ComputeHash(TfToken const & sourceFile); + static ID ComputeFallbackPtexHash(); + static ID ComputeFallbackUVHash(); virtual ~HdTextureResource(); diff --git a/pxr/usdImaging/lib/usdImaging/delegate.cpp b/pxr/usdImaging/lib/usdImaging/delegate.cpp index 006af50c39..d60f1df034 100644 --- a/pxr/usdImaging/lib/usdImaging/delegate.cpp +++ b/pxr/usdImaging/lib/usdImaging/delegate.cpp @@ -2932,6 +2932,90 @@ UsdImagingDelegate::GetSurfaceShaderTextures(SdfPath const &shaderId) HdTextureResource::ID UsdImagingDelegate::GetTextureResourceID(SdfPath const &textureId) { + if (textureId == SdfPath()) { + size_t hash = textureId.GetHash(); + // salt with renderindex to prevent hash collision in non-shared imaging + boost::hash_combine(hash, &GetRenderIndex()); + return HdTextureResource::ID(hash); + } + + SdfPath usdPath = GetPathForUsd(textureId); + + UsdObject object = _stage->GetPrimAtPath(usdPath.GetPrimPath()); + if (not object) { + size_t hash = textureId.GetHash(); + // salt with renderindex to prevent hash collision in non-shared imaging + boost::hash_combine(hash, &GetRenderIndex()); + return HdTextureResource::ID(hash); + } + + bool isPtex = false; + SdfAssetPath asset; + + if (usdPath.IsPropertyPath()) { + // Attribute-based texture. + UsdAttribute attr = object.As().GetAttribute( + usdPath.GetNameToken()); + if (not attr) { + size_t hash = textureId.GetHash(); + // salt with renderindex to prevent hash collision in non-shared imaging + boost::hash_combine(hash, &GetRenderIndex()); + return HdTextureResource::ID(hash); + } + if (not attr.Get(&asset, _time)) { + size_t hash = textureId.GetHash(); + // salt with renderindex to prevent hash collision in non-shared imaging + boost::hash_combine(hash, &GetRenderIndex()); + return HdTextureResource::ID(hash); + } + } else { + TfToken id; + UsdShadeShader shader(_stage->GetPrimAtPath(usdPath)); + + if (not shader){ + size_t hash = textureId.GetHash(); + // salt with renderindex to prevent hash collision in non-shared imaging + boost::hash_combine(hash, &GetRenderIndex()); + return HdTextureResource::ID(hash); + } + if (not UsdHydraTexture(shader).GetFilenameAttr().Get(&asset)) { + size_t hash = textureId.GetHash(); + // salt with renderindex to prevent hash collision in non-shared imaging + boost::hash_combine(hash, &GetRenderIndex()); + return HdTextureResource::ID(hash); + } + } + + TfToken filePath = TfToken(asset.GetResolvedPath()); + + // Fallback to the literal path if it couldn't be resolved. + if (filePath.IsEmpty()) + filePath = TfToken(asset.GetAssetPath()); + + isPtex = GlfPtexTexture::IsPtexTexture(filePath); + + if (not TfPathExists(filePath)) { + if (isPtex) { + TF_WARN("Unable to find Texture '%s' with path '%s'. Fallback" + "textures are not supported for ptex", + filePath.GetText(), usdPath.GetText()); + + HdTextureResource::ID hash = + HdTextureResource::ComputeFallbackPtexHash(); + // Don't salt default values + return hash; + } else { + TF_WARN("Unable to find Texture '%s' with path '%s'. A black" + "texture will be substituted in its place.", + filePath.GetText(), usdPath.GetText()); + + HdTextureResource::ID hash = + HdTextureResource::ComputeFallbackUVHash(); + // Don't salt default values + return hash; + } + } + size_t hash = textureId.GetHash(); // salt with renderindex to prevent hash collision in non-shared imaging boost::hash_combine(hash, &GetRenderIndex()); From 1d3fa36cb3e2029c370074e5c6349dcbfe67fa76 Mon Sep 17 00:00:00 2001 From: pixar-oss Date: Thu, 25 Aug 2016 10:58:46 -0700 Subject: [PATCH 018/380] More robust motion blur handling to support backward or forward motion at arbitrary start and end times. Implementation details: Upon processing of the PxrUsdIn args, we determine the motion direction. If the motion is backward, when building attributes with motion samples, we flip the sign of sample times before inserting into the attribute builder. (Internal change: 1645902) --- .../katana/lib/usdKatana/readCamera.cpp | 5 +- .../lib/usdKatana/readConstraintTarget.cpp | 7 ++- .../katana/lib/usdKatana/readGprim.cpp | 12 ++++- .../katana/lib/usdKatana/readNurbsPatch.cpp | 10 ++-- .../katana/lib/usdKatana/readXformable.cpp | 7 ++- .../katana/lib/usdKatana/usdInArgs.cpp | 3 ++ third_party/katana/lib/usdKatana/usdInArgs.h | 10 ++++ .../katana/lib/usdKatana/usdInPrivateData.cpp | 49 +++++++++---------- .../katana/lib/usdKatana/usdInPrivateData.h | 2 - third_party/katana/lib/usdKatana/utils.cpp | 13 ++++- third_party/katana/lib/usdKatana/utils.h | 5 ++ .../katana/plugin/pxrUsdIn/pxrUsdIn.cpp | 3 +- 12 files changed, 88 insertions(+), 38 deletions(-) diff --git a/third_party/katana/lib/usdKatana/readCamera.cpp b/third_party/katana/lib/usdKatana/readCamera.cpp index 8cf1dd98a6..4df91a4e71 100644 --- a/third_party/katana/lib/usdKatana/readCamera.cpp +++ b/third_party/katana/lib/usdKatana/readCamera.cpp @@ -130,6 +130,8 @@ PxrUsdKatanaReadCamera( const std::vector& motionSampleTimes = data.GetMotionSampleTimes(camera.GetFocalLengthAttr()); + const bool isMotionBackward = data.GetUsdInArgs()->IsMotionBackward(); + FnKat::DoubleBuilder fovBuilder(1); TF_FOR_ALL(iter, motionSampleTimes) { @@ -139,7 +141,8 @@ PxrUsdKatanaReadCamera( double fov = camera.GetCamera(time, camerasAreZup ).GetFieldOfView(GfCamera::FOVHorizontal); - fovBuilder.push_back(fov, fabs(relSampleTime)); + fovBuilder.push_back(fov, isMotionBackward ? + PxrUsdKatanaUtils::ReverseTimeSample(relSampleTime) : relSampleTime); if (not isVarying) { diff --git a/third_party/katana/lib/usdKatana/readConstraintTarget.cpp b/third_party/katana/lib/usdKatana/readConstraintTarget.cpp index bca4b7466b..09e21988f1 100644 --- a/third_party/katana/lib/usdKatana/readConstraintTarget.cpp +++ b/third_party/katana/lib/usdKatana/readConstraintTarget.cpp @@ -99,6 +99,8 @@ _BuildMatrixAttr( const std::vector& motionSampleTimes = data.GetMotionSampleTimes(constraintAttr); + const bool isMotionBackward = data.GetUsdInArgs()->IsMotionBackward(); + FnKat::DoubleBuilder matBuilder(16); TF_FOR_ALL(iter, motionSampleTimes) { double relSampleTime = *iter; @@ -110,7 +112,10 @@ _BuildMatrixAttr( // Convert to vector. const double *matArray = mat.GetArray(); - std::vector &matVec = matBuilder.get(fabs(relSampleTime)); + + std::vector &matVec = matBuilder.get(isMotionBackward ? + PxrUsdKatanaUtils::ReverseTimeSample(relSampleTime) : relSampleTime); + matVec.resize(16); for (int i = 0; i < 16; ++i) { matVec[i] = matArray[i]; diff --git a/third_party/katana/lib/usdKatana/readGprim.cpp b/third_party/katana/lib/usdKatana/readGprim.cpp index 37ef15748a..afd4c47266 100644 --- a/third_party/katana/lib/usdKatana/readGprim.cpp +++ b/third_party/katana/lib/usdKatana/readGprim.cpp @@ -67,6 +67,8 @@ PxrUsdKatanaGeomGetPAttr( // Used to compare value sizes to identify varying topology. int arraySize = -1; + const bool isMotionBackward = data.GetUsdInArgs()->IsMotionBackward(); + FnKat::FloatBuilder attrBuilder(/* tupleSize = */ 3); TF_FOR_ALL(iter, motionSampleTimes) { @@ -85,7 +87,9 @@ PxrUsdKatanaGeomGetPAttr( break; } - std::vector &ptVec = attrBuilder.get(fabs(relSampleTime)); + std::vector &ptVec = attrBuilder.get(isMotionBackward ? + PxrUsdKatanaUtils::ReverseTimeSample(relSampleTime) : relSampleTime); + PxrUsdKatanaUtils::ConvertArrayToVector(ptArray, &ptVec); } @@ -257,6 +261,8 @@ PxrUsdKatanaGeomGetNormalAttr( const std::vector& motionSampleTimes = data.GetMotionSampleTimes(normalsAttr); + const bool isMotionBackward = data.GetUsdInArgs()->IsMotionBackward(); + FnKat::FloatBuilder attrBuilder(/* tupleSize = */ 3); TF_FOR_ALL(iter, motionSampleTimes) { @@ -267,7 +273,9 @@ PxrUsdKatanaGeomGetNormalAttr( VtVec3fArray normalsArray; normalsAttr.Get(&normalsArray, time); - std::vector &normalsVec = attrBuilder.get(fabs(relSampleTime)); + std::vector &normalsVec = attrBuilder.get(isMotionBackward ? + PxrUsdKatanaUtils::ReverseTimeSample(relSampleTime) : relSampleTime); + PxrUsdKatanaUtils::ConvertArrayToVector(normalsArray, &normalsVec); } diff --git a/third_party/katana/lib/usdKatana/readNurbsPatch.cpp b/third_party/katana/lib/usdKatana/readNurbsPatch.cpp index 513378effb..23190d9f78 100644 --- a/third_party/katana/lib/usdKatana/readNurbsPatch.cpp +++ b/third_party/katana/lib/usdKatana/readNurbsPatch.cpp @@ -106,7 +106,8 @@ static FnKat::FloatAttribute _GetPwAttr( const UsdGeomNurbsPatch &nurbsPatch, double currentTime, - const std::vector& motionSampleTimes) + const std::vector& motionSampleTimes, + const bool isMotionBackward) { UsdAttribute weightsAttr = nurbsPatch.GetPointWeightsAttr(); UsdAttribute pointsAttr = nurbsPatch.GetPointsAttr(); @@ -143,7 +144,9 @@ _GetPwAttr( } // set the points data in katana at the give motion sample time - std::vector &ptVec = pwBuilder.get(fabs(relSampleTime)); + std::vector &ptVec = pwBuilder.get(isMotionBackward ? + PxrUsdKatanaUtils::ReverseTimeSample(relSampleTime) : relSampleTime); + ptVec.resize(ptArray.size() * 4); size_t count = 0; @@ -323,7 +326,8 @@ PxrUsdKatanaReadNurbsPatch( FnKat::GroupBuilder geometryBuilder; - geometryBuilder.set("point.Pw", _GetPwAttr(nurbsPatch, currentTime, motionSampleTimes)); + geometryBuilder.set("point.Pw", _GetPwAttr( + nurbsPatch, currentTime, motionSampleTimes, data.GetUsdInArgs()->IsMotionBackward())); geometryBuilder.set("u", _GetUAttr(nurbsPatch, currentTime)); geometryBuilder.set("v", _GetVAttr(nurbsPatch, currentTime)); geometryBuilder.set("uSize", _GetUSizeAttr(nurbsPatch, currentTime)); diff --git a/third_party/katana/lib/usdKatana/readXformable.cpp b/third_party/katana/lib/usdKatana/readXformable.cpp index 1a10d42690..ee64c9213e 100644 --- a/third_party/katana/lib/usdKatana/readXformable.cpp +++ b/third_party/katana/lib/usdKatana/readXformable.cpp @@ -25,6 +25,7 @@ #include "usdKatana/readPrim.h" #include "usdKatana/readXformable.h" #include "usdKatana/usdInPrivateData.h" +#include "usdKatana/utils.h" #include "pxr/usd/usdGeom/xform.h" @@ -58,6 +59,8 @@ PxrUsdKatanaReadXformable( FnKat::GroupBuilder gb; + const bool isMotionBackward = data.GetUsdInArgs()->IsMotionBackward(); + // For each xform op, construct a matrix containing the // transformation data for each time sample it has. // @@ -80,7 +83,9 @@ PxrUsdKatanaReadXformable( // Convert to vector. const double *matArray = mat.GetArray(); - std::vector &matVec = matBuilder.get(fabs(relSampleTime)); + std::vector &matVec = matBuilder.get(isMotionBackward ? + PxrUsdKatanaUtils::ReverseTimeSample(relSampleTime) : relSampleTime); + matVec.resize(16); for (int i = 0; i < 16; ++i) { diff --git a/third_party/katana/lib/usdKatana/usdInArgs.cpp b/third_party/katana/lib/usdKatana/usdInArgs.cpp index e51fddcecd..61c5c07f71 100644 --- a/third_party/katana/lib/usdKatana/usdInArgs.cpp +++ b/third_party/katana/lib/usdKatana/usdInArgs.cpp @@ -53,6 +53,9 @@ PxrUsdKatanaUsdInArgs::PxrUsdKatanaUsdInArgs( _extraAttributesOrNamespaces(extraAttributesOrNamespaces), _verbose(verbose) { + _isMotionBackward = _motionSampleTimes.size() > 1 and + _motionSampleTimes.front() > _motionSampleTimes.back(); + if (errorMessage) { _errorMessage = errorMessage; diff --git a/third_party/katana/lib/usdKatana/usdInArgs.h b/third_party/katana/lib/usdKatana/usdInArgs.h index 9faef1134e..5c040d0f6b 100644 --- a/third_party/katana/lib/usdKatana/usdInArgs.h +++ b/third_party/katana/lib/usdKatana/usdInArgs.h @@ -119,6 +119,15 @@ class PxrUsdKatanaUsdInArgs : public TfRefBase return _motionSampleTimes; } + /// \brief Return true if motion blur is backward. + /// + /// PxrUsdIn supports both forward and backward motion blur. Motion + /// blur is considered backward if multiple samples are requested + /// and the first specified sample is later than the last sample. + const bool IsMotionBackward() const { + return _isMotionBackward; + } + const StringListMap& GetExtraAttributesOrNamespaces() const { return _extraAttributesOrNamespaces; } @@ -164,6 +173,7 @@ class PxrUsdKatanaUsdInArgs : public TfRefBase double _shutterOpen; double _shutterClose; std::vector _motionSampleTimes; + bool _isMotionBackward; // maps the root-level attribute name to the specified attributes or namespaces StringListMap _extraAttributesOrNamespaces; diff --git a/third_party/katana/lib/usdKatana/usdInPrivateData.cpp b/third_party/katana/lib/usdKatana/usdInPrivateData.cpp index 6bee9dedc1..62daf36d31 100644 --- a/third_party/katana/lib/usdKatana/usdInPrivateData.cpp +++ b/third_party/katana/lib/usdKatana/usdInPrivateData.cpp @@ -75,13 +75,6 @@ PxrUsdKatanaUsdInPrivateData::PxrUsdKatanaUsdInPrivateData( } } -const std::vector -PxrUsdKatanaUsdInPrivateData::_GetNoMotion() -{ - static std::vector noMotion = {0.0}; - return noMotion; -} - const std::vector PxrUsdKatanaUsdInPrivateData::GetMotionSampleTimes(const UsdAttribute& attr) const { @@ -89,7 +82,8 @@ PxrUsdKatanaUsdInPrivateData::GetMotionSampleTimes(const UsdAttribute& attr) con if (attr and not PxrUsdKatanaUtils::IsAttributeVarying(attr, currentTime)) { - return _GetNoMotion(); + static std::vector noMotion = {0.0}; + return noMotion; } const std::vector motionSampleTimes = _usdInArgs->GetMotionSampleTimes(); @@ -107,15 +101,11 @@ PxrUsdKatanaUsdInPrivateData::GetMotionSampleTimes(const UsdAttribute& attr) con double shutterOpen = _usdInArgs->GetShutterOpen(); double shutterClose = _usdInArgs->GetShutterClose(); - double motionBegin = std::min( - motionSampleTimes.front(), motionSampleTimes.back()); - double shutterStartTime, shutterCloseTime; - // Calculate shutter start and close times based on whether - // we're to grab samples up to the current frame or from the - // current frame (typical motion specification is [0 -1]) - if (motionBegin < 0) + // Calculate shutter start and close times based on + // the direction of motion blur. + if (_usdInArgs->IsMotionBackward()) { shutterStartTime = currentTime - shutterClose; shutterCloseTime = currentTime - shutterOpen; @@ -134,17 +124,24 @@ PxrUsdKatanaUsdInPrivateData::GetMotionSampleTimes(const UsdAttribute& attr) con return motionSampleTimes; } - if (result.empty()) + bool foundSamplesInInterval = not result.empty(); + + double firstSample, lastSample; + + if (foundSamplesInInterval) { - return motionSampleTimes; + firstSample = result.front(); + lastSample = result.back(); + } + else + { + firstSample = shutterStartTime; + lastSample = shutterCloseTime; } - double firstSample = result.front(); - double lastSample = result.back(); - - // If the first sample is later than the shutter start time - // then attempt to get the previous sample in time. - if ((firstSample-shutterStartTime) > epsilon) + // If no samples were found or the first sample is later than the + // shutter start time then attempt to get the previous sample in time. + if (not foundSamplesInInterval or (firstSample-shutterStartTime) > epsilon) { double lower, upper; bool hasTimeSamples; @@ -161,9 +158,9 @@ PxrUsdKatanaUsdInPrivateData::GetMotionSampleTimes(const UsdAttribute& attr) con } } - // If the last sample is earlier than the shutter close time - // then attempt to get the next sample in time. - if ((shutterCloseTime-lastSample) > epsilon) + // If no samples were found or the last sample is earlier than the + // shutter close time then attempt to get the next sample in time. + if (not foundSamplesInInterval or (shutterCloseTime-lastSample) > epsilon) { double lower, upper; bool hasTimeSamples; diff --git a/third_party/katana/lib/usdKatana/usdInPrivateData.h b/third_party/katana/lib/usdKatana/usdInPrivateData.h index 915550f130..1bef0e3b52 100644 --- a/third_party/katana/lib/usdKatana/usdInPrivateData.h +++ b/third_party/katana/lib/usdKatana/usdInPrivateData.h @@ -66,8 +66,6 @@ class PxrUsdKatanaUsdInPrivateData : public Foundry::Katana::GeolibPrivateData private: - static const std::vector _GetNoMotion(); - UsdPrim _prim; PxrUsdKatanaUsdInArgsRefPtr _usdInArgs; diff --git a/third_party/katana/lib/usdKatana/utils.cpp b/third_party/katana/lib/usdKatana/utils.cpp index ff2db18f32..e6880243d8 100644 --- a/third_party/katana/lib/usdKatana/utils.cpp +++ b/third_party/katana/lib/usdKatana/utils.cpp @@ -102,6 +102,14 @@ _ResolveAssetPath(const std::string &assetPath, bool asModel) return assetPath; } +double +PxrUsdKatanaUtils::ReverseTimeSample(double sample) +{ + // Only multiply when the sample is not 0 to avoid writing + // out a motion block containing -0. + return (sample == 0.0) ? sample : sample * -1; +} + void PxrUsdKatanaUtils::ConvertNumVertsToStartVerts( const std::vector &numVertsVec, std::vector *startVertsVec ) @@ -1235,6 +1243,7 @@ FnKat::DoubleAttribute PxrUsdKatanaUtils::ConvertBoundsToAttribute( const std::vector& bounds, const std::vector& motionSampleTimes, + const bool isMotionBackward, bool* hasInfiniteBounds) { FnKat::DoubleBuilder boundBuilder(6); @@ -1265,7 +1274,9 @@ PxrUsdKatanaUtils::ConvertBoundsToAttribute( *hasInfiniteBounds = true; } - std::vector &boundData = boundBuilder.get(fabs(relSampleTime)); + std::vector &boundData = boundBuilder.get( + isMotionBackward ? PxrUsdKatanaUtils::ReverseTimeSample(relSampleTime) : relSampleTime); + boundData.push_back( min[0] ); boundData.push_back( max[0] ); boundData.push_back( min[1] ); diff --git a/third_party/katana/lib/usdKatana/utils.h b/third_party/katana/lib/usdKatana/utils.h index b54768b03f..10a917d58e 100644 --- a/third_party/katana/lib/usdKatana/utils.h +++ b/third_party/katana/lib/usdKatana/utils.h @@ -42,6 +42,10 @@ namespace FnKat = Foundry::Katana; struct PxrUsdKatanaUtils { + /// Reverse a motion time sample. This is used for building + /// multi-sampled attributes when motion blur is backward. + static double ReverseTimeSample(double sample); + /// Convert Pixar-style numVerts to Katana-style startVerts. static void ConvertNumVertsToStartVerts( const std::vector &numVertsVec, std::vector *startVertsVec ); @@ -143,6 +147,7 @@ struct PxrUsdKatanaUtils { static FnKat::DoubleAttribute ConvertBoundsToAttribute( const std::vector& bounds, const std::vector& motionSampleTimes, + bool isMotionBackward, bool* hasInfiniteBounds); /// \} diff --git a/third_party/katana/plugin/pxrUsdIn/pxrUsdIn.cpp b/third_party/katana/plugin/pxrUsdIn/pxrUsdIn.cpp index db6eb88444..0328291f40 100644 --- a/third_party/katana/plugin/pxrUsdIn/pxrUsdIn.cpp +++ b/third_party/katana/plugin/pxrUsdIn/pxrUsdIn.cpp @@ -738,9 +738,10 @@ class PxrUsdInOp : public FnKat::GeolibOp } std::vector bounds = usdInArgs->ComputeBounds(prim); const std::vector& motionSampleTimes = usdInArgs->GetMotionSampleTimes(); + bool hasInfiniteBounds = false; FnKat::DoubleAttribute boundsAttr = PxrUsdKatanaUtils::ConvertBoundsToAttribute( - bounds, motionSampleTimes, &hasInfiniteBounds); + bounds, motionSampleTimes, usdInArgs->IsMotionBackward(), &hasInfiniteBounds); // Report infinite bounds as a warning. if (hasInfiniteBounds) { From 7cc5b03cbf3b474dcd39ca26e66f71c110d4d4fb Mon Sep 17 00:00:00 2001 From: mattyjams Date: Thu, 25 Aug 2016 10:58:58 -0700 Subject: [PATCH 019/380] transform GL lights from world space to view space for VP1.0 px_vp20Utils::setupLightingGL() already does this for lights when rendering in Maya using VP2.0, but that code is bypassed when using VP1.0. (Internal change: 1645964) --- .../maya/lib/pxrUsdMayaGL/batchRenderer.cpp | 27 ++++++++++++++++--- .../maya/lib/pxrUsdMayaGL/batchRenderer.h | 2 +- 2 files changed, 24 insertions(+), 5 deletions(-) diff --git a/third_party/maya/lib/pxrUsdMayaGL/batchRenderer.cpp b/third_party/maya/lib/pxrUsdMayaGL/batchRenderer.cpp index a290081567..16e255b9f5 100644 --- a/third_party/maya/lib/pxrUsdMayaGL/batchRenderer.cpp +++ b/third_party/maya/lib/pxrUsdMayaGL/batchRenderer.cpp @@ -571,13 +571,25 @@ UsdMayaGLBatchRenderer::TaskDelegate::SetCameraState( } void -UsdMayaGLBatchRenderer::TaskDelegate::SetLightingStateFromOpenGL() +UsdMayaGLBatchRenderer::TaskDelegate::SetLightingStateFromOpenGL(const MMatrix& viewMatForLights) { // XXX: this is a dumb copy of UsdImaging::HdEngine // ideally we should directly suck the lightint parameter from // maya API and put them into HdLight. - _lightingContextForOpenGLState->SetStateFromOpenGL(); + // We only transform the light positions into view space if the view matrix + // is non-identity (the VP1.0 case). If the view matrix is identity (the + // VP2.0 case), the light positions have already been transformed, so don't + // doubly transform them. + if (viewMatForLights != MMatrix::identity) { + glMatrixMode(GL_MODELVIEW); + glPushMatrix(); + glLoadMatrixd(viewMatForLights.matrix[0]); + _lightingContextForOpenGLState->SetStateFromOpenGL(); + glPopMatrix(); + } else { + _lightingContextForOpenGLState->SetStateFromOpenGL(); + } // cache the GlfSimpleLight vector GlfSimpleLightVector const &lights @@ -1127,10 +1139,17 @@ UsdMayaGLBatchRenderer::_RenderBatches( glDisable(GL_BLEND); glEnable(GL_SAMPLE_ALPHA_TO_COVERAGE); - if( vp2Context ) + // With VP2.0, the utils method will take care of transforming the light + // positions from world space into view space when it loads them into GL. + // For VP1.0, we will need to transform the light positions ourselves. + MMatrix viewMatForLights; + if (vp2Context) { px_vp20Utils::setupLightingGL(*vp2Context); + } else { + viewMatForLights = viewMat; + } - _taskDelegate->SetLightingStateFromOpenGL(); + _taskDelegate->SetLightingStateFromOpenGL(viewMatForLights); // The legacy viewport does not support color management, // so we roll our own gamma correction by GL means (only in diff --git a/third_party/maya/lib/pxrUsdMayaGL/batchRenderer.h b/third_party/maya/lib/pxrUsdMayaGL/batchRenderer.h index 1cbea4a284..4742cf9d3c 100644 --- a/third_party/maya/lib/pxrUsdMayaGL/batchRenderer.h +++ b/third_party/maya/lib/pxrUsdMayaGL/batchRenderer.h @@ -245,7 +245,7 @@ class UsdMayaGLBatchRenderer : private boost::noncopyable void SetCameraState(const GfMatrix4d& viewMatrix, const GfMatrix4d& projectionMatrix, const GfVec4d& viewport); - void SetLightingStateFromOpenGL(); + void SetLightingStateFromOpenGL(const MMatrix& viewMatForLights); HdTaskSharedPtrVector GetSetupTasks(); From 410f93d3a27c23e7a0f3f98bd609c1359cd95b01 Mon Sep 17 00:00:00 2001 From: superfunc Date: Thu, 25 Aug 2016 10:59:33 -0700 Subject: [PATCH 020/380] [Pxr] Fix relative links. (Internal change: 1646115) (Internal change: 1646405) --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 14b9260616..26326c2ee8 100644 --- a/README.md +++ b/README.md @@ -93,7 +93,7 @@ make -j install #### On OS X (experimental) The following will generate an Xcode project that can be used to build USD. -See notes in the [Supported Platforms](#Supported-Platforms) section +See notes in the [Supported Platforms](#supported-platforms) section for more information. ```bash @@ -115,7 +115,7 @@ make -j install The following will generate a Visual Studio 2015 (the minimum required version) sln file which can be used to build USD. See notes in the -[Supported Platforms](#Supported-Platforms) section for more information. +[Supported Platforms](#supported-platforms) section for more information. ```powershell C:\Program Files\CMake\bin\cmake.exe ^ From 8d52ad3be2d4252a63f8d3ee1c754b36350039e1 Mon Sep 17 00:00:00 2001 From: superfunc Date: Thu, 25 Aug 2016 10:59:58 -0700 Subject: [PATCH 021/380] [Pxr] Fix bug in cmake which caused USDSchemaGen to not work. When writing out the usdGenSchema Python file. CMake was stripping out semicolons. This caused the resulting python file to have the following string: customCode = _ExtractCustomCode(clsHFilePath, default='}\n\n#endif\n') whereas the original had: customCode = _ExtractCustomCode(clsHFilePath, default='};\n\n#endif\n') This caused usdGenSchema to generate syntactically invalid C++ classes( no closing semicolon) in the case where a user had no custom code and the default string above would be used. Credit to github user murphyeoin for filing the bug and pointing us to the fix. Fixes #15 (Internal change: 1646239) --- cmake/macros/Public.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/macros/Public.cmake b/cmake/macros/Public.cmake index 75952e8cc5..a04c37499d 100644 --- a/cmake/macros/Public.cmake +++ b/cmake/macros/Public.cmake @@ -34,7 +34,7 @@ function(pxr_python_bins) file(READ ${pyFile} contents) string(REGEX REPLACE "/pxrpythonsubst" ${PXR_PYTHON_SHEBANG} contents "${contents}") - file(WRITE ${CMAKE_BINARY_DIR}/${pyFile} ${contents}) + file(WRITE ${CMAKE_BINARY_DIR}/${pyFile} "${contents}") install(PROGRAMS ${CMAKE_BINARY_DIR}/${pyFile} From 448a80df62db83ccd9f888b5f0fe2491cedeeb4f Mon Sep 17 00:00:00 2001 From: jmk Date: Thu, 25 Aug 2016 11:01:23 -0700 Subject: [PATCH 022/380] Fixed a bug that could cause a crash when trying to convert an unbound instance method from python (see testTfPython for an example). (Internal change: 1646384) --- pxr/base/lib/tf/pyFunction.h | 19 ++++++++++--------- pxr/base/lib/tf/testenv/testTfPython.py | 2 ++ pxr/base/lib/tf/wrapTestTfPython.cpp | 5 +++++ 3 files changed, 17 insertions(+), 9 deletions(-) diff --git a/pxr/base/lib/tf/pyFunction.h b/pxr/base/lib/tf/pyFunction.h index deed2dc3b3..a67595c8eb 100644 --- a/pxr/base/lib/tf/pyFunction.h +++ b/pxr/base/lib/tf/pyFunction.h @@ -146,22 +146,23 @@ struct TfPyFunctionFromPython // for most usage patterns. object callable(handle<>(borrowed(src))); - - if (PyMethod_Check(callable.ptr())) { + PyObject *pyCallable = callable.ptr(); + PyObject *self = + PyMethod_Check(pyCallable) ? PyMethod_GET_SELF(pyCallable) : NULL; + + if (self) { // Deconstruct the method and attempt to get a weak reference to // the self instance. - PyObject *method = callable.ptr(); - object cls(handle<>(borrowed(PyMethod_GET_CLASS(method)))); - object func(handle<>(borrowed(PyMethod_GET_FUNCTION(method)))); - object weakSelf - (handle<>(PyWeakref_NewRef(PyMethod_GET_SELF(method), NULL))); + object cls(handle<>(borrowed(PyMethod_GET_CLASS(pyCallable)))); + object func(handle<>(borrowed(PyMethod_GET_FUNCTION(pyCallable)))); + object weakSelf(handle<>(PyWeakref_NewRef(self, NULL))); new (storage) FuncType(bind(CallMethod, TfPyObjWrapper(func), TfPyObjWrapper(weakSelf), TfPyObjWrapper(cls) BOOST_PP_ENUM_TRAILING(N, PLACEHOLDER, ~))); - } else if (PyObject_HasAttrString(callable.ptr(), "__name__") and + } else if (PyObject_HasAttrString(pyCallable, "__name__") and extract(callable.attr("__name__"))() == "") { // Explicitly hold on to strong references to lambdas. new (storage) @@ -170,7 +171,7 @@ struct TfPyFunctionFromPython } else { // Attempt to get a weak reference to the callable. if (PyObject *weakCallable = - PyWeakref_NewRef(callable.ptr(), NULL)) { + PyWeakref_NewRef(pyCallable, NULL)) { new (storage) FuncType(bind(CallWeak, TfPyObjWrapper(object(handle<>(weakCallable))) diff --git a/pxr/base/lib/tf/testenv/testTfPython.py b/pxr/base/lib/tf/testenv/testTfPython.py index 6dbf7491ac..3d8f1aad4d 100644 --- a/pxr/base/lib/tf/testenv/testTfPython.py +++ b/pxr/base/lib/tf/testenv/testTfPython.py @@ -324,6 +324,8 @@ def method(self): del l self.assertEqual('python lambda', Tf._invokeTestCallback()) + # Test unbound instance method. + self.assertEqual('test', Tf._callUnboundInstance(str.lower, "TEST")) # the callback is a function, it should not stay alive def func(): diff --git a/pxr/base/lib/tf/wrapTestTfPython.cpp b/pxr/base/lib/tf/wrapTestTfPython.cpp index c14222fe3a..24ada044a9 100644 --- a/pxr/base/lib/tf/wrapTestTfPython.cpp +++ b/pxr/base/lib/tf/wrapTestTfPython.cpp @@ -327,6 +327,10 @@ static string stringStringCallback(boost::function const &f) { return f("c++ is calling..."); } +static string callUnboundInstance(boost::function const &f, + string const &str) { + return f(str); +} static TfStaticData > _testCallback; @@ -445,6 +449,7 @@ void wrapTf_TestTfPython() def("_stringStringCallback", stringStringCallback); def("_setTestCallback", setTestCallback); def("_invokeTestCallback", invokeTestCallback); + def("_callUnboundInstance", callUnboundInstance); TfPyWrapEnum(); From 2b20215ab8238e0f2152081afa34273d1ae8ab87 Mon Sep 17 00:00:00 2001 From: gitamohr Date: Thu, 25 Aug 2016 12:52:43 -0700 Subject: [PATCH 023/380] pcp/usd: Change the pcp parallel indexing API to take a payload predicate. We evaluate this predicate for every prim index computed during parallel indexing that has a payload and isn't in the cache's include set. If the predicate returns true, then we index with the payload included, and add the payload to the cache's include set as indexing completes. Usd makes use of this to auto-include discovered payloads at stage open time, and to auto-load new payloads if their nearest ancestor's payload was also included. (Internal change: 1646394) --- pxr/usd/lib/pcp/cache.cpp | 112 ++++++++++++++++++++++++---------- pxr/usd/lib/pcp/cache.h | 99 ++++++++++++++++++++---------- pxr/usd/lib/pcp/primIndex.cpp | 24 +++++++- pxr/usd/lib/pcp/primIndex.h | 36 ++++++++--- pxr/usd/lib/usd/stage.cpp | 112 ++++++++++++++++++++++++++++------ pxr/usd/lib/usd/stage.h | 15 ++++- 6 files changed, 305 insertions(+), 93 deletions(-) diff --git a/pxr/usd/lib/pcp/cache.cpp b/pxr/usd/lib/pcp/cache.cpp index 30df90aa5a..affabd9078 100644 --- a/pxr/usd/lib/pcp/cache.cpp +++ b/pxr/usd/lib/pcp/cache.cpp @@ -2468,13 +2468,15 @@ PcpCache::_GetPrimIndex(const SdfPath& path) const return NULL; } -template +template struct Pcp_ParallelIndexer { typedef Pcp_ParallelIndexer This; + template Pcp_ParallelIndexer(PcpCache *cache, - Predicate pred, + ChildrenPredicate childrenPred, + PayloadPredicate payloadPred, const PcpLayerStackPtr &layerStack, PcpPrimIndexInputs baseInputs, PcpErrorVector *allErrors, @@ -2483,7 +2485,7 @@ struct Pcp_ParallelIndexer const char *mallocTag2) : _cache(cache) , _allErrors(allErrors) - , _predicate(pred) + , _childrenPredicate(childrenPred) , _layerStack(layerStack) , _baseInputs(baseInputs) , _resolver(ArGetResolver()) @@ -2491,13 +2493,21 @@ struct Pcp_ParallelIndexer , _parentCache(parentCache) , _mallocTag1(mallocTag1) , _mallocTag2(mallocTag2) - {} + { + // Set the payload predicate in the base inputs, as well as the + // includedPayloadsMutex. + _baseInputs + .IncludedPayloadsMutex(&_includedPayloadsMutex) + .IncludePayloadPredicate(payloadPred) + ; + } ~Pcp_ParallelIndexer() { // Tear down async. WorkSwapDestroyAsync(_toCompute); WorkMoveDestroyAsync(_finishedOutputs); WorkSwapDestroyAsync(_consumerScratch); + WorkSwapDestroyAsync(_consumerScratchPayloads); // We need to tear down the _results synchronously because doing so may // drop layers, and that's something that clients rely on, but we can @@ -2506,7 +2516,7 @@ struct Pcp_ParallelIndexer [](PcpPrimIndexOutputs &out) { PcpPrimIndexOutputs().swap(out); }); - } + } // Run the added work and wait for it to complete. void RunAndWait() { @@ -2568,7 +2578,7 @@ struct Pcp_ParallelIndexer // Invoke the client's predicate to see if we should do children. bool didChildren = false; - if (_predicate(*index)) { + if (_childrenPredicate(*index)) { // Compute the children paths and add new tasks for them. TfTokenVector names; PcpTokenSet prohibitedNames; @@ -2609,18 +2619,54 @@ struct Pcp_ParallelIndexer _allErrors->insert(_allErrors->end(), outputs->allErrors.begin(), outputs->allErrors.end()); - + + SdfPath const &primIndexPath = outputs->primIndex.GetPath(); + // Add dependencies. - _cache->_AddIndexDependencies( - outputs->primIndex.GetPath(), outputs); + _cache->_AddIndexDependencies(primIndexPath, outputs); // Store index off to the side so we can publish several at once, // ideally. We have to make a copy to move into the _cache itself, // since sibling caches in other tasks will still require that their // parent be valid. _consumerScratch.push_back(outputs->primIndex); + + // Store included payload path to the side to publish several at + // once, as well. + if (outputs->includedDiscoveredPayload) + _consumerScratchPayloads.push_back(primIndexPath); } - + + // This size threshold is arbitrary but helps ensure that even with + // writer starvation we'll avoid growing our working spaces too large. + static const size_t PendingSizeThreshold = 20000; + + if (not _consumerScratchPayloads.empty()) { + // Publish to _includedPayloads if possible. If we're told to + // flush, or if we're over a threshold number of pending results, + // then take the write lock and publish. Otherwise only attempt to + // take the write lock, and if we fail to do so then we do nothing, + // since we're guaranteed to run again. This helps minimize + // contention and maximize throughput. + tbb::spin_rw_mutex::scoped_lock lock; + + bool locked = flush || + _consumerScratch.size() >= PendingSizeThreshold; + if (locked) { + lock.acquire(_includedPayloadsMutex, /*write=*/true); + } else { + locked = lock.try_acquire( + _includedPayloadsMutex, /*write=*/true); + } + if (locked) { + for (auto const &path: _consumerScratchPayloads) { + _cache->_includedPayloads.insert(path); + } + lock.release(); + _consumerScratchPayloads.clear(); + } + } + // Ok, publish the set of indexes. if (not _consumerScratch.empty()) { // If we're told to flush, or if we're over a threshold number of @@ -2628,38 +2674,39 @@ struct Pcp_ParallelIndexer // only attempt to take the write lock, and if we fail to do so then // we do nothing, since we're guaranteed to run again. This helps // minimize contention and maximize throughput. - - // This size threshold is arbitrary but helps ensure that even with - // writer starvation we'll never grow our working space too huge. - static const size_t PendingSizeThreshold = 20000; - tbb::spin_rw_mutex::scoped_lock lock; - if (flush or _consumerScratch.size() >= PendingSizeThreshold) { + + bool locked = flush || + _consumerScratch.size() >= PendingSizeThreshold; + if (locked) { lock.acquire(_primIndexCacheMutex, /*write=*/true); } else { - if (not lock.try_acquire(_primIndexCacheMutex, /*write=*/true)) - return; + locked = lock.try_acquire(_primIndexCacheMutex, /*write=*/true); } - for (auto &index: _consumerScratch) { - // Save the prim index in the cache. - const SdfPath &path = index.GetPath(); - _cache->_primIndexCache[path].Swap(index); + if (locked) { + for (auto &index: _consumerScratch) { + // Save the prim index in the cache. + const SdfPath &path = index.GetPath(); + _cache->_primIndexCache[path].Swap(index); + } + lock.release(); + _consumerScratch.clear(); } - lock.release(); - _consumerScratch.clear(); } } PcpCache *_cache; PcpErrorVector *_allErrors; - Predicate _predicate; + ChildrenPredicate _childrenPredicate; vector > _toCompute; const PcpLayerStackPtr &_layerStack; PcpPrimIndexInputs _baseInputs; tbb::concurrent_vector _results; tbb::spin_rw_mutex _primIndexCacheMutex; + tbb::spin_rw_mutex _includedPayloadsMutex; tbb::concurrent_queue _finishedOutputs; vector _consumerScratch; + vector _consumerScratchPayloads; ArResolver& _resolver; WorkDispatcher _dispatcher; WorkSingularTask _consumer; @@ -2672,7 +2719,8 @@ void PcpCache::_ComputePrimIndexesInParallel( const SdfPathVector &roots, PcpErrorVector *allErrors, - _UntypedPredicate pred, + _UntypedIndexingChildrenPredicate childrenPred, + _UntypedIndexingPayloadPredicate payloadPred, const char *mallocTag1, const char *mallocTag2) { @@ -2685,22 +2733,22 @@ PcpCache::_ComputePrimIndexesInParallel( TF_PY_ALLOW_THREADS_IN_SCOPE(); ArResolverScopedCache parentCache; - TfAutoMallocTag2 tag(mallocTag1, mallocTag2); + TfAutoMallocTag2 tag(mallocTag1, mallocTag2); - typedef Pcp_ParallelIndexer<_UntypedPredicate> Indexer; + using Indexer = Pcp_ParallelIndexer<_UntypedIndexingChildrenPredicate>; if (not _layerStack) ComputeLayerStack(GetLayerStackIdentifier(), allErrors); // General strategy: Compute indexes recursively starting from roots, in - // parallel. When we've computed an index, ask the predicate if we should - // continue to compute its children indexes. If so, we add all the children - // as new tasks for threads to pick up. + // parallel. When we've computed an index, ask the children predicate if we + // should continue to compute its children indexes. If so, we add all the + // children as new tasks for threads to pick up. // // Once all the indexes are computed, add them to the cache and add their // dependencies to the dependencies structures. - Indexer indexer(this, pred, _layerStack, + Indexer indexer(this, childrenPred, payloadPred, _layerStack, GetPrimIndexInputs().USD(_usd), allErrors, &parentCache, mallocTag1, mallocTag2); diff --git a/pxr/usd/lib/pcp/cache.h b/pxr/usd/lib/pcp/cache.h index cc7f1732ca..3d7e0a801e 100644 --- a/pxr/usd/lib/pcp/cache.h +++ b/pxr/usd/lib/pcp/cache.h @@ -254,57 +254,73 @@ class PcpCache ComputePrimIndex(const SdfPath &primPath, PcpErrorVector *allErrors); /// Compute PcpPrimIndexes in the subtree rooted at path in parallel, - /// subject to the supplied predicate \p pred. This is similar to - /// ComputePrimIndex(), except it will compute an entire subtree of indexes - /// in parallel, so it can be much more efficient. This function invokes - /// \p pred concurrently, so it must be safe to do so. When a PcpPrimIndex - /// is finished being computed, this function invokes \p pred, passing it - /// the PcpPrimIndex. If \p pred returns true, this function will continue - /// to the children and compute their indexes. If \p pred returns false, - /// prim index computation ceases for that subtree. - template + /// recursing to children based on the supplied \p childrenPred. Also + /// include payloads not already in this cache's included payloads (see + /// GetIncludedPayloads()) according to \p payloadPred. + /// + /// This is similar to ComputePrimIndex(), except it computes an entire + /// subtree of indexes in parallel so it can be much more efficient. This + /// function invokes both \p childrenPred and \p payloadPred concurrently, + /// so it must be safe to do so. When a PcpPrimIndex computation completes + /// invoke \p childrenPred, passing it the PcpPrimIndex. If \p childrenPred + /// returns true, continue indexing children prim indexes. Conversely if + /// \p childrenPred returns false, stop indexing in that subtree. If + /// payloads discovered during indexing do not already appear in this + /// cache's set of included payloads, invoke \p payloadPred, passing it the + /// path for the prim with the payload. If \p payloadPred returns true, + /// include its payload and add it to the cache's set of included payloads + /// upon completion. + template void ComputePrimIndexesInParallel(const SdfPath &path, PcpErrorVector *allErrors, - const Predicate &pred) { - ComputePrimIndexesInParallel(SdfPathVector(1, path), allErrors, pred, + const ChildrenPredicate &childrenPred, + const PayloadPredicate &payloadPred) { + ComputePrimIndexesInParallel(SdfPathVector(1, path), allErrors, + childrenPred, payloadPred, "Pcp", "ComputePrimIndexesInParallel"); } /// \overload /// XXX Do not add new callers of this method. It is needed as a workaround /// for bug #132031, which we hope to tackle soon (as of 6/2016) - template + template void ComputePrimIndexesInParallel(const SdfPath &path, PcpErrorVector *allErrors, - const Predicate &pred, + const ChildrenPredicate &childrenPred, + const PayloadPredicate &payloadPred, const char *mallocTag1, const char *mallocTag2) { - ComputePrimIndexesInParallel(SdfPathVector(1, path), allErrors, pred. + ComputePrimIndexesInParallel(SdfPathVector(1, path), allErrors, + childrenPred, payloadPred, mallocTag1, mallocTag2); } /// Vectorized form of ComputePrimIndexesInParallel(). Equivalent to /// invoking that method for each path in \p paths, but more efficient. - template + template void ComputePrimIndexesInParallel(const SdfPathVector &paths, PcpErrorVector *allErrors, - const Predicate &pred) { - _UntypedPredicate p(&pred); - _ComputePrimIndexesInParallel(paths, allErrors, p, + const ChildrenPredicate &childrenPred, + const PayloadPredicate &payloadPred) { + _UntypedIndexingChildrenPredicate cp(&childrenPred); + _UntypedIndexingPayloadPredicate pp(&payloadPred); + _ComputePrimIndexesInParallel(paths, allErrors, cp, pp, "Pcp", "ComputePrimIndexesInParallel"); } /// \overload /// XXX Do not add new callers of this method. It is needed as a workaround /// for bug #132031, which we hope to tackle soon (as of 6/2016) - template + template void ComputePrimIndexesInParallel(const SdfPathVector &paths, PcpErrorVector *allErrors, - const Predicate &pred, + const ChildrenPredicate &childrenPred, + const PayloadPredicate &payloadPred, const char *mallocTag1, const char *mallocTag2) { - _UntypedPredicate p(&pred); - _ComputePrimIndexesInParallel(paths, allErrors, p, + _UntypedIndexingChildrenPredicate cp(&childrenPred); + _UntypedIndexingPayloadPredicate pp(&payloadPred); + _ComputePrimIndexesInParallel(paths, allErrors, cp, pp, mallocTag1, mallocTag2); } @@ -606,12 +622,12 @@ class PcpCache friend class PcpChanges; friend class Pcp_Statistics; - template + template friend struct Pcp_ParallelIndexer; struct _PathDebugInfo; - // Helper struct to type-erase a predicate for the duration of + // Helper struct to type-erase a children predicate for the duration of // ComputePrimIndexesInParallel. // // This lets us achieve two goals. First, clients may pass any arbitrary @@ -624,9 +640,9 @@ class PcpCache // typecast and predicate invocation, and pass that function pointer into // the implementation. There is no heap allocation, no predicate copy, no // argument marshalling, etc. - struct _UntypedPredicate { + struct _UntypedIndexingChildrenPredicate { template - explicit _UntypedPredicate(const Pred *pred) + explicit _UntypedIndexingChildrenPredicate(const Pred *pred) : pred(pred), invoke(_Invoke) {} inline bool operator()(const PcpPrimIndex &index) const { @@ -641,12 +657,33 @@ class PcpCache bool (*invoke)(const void *, const PcpPrimIndex &); }; + // See doc for _UntypedIndexingChildrenPredicate above. This does the same + // for the payload inclusion predicate. + struct _UntypedIndexingPayloadPredicate { + template + explicit _UntypedIndexingPayloadPredicate(const Pred *pred) + : pred(pred), invoke(_Invoke) {} + + inline bool operator()(const SdfPath &path) const { + return invoke(pred, path); + } + private: + template + static bool _Invoke(const void *pred, const SdfPath &path) { + return (*static_cast(pred))(path); + } + const void *pred; + bool (*invoke)(const void *, const SdfPath &); + }; + // Parallel indexing implementation. - void _ComputePrimIndexesInParallel(const SdfPathVector &paths, - PcpErrorVector *allErrors, - _UntypedPredicate pred, - const char *mallocTag1, - const char *mallocTag2); + void _ComputePrimIndexesInParallel( + const SdfPathVector &paths, + PcpErrorVector *allErrors, + _UntypedIndexingChildrenPredicate childrenPred, + _UntypedIndexingPayloadPredicate payloadPred, + const char *mallocTag1, + const char *mallocTag2); // Helper to add a computed prim index to dependency structures. void _AddIndexDependencies(const SdfPath &path, diff --git a/pxr/usd/lib/pcp/primIndex.cpp b/pxr/usd/lib/pcp/primIndex.cpp index e9794fa604..769402a4fe 100644 --- a/pxr/usd/lib/pcp/primIndex.cpp +++ b/pxr/usd/lib/pcp/primIndex.cpp @@ -3394,13 +3394,33 @@ _EvalNodePayload( // Mark that this prim index contains a payload. // However, only process the payload if it's been requested. index->GetGraph()->SetHasPayload(true); + const PcpPrimIndexInputs::PayloadSet* includedPayloads = indexer->inputs.includedPayloads; - if (not includedPayloads or - includedPayloads->count(node.GetRootNode().GetPath()) == 0) { + + // If includedPayloads is nullptr, we never include payloads. Otherwise if + // it does not have this path, we invoke the predicate. If the predicate + // returns true we set the output bit includedDiscoveredPayload and we + // compose it. + if (!includedPayloads) { PCP_GRAPH_MSG(node, "Payload was not included, skipping"); return; } + SdfPath const &path = node.GetRootNode().GetPath(); + tbb::spin_rw_mutex::scoped_lock lock; + auto *mutex = indexer->inputs.includedPayloadsMutex; + if (mutex) { lock.acquire(*mutex, /*write=*/false); } + bool inIncludeSet = includedPayloads->count(path); + if (mutex) { lock.release(); } + if (!inIncludeSet) { + auto const &pred = indexer->inputs.includePayloadPredicate; + if (pred and pred(path)) { + indexer->outputs->includedDiscoveredPayload = true; + } else { + PCP_GRAPH_MSG(node, "Payload was not included, skipping"); + return; + } + } // Verify the payload prim path. if (not payload.GetPrimPath().IsEmpty() and diff --git a/pxr/usd/lib/pcp/primIndex.h b/pxr/usd/lib/pcp/primIndex.h index f4b4947fde..3898023dd4 100644 --- a/pxr/usd/lib/pcp/primIndex.h +++ b/pxr/usd/lib/pcp/primIndex.h @@ -36,6 +36,8 @@ #include "pxr/base/tf/hashset.h" #include #include +#include +#include #include SDF_DECLARE_HANDLES(SdfLayer); @@ -303,6 +305,10 @@ class PcpPrimIndexOutputs /// List of all errors encountered during indexing. PcpErrorVector allErrors; + + /// True if this prim index has a payload that we included during indexing + /// that wasn't previously in the cache's payload include set. + bool includedDiscoveredPayload = false; /// Swap content with \p r. inline void swap(PcpPrimIndexOutputs &r) { @@ -314,6 +320,7 @@ class PcpPrimIndexOutputs spookyDependencySites.swap(r.spookyDependencySites); spookyDependencyNodes.swap(r.spookyDependencyNodes); allErrors.swap(r.allErrors); + std::swap(includedDiscoveredPayload, r.includedDiscoveredPayload); } }; @@ -327,13 +334,14 @@ inline void swap(PcpPrimIndexOutputs &l, PcpPrimIndexOutputs &r) { l.swap(r); } class PcpPrimIndexInputs { public: PcpPrimIndexInputs() - : cache(NULL) - , variantFallbacks(NULL) - , includedPayloads(NULL) - , parentIndex(NULL) + : cache(nullptr) + , variantFallbacks(nullptr) + , includedPayloads(nullptr) + , includedPayloadsMutex(nullptr) + , parentIndex(nullptr) + , payloadDecorator(nullptr) , cull(true) , usd(false) - , payloadDecorator(NULL) { } /// Returns true if prim index computations using this parameters object @@ -361,6 +369,18 @@ class PcpPrimIndexInputs { PcpPrimIndexInputs& IncludedPayloads(const PayloadSet* payloadSet) { includedPayloads = payloadSet; return *this; } + /// Optional mutex for accessing includedPayloads. + PcpPrimIndexInputs &IncludedPayloadsMutex(tbb::spin_rw_mutex *mutex) + { includedPayloadsMutex = mutex; return *this; } + + /// Optional predicate evaluated when a not-yet-included payload is + /// discovered while indexing. If the predicate returns true, indexing + /// includes the payload and sets the includedDiscoveredPayload bit in the + /// outputs. + PcpPrimIndexInputs &IncludePayloadPredicate( + std::function predicate) + { includePayloadPredicate = predicate; return *this; } + /// Whether subtrees that contribute no opinions should be culled /// from the index. PcpPrimIndexInputs& Cull(bool doCulling = true) @@ -381,11 +401,13 @@ class PcpPrimIndexInputs { PcpCache* cache; const PcpVariantFallbackMap* variantFallbacks; const PayloadSet* includedPayloads; + tbb::spin_rw_mutex *includedPayloadsMutex; + std::function includePayloadPredicate; const PcpPrimIndex *parentIndex; - bool cull; - bool usd; std::string targetSchema; PcpPayloadDecorator* payloadDecorator; + bool cull; + bool usd; }; /// Compute an index for the given path. \p errors will contain any errors diff --git a/pxr/usd/lib/usd/stage.cpp b/pxr/usd/lib/usd/stage.cpp index 7d6c98fa72..5cb446dc4c 100644 --- a/pxr/usd/lib/usd/stage.cpp +++ b/pxr/usd/lib/usd/stage.cpp @@ -346,7 +346,8 @@ _CreateAnonymousSessionLayer(const SdfLayerHandle &rootLayer) UsdStage::UsdStage(const SdfLayerRefPtr& rootLayer, const SdfLayerRefPtr& sessionLayer, - const ArResolverContext& pathResolverContext) + const ArResolverContext& pathResolverContext, + InitialLoadSet load) : _pseudoRoot(0) , _rootLayer(rootLayer) , _sessionLayer(sessionLayer) @@ -359,6 +360,7 @@ UsdStage::UsdStage(const SdfLayerRefPtr& rootLayer, , _instanceCache(new Usd_InstanceCache) , _interpolationType(UsdInterpolationTypeLinear) , _lastChangeSerialNumber(0) + , _initialLoadSet(load) , _isClosingStage(false) { if (not TF_VERIFY(_rootLayer)) @@ -514,27 +516,20 @@ UsdStage::_InstantiateStage(const SdfLayerRefPtr &rootLayer, return TfNullPtr; UsdStageRefPtr stage = TfCreateRefPtr( - new UsdStage(rootLayer, sessionLayer, pathResolverContext)); + new UsdStage(rootLayer, sessionLayer, pathResolverContext, load)); ArResolverScopedCache resolverCache; - // Minimally populate the stage, do not request payloads. + // Populate the stage, request payloads according to InitialLoadSet load. stage->_ComposePrimIndexesInParallel( - SdfPathVector(1, SdfPath::AbsoluteRootPath()), "Instantiating stage"); + SdfPathVector(1, SdfPath::AbsoluteRootPath()), + load == LoadAll ? + _IncludeAllDiscoveredPayloads : _IncludeNoDiscoveredPayloads, + "Instantiating stage"); stage->_pseudoRoot = stage->_InstantiatePrim(SdfPath::AbsoluteRootPath()); stage->_ComposeSubtreeInParallel(stage->_pseudoRoot); stage->_RegisterPerLayerNotices(); - // Include all payloads, if desired. - if (load == LoadAll) { - // we will ignore the aggregation of loads/unloads - // because we won't be using them to send a notification - SdfPathSet include, exclude; - - include.insert(SdfPath::AbsoluteRootPath()); - stage->_LoadAndUnload(include, exclude, NULL, NULL); - } - // Publish this stage into all current writable caches. BOOST_FOREACH(UsdStageCache *cache, UsdStageCacheContext::_GetWritableCaches()) { @@ -3054,7 +3049,8 @@ void UsdStage::_Recompose(const PcpChanges &changes, Usd_InstanceChanges changes; _ComposePrimIndexesInParallel( - primPathsToRecompose, "Recomposing stage", &changes); + primPathsToRecompose, _IncludeNewPayloadsIfAncestorWasIncluded, + "Recomposing stage", &changes); // Determine what instance master prims on this stage need to // be recomposed due to instance prim index changes. @@ -3239,9 +3235,68 @@ UsdStage::_ComputeSubtreesToRecompose( } } +struct UsdStage::_IncludeNewlyDiscoveredPayloadsPredicate +{ + explicit _IncludeNewlyDiscoveredPayloadsPredicate(UsdStage const *stage) + : _stage(stage) {} + + bool operator()(SdfPath const &path) const { + // We want to include newly discovered payloads on existing prims or on + // new prims if their nearest loadable ancestor was loaded, or if there + // is no nearest loadable ancestor and the stage was initially populated + // with LoadAll. + + // First, check to see if this payload is new to us. This is safe to do + // concurrently without a lock since these are only ever reads. + + // The path we're given is a prim index path. Due to instancing, the + // path to the corresponding prim on the stage may differ (it may be a + // generated master path). + SdfPath stagePath = _stage->_GetPrimPathUsingPrimIndexAtPath(path); + if (stagePath.IsEmpty()) + stagePath = path; + + UsdPrim prim = _stage->GetPrimAtPath(stagePath); + bool isNewPayload = !prim or !prim.HasPayload(); + + if (not isNewPayload) + return false; + + // XXX: This does not quite work correctly with instancing. What we + // need to do is once we hit a master, continue searching ancestors of + // all instances that use it. If we find *any* nearest ancestor that's + // loadable, we should return true. + + // This is a new payload -- find the nearest ancestor with a payload. + // First walk up by path until we find an existing prim. + if (prim) { + prim = prim.GetParent(); + } + else { + for (SdfPath curPath = stagePath.GetParentPath(); !prim; + curPath = curPath.GetParentPath()) { + prim = _stage->GetPrimAtPath(curPath); + } + } + + UsdPrim root = _stage->GetPseudoRoot(); + for (; !prim.HasPayload() && prim != root; prim = prim.GetParent()) { + // continue + } + + // If we hit the root, then consult the initial population state. + // Otherwise load the payload if the ancestor is loaded. + return prim != root ? prim.IsLoaded() : + _stage->_initialLoadSet == LoadAll; + } + + UsdStage const *_stage; +}; + void UsdStage::_ComposePrimIndexesInParallel( const std::vector& primIndexPaths, + _IncludePayloadsRule includeRule, const std::string& context, Usd_InstanceChanges* instanceChanges) { @@ -3251,10 +3306,26 @@ UsdStage::_ComposePrimIndexesInParallel( // Ask Pcp to compute all the prim indexes in parallel, stopping at // prim indexes that won't be used by the stage. PcpErrorVector errs; - _cache->ComputePrimIndexesInParallel( - primIndexPaths, - &errs, _NameChildrenPred(_instanceCache.get()), - "Usd", _mallocTagID); + + if (includeRule == _IncludeAllDiscoveredPayloads) { + _cache->ComputePrimIndexesInParallel( + primIndexPaths, &errs, _NameChildrenPred(_instanceCache.get()), + [](const SdfPath &) { return true; }, + "Usd", _mallocTagID); + } + else if (includeRule == _IncludeNoDiscoveredPayloads) { + _cache->ComputePrimIndexesInParallel( + primIndexPaths, &errs, _NameChildrenPred(_instanceCache.get()), + [](const SdfPath &) { return false; }, + "Usd", _mallocTagID); + } + else if (includeRule == _IncludeNewPayloadsIfAncestorWasIncluded) { + _cache->ComputePrimIndexesInParallel( + primIndexPaths, &errs, _NameChildrenPred(_instanceCache.get()), + _IncludeNewlyDiscoveredPayloadsPredicate(this), + "Usd", _mallocTagID); + } + if (not errs.empty()) { _ReportPcpErrors(errs, context); } @@ -3274,7 +3345,8 @@ UsdStage::_ComposePrimIndexesInParallel( // instance. Compose the new source prim indexes. if (not changes.changedMasterPrims.empty()) { _ComposePrimIndexesInParallel( - changes.changedMasterPrimIndexes, context, instanceChanges); + changes.changedMasterPrimIndexes, includeRule, + context, instanceChanges); } } diff --git a/pxr/usd/lib/usd/stage.h b/pxr/usd/lib/usd/stage.h index 185e02cfe6..2477bbe6e0 100644 --- a/pxr/usd/lib/usd/stage.h +++ b/pxr/usd/lib/usd/stage.h @@ -1097,13 +1097,22 @@ class UsdStage : public TfRefBase, public TfWeakBase { /// @} private: + struct _IncludeNewlyDiscoveredPayloadsPredicate; + + enum _IncludePayloadsRule { + _IncludeAllDiscoveredPayloads, + _IncludeNoDiscoveredPayloads, + _IncludeNewPayloadsIfAncestorWasIncluded + }; + // --------------------------------------------------------------------- // // Stage Construction & Initialization // --------------------------------------------------------------------- // UsdStage(const SdfLayerRefPtr& rootLayer, const SdfLayerRefPtr& sessionLayer, - const ArResolverContext& pathResolverContext); + const ArResolverContext& pathResolverContext, + InitialLoadSet load); // Common ref ptr initialization, called by public, static constructors. // @@ -1230,6 +1239,7 @@ class UsdStage : public TfRefBase, public TfWeakBase { // during composition. void _ComposePrimIndexesInParallel( const std::vector& primIndexPaths, + _IncludePayloadsRule includeRule, const std::string& context, Usd_InstanceChanges* instanceChanges = NULL); @@ -1644,6 +1654,9 @@ class UsdStage : public TfRefBase, public TfWeakBase { // for this stage - from all access points - to this tag. char const *_mallocTagID; + // The state used when instantiating the stage. + const InitialLoadSet _initialLoadSet; + bool _isClosingStage; friend class UsdAttribute; From bb2e6fa32fe7712b905252c901e3075fef6af9fd Mon Sep 17 00:00:00 2001 From: takahito-tejima Date: Thu, 25 Aug 2016 13:01:18 -0700 Subject: [PATCH 024/380] [Garch, Glfq] move osx specific code from glfq to garch (Internal change: 1646439) --- .../lib/garch/glPlatformContextDarwin.mm | 14 +++++++ .../lib/garch/glPlatformDebugContext.cpp | 10 ++--- pxr/imaging/lib/glfq/CMakeLists.txt | 8 ---- pxr/imaging/lib/glfq/selectVisual.mm | 38 ------------------- 4 files changed, 18 insertions(+), 52 deletions(-) delete mode 100644 pxr/imaging/lib/glfq/selectVisual.mm diff --git a/pxr/imaging/lib/garch/glPlatformContextDarwin.mm b/pxr/imaging/lib/garch/glPlatformContextDarwin.mm index f3789b75d8..2f4c255d41 100644 --- a/pxr/imaging/lib/garch/glPlatformContextDarwin.mm +++ b/pxr/imaging/lib/garch/glPlatformContextDarwin.mm @@ -106,3 +106,17 @@ { return GarchNSGLContextState(GarchNSGLContextState::NullState::nullstate); } + +void * +GarchSelectCoreProfileMacVisual() +{ + NSOpenGLPixelFormatAttribute attribs[10]; + int c = 0; + + attribs[c++] = NSOpenGLPFAOpenGLProfile; + attribs[c++] = NSOpenGLProfileVersion3_2Core; + attribs[c++] = NSOpenGLPFADoubleBuffer; + attribs[c++] = 0; + + return [[NSOpenGLPixelFormat alloc] initWithAttributes:attribs]; +} diff --git a/pxr/imaging/lib/garch/glPlatformDebugContext.cpp b/pxr/imaging/lib/garch/glPlatformDebugContext.cpp index c91aa5a29c..9e96b6a652 100644 --- a/pxr/imaging/lib/garch/glPlatformDebugContext.cpp +++ b/pxr/imaging/lib/garch/glPlatformDebugContext.cpp @@ -141,7 +141,7 @@ GarchGLPlatformDebugContextPrivate::MakeCurrent() glXMakeCurrent(glXGetCurrentDisplay(), glXGetCurrentDrawable(), _ctx); } -void *GlfqSelectCoreProfileMacVisual() +void *GarchSelectCoreProfileMacVisual() { return nullptr; } @@ -163,7 +163,7 @@ class GarchGLPlatformDebugContextPrivate { void MakeCurrent() {} }; -void *GlfqSelectCoreProfileMacVisual(); // extern obj-c +void *GarchSelectCoreProfileMacVisual(); // extern obj-c #endif @@ -183,7 +183,7 @@ class GarchGLPlatformDebugContextPrivate { void MakeCurrent() {} }; -void *GlfqSelectCoreProfileMacVisual() +void *GarchSelectCoreProfileMacVisual() { return nullptr; } @@ -235,9 +235,7 @@ GarchGLPlatformDebugContext::chooseMacVisual() { if (_coreProfile or GarchGLPlatformDebugContext::IsEnabledCoreProfile()) { - // XXX: move selectVisual to garch - //return GlfqSelectCoreProfileMacVisual(); - return nullptr; + return GarchSelectCoreProfileMacVisual(); } else { return nullptr; } diff --git a/pxr/imaging/lib/glfq/CMakeLists.txt b/pxr/imaging/lib/glfq/CMakeLists.txt index d14a99f4b4..5fb6fa9725 100644 --- a/pxr/imaging/lib/glfq/CMakeLists.txt +++ b/pxr/imaging/lib/glfq/CMakeLists.txt @@ -6,12 +6,6 @@ if (NOT QT4_FOUND) return() endif() -if(APPLE) - FIND_LIBRARY(COCOA_LIBRARY Cocoa) - set(COCOA_SRC selectVisual.mm) -endif() - - pxr_shared_library(glfq LIBRARIES garch @@ -26,7 +20,6 @@ pxr_shared_library(glfq ${Boost_SYSTEM_LIBRARY} ${OPENGL_gl_LIBRARY} ${GLEW_LIBRARY} - ${COCOA_LIBRARY} INCLUDE_DIRS ${Boost_INCLUDE_DIRS} @@ -37,7 +30,6 @@ pxr_shared_library(glfq CPPFILES moduleDeps.cpp - ${COCOA_SRC} PYMODULE_CPPFILES module.cpp diff --git a/pxr/imaging/lib/glfq/selectVisual.mm b/pxr/imaging/lib/glfq/selectVisual.mm deleted file mode 100644 index 541900338d..0000000000 --- a/pxr/imaging/lib/glfq/selectVisual.mm +++ /dev/null @@ -1,38 +0,0 @@ -// -// 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. -// - -#include - -void *GlfqSelectCoreProfileMacVisual() -{ - NSOpenGLPixelFormatAttribute attribs[10]; - int c = 0; - - attribs[c++] = NSOpenGLPFAOpenGLProfile; - attribs[c++] = NSOpenGLProfileVersion3_2Core; - attribs[c++] = NSOpenGLPFADoubleBuffer; - attribs[c++] = 0; - - return [[NSOpenGLPixelFormat alloc] initWithAttributes:attribs]; -} From fda1733eafffc6b2270c7096b1e342a2c2e53853 Mon Sep 17 00:00:00 2001 From: Aaron Luk Date: Fri, 26 Aug 2016 01:53:21 +0200 Subject: [PATCH 025/380] Fix OSX build by reordering includes as described in issue #28 --- pxr/usd/plugin/usdAbc/wrapAlembicTest.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pxr/usd/plugin/usdAbc/wrapAlembicTest.cpp b/pxr/usd/plugin/usdAbc/wrapAlembicTest.cpp index 1a60b5513f..a84abbf386 100644 --- a/pxr/usd/plugin/usdAbc/wrapAlembicTest.cpp +++ b/pxr/usd/plugin/usdAbc/wrapAlembicTest.cpp @@ -21,10 +21,10 @@ // KIND, either express or implied. See the Apache License for the specific // language governing permissions and limitations under the Apache License. // -#include "pxr/usd/usdAbc/alembicTest.h" - #include +#include "pxr/usd/usdAbc/alembicTest.h" + using namespace boost::python; void wrapUsdAbcAlembicTest() From b9e43df85f0b97d1d66d5034e608d23ad7dba1b5 Mon Sep 17 00:00:00 2001 From: sunyab Date: Thu, 25 Aug 2016 13:02:15 -0700 Subject: [PATCH 026/380] Don't build usdview(q) if Qt4 and PySide aren't found This allows the usdImaging component to build on systems that have Qt4 but not PySide. In such cases, usdview will just not be available. Fixes #18 (Internal change: 1646492) --- pxr/usdImaging/bin/usdview/CMakeLists.txt | 5 +++++ pxr/usdImaging/lib/usdviewq/CMakeLists.txt | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/pxr/usdImaging/bin/usdview/CMakeLists.txt b/pxr/usdImaging/bin/usdview/CMakeLists.txt index 369d733395..195a208e99 100644 --- a/pxr/usdImaging/bin/usdview/CMakeLists.txt +++ b/pxr/usdImaging/bin/usdview/CMakeLists.txt @@ -1,3 +1,8 @@ +if (NOT TARGET usdviewq) + message(WARNING "Not building usdview because of missing dependency: usdviewq") + return() +endif() + pxr_python_bins( usdview ) diff --git a/pxr/usdImaging/lib/usdviewq/CMakeLists.txt b/pxr/usdImaging/lib/usdviewq/CMakeLists.txt index b70b4616ac..c7918e255e 100644 --- a/pxr/usdImaging/lib/usdviewq/CMakeLists.txt +++ b/pxr/usdImaging/lib/usdviewq/CMakeLists.txt @@ -6,6 +6,11 @@ if (NOT QT4_FOUND) return() endif() +if (NOT PYSIDE_FOUND) + message(WARNING "Not building ${PXR_PACKAGE} because of missing dependency: PySide") + return() +endif() + pxr_shared_library(usdviewq LIBRARIES tf From a165fdca44cef91230f067761236099070818ef1 Mon Sep 17 00:00:00 2001 From: c64kernal Date: Thu, 25 Aug 2016 13:03:02 -0700 Subject: [PATCH 027/380] Remove extraneous import of sip. Fixes #22. (Internal change: 1646517) --- pxr/usdImaging/lib/usdviewq/mainWindow.py | 1 - 1 file changed, 1 deletion(-) diff --git a/pxr/usdImaging/lib/usdviewq/mainWindow.py b/pxr/usdImaging/lib/usdviewq/mainWindow.py index c8431afa6c..9c9486a880 100644 --- a/pxr/usdImaging/lib/usdviewq/mainWindow.py +++ b/pxr/usdImaging/lib/usdviewq/mainWindow.py @@ -1280,7 +1280,6 @@ def _configureRenderGraphPlugins(self): # Topology-dependent UI changes def _reloadVaryingUI(self): - import sip # We must call ReloadStage() before _clearCaches() to avoid a crash in # the case when we have reopened the stage. The problem is when the From a835c4d6b5cc3c23283f4cb26873f4f1b43907a9 Mon Sep 17 00:00:00 2001 From: c64kernal Date: Thu, 25 Aug 2016 13:03:16 -0700 Subject: [PATCH 028/380] Better fix for WorkParallelForN callback forwarding. (Internal change: 1646966) --- pxr/base/lib/work/loops.h | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/pxr/base/lib/work/loops.h b/pxr/base/lib/work/loops.h index d0aff308e5..fd310acb4f 100644 --- a/pxr/base/lib/work/loops.h +++ b/pxr/base/lib/work/loops.h @@ -72,16 +72,19 @@ WorkParallelForN(size_t n, Fn &&callback) class Work_ParallelForN_TBB { public: - // Private constructor because no one is allowed to create one of - // these objects from the outside. - Work_ParallelForN_TBB(Fn &&fn) : _fn(std::forward(fn)) { } + Work_ParallelForN_TBB(Fn &fn) : _fn(fn) { } void operator()(const tbb::blocked_range &r) const { + // Note that we std::forward _fn using Fn in order get the + // right operator(). + // We maintain the right type in this way: + // If Fn is T&, then reference collapsing gives us T& for _fn + // If Fn is T, then std::forward correctly gives us T&& for _fn std::forward(_fn)(r.begin(), r.end()); } private: - Fn &&_fn; + Fn &_fn; }; // Note that for the tbb version in the future, we will likely want to @@ -90,7 +93,7 @@ WorkParallelForN(size_t n, Fn &&callback) // parent context, so we create an isolated task group context. tbb::task_group_context ctx(tbb::task_group_context::isolated); tbb::parallel_for(tbb::blocked_range(0,n), - Work_ParallelForN_TBB(std::forward(callback)), + Work_ParallelForN_TBB(callback), ctx); } else { From 42ed723b8f80f4ecb3998468a4bbb229d288a04f Mon Sep 17 00:00:00 2001 From: spiffmon Date: Thu, 25 Aug 2016 13:03:24 -0700 Subject: [PATCH 029/380] Fix doxygen mis-classification for \file statement. (Internal change: 1647544) --- pxr/usd/lib/usdGeom/metrics.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pxr/usd/lib/usdGeom/metrics.h b/pxr/usd/lib/usdGeom/metrics.h index 0297ec5562..0cf60d9c73 100644 --- a/pxr/usd/lib/usdGeom/metrics.h +++ b/pxr/usd/lib/usdGeom/metrics.h @@ -27,7 +27,7 @@ #include "pxr/base/tf/token.h" #include "pxr/usd/usd/common.h" -/// \file usd/metrics.h +/// \file usdGeom/metrics.h /// /// Schema and utilities for encoding various spatial and geometric metrics of /// a UsdStage and its contents. From ed291c7ff5cecf59b52f6b83991ad32226db8dd3 Mon Sep 17 00:00:00 2001 From: mattyjams Date: Thu, 25 Aug 2016 13:03:32 -0700 Subject: [PATCH 030/380] revert default un-authored color set value to (1.0, 1.0, 1.0, 1.0) to preserve old behavior (Internal change: 1647645) --- third_party/maya/lib/usdMaya/MayaMeshWriter.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/third_party/maya/lib/usdMaya/MayaMeshWriter.cpp b/third_party/maya/lib/usdMaya/MayaMeshWriter.cpp index b5a503b1eb..8817f91c08 100644 --- a/third_party/maya/lib/usdMaya/MayaMeshWriter.cpp +++ b/third_party/maya/lib/usdMaya/MayaMeshWriter.cpp @@ -44,8 +44,8 @@ TF_DEFINE_PRIVATE_TOKENS(_tokens, const GfVec3f MayaMeshWriter::_ShaderDefaultRGB = GfVec3f(0.5); const float MayaMeshWriter::_ShaderDefaultAlpha = 0.0; -const GfVec3f MayaMeshWriter::_ColorSetDefaultRGB = GfVec3f(0.0); -const float MayaMeshWriter::_ColorSetDefaultAlpha = 0.0; +const GfVec3f MayaMeshWriter::_ColorSetDefaultRGB = GfVec3f(1.0); +const float MayaMeshWriter::_ColorSetDefaultAlpha = 1.0; MayaMeshWriter::MayaMeshWriter( From fcd772dfa6593ea81e30d8cb27201a89aded8ce2 Mon Sep 17 00:00:00 2001 From: sunyab Date: Thu, 25 Aug 2016 15:45:17 -0700 Subject: [PATCH 031/380] Fixes for FindPySide.cmake module Fixes incorrect syntax for checking the existence of the pyside-uic binary, which caused the PYSIDE_FOUND flag to not be set properly. Also add a status message indicating if PySide was found at cmake time. (Internal change: 1647848) --- cmake/modules/FindPySide.cmake | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/cmake/modules/FindPySide.cmake b/cmake/modules/FindPySide.cmake index b5722fb44f..045fc72873 100644 --- a/cmake/modules/FindPySide.cmake +++ b/cmake/modules/FindPySide.cmake @@ -37,6 +37,7 @@ execute_process( pySideImportResult ) -if (pySideImportResult EQUAL 0 AND EXISTS(${PYSIDEUICBINARY})) +if (pySideImportResult EQUAL 0 AND EXISTS ${PYSIDEUICBINARY}) + message(STATUS "Found PySide: ${PYSIDEUICBINARY}") set(PYSIDE_FOUND True) endif() From 17b2e6083aa4800b5f9c9145c4388da52c9900f4 Mon Sep 17 00:00:00 2001 From: Aaron Luk Date: Fri, 26 Aug 2016 21:34:18 +0200 Subject: [PATCH 032/380] Fix OPENSUBDIV defines for Hd. --- pxr/imaging/lib/hd/CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pxr/imaging/lib/hd/CMakeLists.txt b/pxr/imaging/lib/hd/CMakeLists.txt index 6defd6ebb1..e4015da1e1 100644 --- a/pxr/imaging/lib/hd/CMakeLists.txt +++ b/pxr/imaging/lib/hd/CMakeLists.txt @@ -7,10 +7,10 @@ if (QT4_FOUND) endif() if (OPENSUBDIV_HAS_GLSL_TRANSFORM_FEEDBACK) - _add_define(OPENSUBDIV_HAS_GLSL_TRANSFORM_FEEDBACK) + add_definitions(-DOPENSUBDIV_HAS_GLSL_TRANSFORM_FEEDBACK) endif() if (OPENSUBDIV_HAS_GLSL_COMPUTE) - _add_define(OPENSUBDIV_HAS_GLSL_COMPUTE) + add_definitions(-DOPENSUBDIV_HAS_GLSL_COMPUTE) endif() pxr_shared_library(hd From d9f76c8c26d92e74b686721e5fe67422a5dc5674 Mon Sep 17 00:00:00 2001 From: gitamohr Date: Fri, 26 Aug 2016 14:45:16 -0700 Subject: [PATCH 033/380] usd: Fix doc typo for UsdStage::LoadAndUnload(). (Internal change: 1648091) --- pxr/usd/lib/usd/stage.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pxr/usd/lib/usd/stage.h b/pxr/usd/lib/usd/stage.h index 2477bbe6e0..a6aad2ee57 100644 --- a/pxr/usd/lib/usd/stage.h +++ b/pxr/usd/lib/usd/stage.h @@ -425,7 +425,7 @@ class UsdStage : public TfRefBase, public TfWeakBase { /// unload set were processed first followed by the load set. /// /// This is equivalent to calling UsdStage::Unload for each item in the - /// loadSet followed by UsdStage::Load for each item in the unloadSet, + /// unloadSet followed by UsdStage::Load for each item in the loadSet, /// however this method is more efficient as all operations are committed /// in a single batch. /// From 58d254c3380fcad18debe572c1d1884fa7b4828e Mon Sep 17 00:00:00 2001 From: gitamohr Date: Fri, 26 Aug 2016 14:45:22 -0700 Subject: [PATCH 034/380] usd: Add a forward declaration to appease certain MSVC versions. Fixes #21 (Internal change: 1648093) --- pxr/usd/lib/usd/crateFile.h | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/pxr/usd/lib/usd/crateFile.h b/pxr/usd/lib/usd/crateFile.h index 9f5a7d213e..c66b9887b6 100644 --- a/pxr/usd/lib/usd/crateFile.h +++ b/pxr/usd/lib/usd/crateFile.h @@ -61,6 +61,9 @@ using std::unordered_map; using std::tuple; using std::vector; +// Forward declaration required here for certain MSVC versions. +struct _PathItemHeader; + // Tag indicating trivially copyable types, hack since gcc doesn't yet implement // is_trivially_copyable correctly. struct _BitwiseReadWrite {}; @@ -500,7 +503,7 @@ class CrateFile static _BootStrap _ReadBootStrap(ByteStream src, int64_t fileSize); template - _TableOfContents _ReadTOC(Reader src, struct _BootStrap const &b) const; + _TableOfContents _ReadTOC(Reader src, _BootStrap const &b) const; template void _ReadFieldSets(Reader src); template void _ReadFields(Reader src); @@ -511,7 +514,7 @@ class CrateFile template void _ReadPathsRecursively( Reader src, const SdfPath &parentPath, - const struct _PathItemHeader &h, + const _PathItemHeader &h, WorkArenaDispatcher &dispatcher); void _ReadRawBytes(int64_t start, int64_t size, char *buf) const; From a72d2ee369831c9977edafe013975e6493c366db Mon Sep 17 00:00:00 2001 From: unhyperbolic Date: Mon, 29 Aug 2016 21:25:00 -0700 Subject: [PATCH 035/380] Adding GfFrustum::ComputeCornersAtDistance which will be useful in writing camera guides such as focus plane. (Internal change: 1650399) --- pxr/base/lib/gf/frustum.cpp | 32 ++++++++++++++++++++++++++++++++ pxr/base/lib/gf/frustum.h | 11 +++++++++++ pxr/base/lib/gf/wrapFrustum.cpp | 3 +++ 3 files changed, 46 insertions(+) diff --git a/pxr/base/lib/gf/frustum.cpp b/pxr/base/lib/gf/frustum.cpp index 9a678f3fa0..550a51c278 100644 --- a/pxr/base/lib/gf/frustum.cpp +++ b/pxr/base/lib/gf/frustum.cpp @@ -653,6 +653,38 @@ GfFrustum::ComputeCorners() const return corners; } +vector +GfFrustum::ComputeCornersAtDistance(double d) const +{ + const GfVec2d &winMin = _window.GetMin(); + const GfVec2d &winMax = _window.GetMax(); + + vector corners; + corners.reserve(4); + + if (_projectionType == Perspective) { + // Similar to ComputeCorners + corners.push_back(GfVec3d(d * winMin[0], d * winMin[1], -d)); + corners.push_back(GfVec3d(d * winMax[0], d * winMin[1], -d)); + corners.push_back(GfVec3d(d * winMin[0], d * winMax[1], -d)); + corners.push_back(GfVec3d(d * winMax[0], d * winMax[1], -d)); + } + else { + corners.push_back(GfVec3d(winMin[0], winMin[1], -d)); + corners.push_back(GfVec3d(winMax[0], winMin[1], -d)); + corners.push_back(GfVec3d(winMin[0], winMax[1], -d)); + corners.push_back(GfVec3d(winMax[0], winMax[1], -d)); + } + + // Each corner is then transformed into world space by the inverse + // of the view matrix. + const GfMatrix4d m = ComputeViewInverse(); + for (int i = 0; i < 4; i++) + corners[i] = m.Transform(corners[i]); + + return corners; +} + GfFrustum GfFrustum::ComputeNarrowedFrustum(const GfVec2d &point, const GfVec2d &halfSize) const diff --git a/pxr/base/lib/gf/frustum.h b/pxr/base/lib/gf/frustum.h index 3e44bc89ea..4f61645819 100644 --- a/pxr/base/lib/gf/frustum.h +++ b/pxr/base/lib/gf/frustum.h @@ -426,6 +426,17 @@ class GfFrustum { /// \li Right top far std::vector ComputeCorners() const; + /// Returns the world-space corners of the intersection of the frustum + /// with a plane parallel to the near/far plane at distance d from the + /// apex, ordered as: + /// \li Left bottom + /// \li Right bottom + /// \li Left top + /// \li Right top + /// In particular, it gives the partial result of ComputeCorners when given + /// near or far distance. + std::vector ComputeCornersAtDistance(double d) const; + /// Returns a frustum that is a narrowed-down version of this frustum, /// such that the frustum rectangle on the near plane encloses \p point /// with at most \p halfSize[0] distance on the left and right and at most diff --git a/pxr/base/lib/gf/wrapFrustum.cpp b/pxr/base/lib/gf/wrapFrustum.cpp index 3ab6691773..082423a0b2 100644 --- a/pxr/base/lib/gf/wrapFrustum.cpp +++ b/pxr/base/lib/gf/wrapFrustum.cpp @@ -206,6 +206,9 @@ void wrapFrustum() .def("ComputeCorners", &This::ComputeCorners, return_value_policy()) + .def("ComputeCornersAtDistance", &This::ComputeCornersAtDistance, + return_value_policy()) + .def("ComputeNarrowedFrustum", (GfFrustum (This::*)(const GfVec2d &, const GfVec2d &) const) &This::ComputeNarrowedFrustum) From 7cdaff58a00d70bc49c440a4e3cc45b211841d39 Mon Sep 17 00:00:00 2001 From: takahito-tejima Date: Mon, 29 Aug 2016 21:25:19 -0700 Subject: [PATCH 036/380] [Hd] fix excessive batch rebuilding when a light collection gets dirty. suppress marking collection dirty if the collection is not actually being changed. (Internal change: 1650406) --- pxr/imaging/lib/hd/changeTracker.cpp | 6 ++++ pxr/imaging/lib/hd/light.cpp | 10 ++++-- pxr/imaging/lib/hd/unitTestDelegate.cpp | 48 +++++++++++++++++++++++++ pxr/imaging/lib/hd/unitTestDelegate.h | 18 ++++++++++ 4 files changed, 79 insertions(+), 3 deletions(-) diff --git a/pxr/imaging/lib/hd/changeTracker.cpp b/pxr/imaging/lib/hd/changeTracker.cpp index 68fbe486c5..f183d183cd 100644 --- a/pxr/imaging/lib/hd/changeTracker.cpp +++ b/pxr/imaging/lib/hd/changeTracker.cpp @@ -794,6 +794,8 @@ HdChangeTracker::GetRprimDirtyBits(SdfPath const& id) const void HdChangeTracker::AddCollection(TfToken const& collectionName) { + HD_TRACE_FUNCTION(); + _CollectionStateMap::iterator it = _collectionState.find(collectionName); // if it already exists, just return. if (it != _collectionState.end()) { @@ -805,6 +807,8 @@ HdChangeTracker::AddCollection(TfToken const& collectionName) void HdChangeTracker::MarkCollectionDirty(TfToken const& collectionName) { + HD_TRACE_FUNCTION(); + _CollectionStateMap::iterator it = _collectionState.find(collectionName); if (not TF_VERIFY(it != _collectionState.end(), "Collection %s not found\n", collectionName.GetText())) { @@ -823,6 +827,8 @@ HdChangeTracker::MarkCollectionDirty(TfToken const& collectionName) void HdChangeTracker::MarkAllCollectionsDirty() { + HD_TRACE_FUNCTION(); + ++_indexVersion; ++_varyingStateVersion; diff --git a/pxr/imaging/lib/hd/light.cpp b/pxr/imaging/lib/hd/light.cpp index 9da4bad574..0bb5901047 100644 --- a/pxr/imaging/lib/hd/light.cpp +++ b/pxr/imaging/lib/hd/light.cpp @@ -94,10 +94,14 @@ HdLight::Sync() // Optional if (vtShadowCollection.IsHolding()) { - _shadowCollection = - vtShadowCollection.UncheckedGet(); + HdRprimCollection newCollection = + vtShadowCollection.UncheckedGet(); + + if (_shadowCollection != newCollection) { + _shadowCollection = newCollection; + changeTracker.MarkCollectionDirty(_shadowCollection.GetName()); + } - changeTracker.MarkCollectionDirty(_shadowCollection.GetName()); } else { _shadowCollection = HdRprimCollection(); } diff --git a/pxr/imaging/lib/hd/unitTestDelegate.cpp b/pxr/imaging/lib/hd/unitTestDelegate.cpp index 39d1479ff5..5e722563c4 100644 --- a/pxr/imaging/lib/hd/unitTestDelegate.cpp +++ b/pxr/imaging/lib/hd/unitTestDelegate.cpp @@ -24,6 +24,8 @@ #include "pxr/imaging/hd/unitTestDelegate.h" #include "pxr/imaging/hd/basisCurves.h" +#include "pxr/imaging/hd/camera.h" +#include "pxr/imaging/hd/light.h" #include "pxr/imaging/hd/mesh.h" #include "pxr/imaging/hd/meshTopology.h" #include "pxr/imaging/hd/points.h" @@ -35,6 +37,7 @@ #include "pxr/base/gf/matrix4f.h" #include "pxr/base/gf/rotation.h" +#include "pxr/imaging/glf/simpleLight.h" #include "pxr/imaging/glf/textureRegistry.h" #include "pxr/imaging/glf/ptexTexture.h" @@ -256,6 +259,28 @@ Hd_UnitTestDelegate::AddTexture(SdfPath const& id, _textures[id] = _Texture(texture); } +void +Hd_UnitTestDelegate::AddCamera(SdfPath const &id) +{ + HdRenderIndex& index = GetRenderIndex(); + index.InsertCamera(this, id); + _cameras[id].params[HdShaderTokens->worldToViewMatrix] + = VtValue(GfMatrix4d(1)); + _cameras[id].params[HdShaderTokens->projectionMatrix] + = VtValue(GfMatrix4d(1)); +} + +void +Hd_UnitTestDelegate::AddLight(SdfPath const &id) +{ + HdRenderIndex& index = GetRenderIndex(); + index.InsertLight(this, id); + _lights[id].params[HdTokens->lightParams] + = VtValue(GlfSimpleLight()); + _lights[id].params[HdTokens->lightShadowCollection] + = VtValue(HdRprimCollection(HdTokens->geometry, HdTokens->hull)); +} + void Hd_UnitTestDelegate::HideRprim(SdfPath const& id) { @@ -383,6 +408,22 @@ Hd_UnitTestDelegate::UpdateInstancerPrototypes(float time) } } +void +Hd_UnitTestDelegate::UpdateCamera(SdfPath const &id, + TfToken const &key, + VtValue value) +{ + _cameras[id].params[key] = value; +} + +void +Hd_UnitTestDelegate::UpdateLight(SdfPath const &id, + TfToken const &key, + VtValue value) +{ + _lights[id].params[key] = value; +} + /*virtual*/ bool Hd_UnitTestDelegate::IsInCollection(SdfPath const& id, @@ -642,6 +683,13 @@ Hd_UnitTestDelegate::Get(SdfPath const& id, TfToken const& key) { HD_TRACE_FUNCTION(); + // camera and light + if (_cameras.find(id) != _cameras.end()) { + return _cameras[id].params[key]; + } else if (_lights.find(id) != _lights.end()) { + return _lights[id].params[key]; + } + VtValue value; if (key == HdTokens->points) { // We could be a mesh or a cuve diff --git a/pxr/imaging/lib/hd/unitTestDelegate.h b/pxr/imaging/lib/hd/unitTestDelegate.h index 11078b7ea5..36ed61ed41 100644 --- a/pxr/imaging/lib/hd/unitTestDelegate.h +++ b/pxr/imaging/lib/hd/unitTestDelegate.h @@ -176,6 +176,12 @@ class Hd_UnitTestDelegate : public HdSceneDelegate { void AddTexture(SdfPath const& id, GlfTextureRefPtr const& texture); + /// Camera + void AddCamera(SdfPath const &id); + + /// Light + void AddLight(SdfPath const &id); + /// Remove a prim void Remove(SdfPath const &id); @@ -202,6 +208,9 @@ class Hd_UnitTestDelegate : public HdSceneDelegate { void UpdateInstancerPrimVars(float time); void UpdateInstancerPrototypes(float time); + void UpdateCamera(SdfPath const &id, TfToken const &key, VtValue value); + void UpdateLight(SdfPath const &id, TfToken const &key, VtValue value); + void BindSurfaceShader(SdfPath const &rprimId, SdfPath const &shaderId) { _surfaceShaderBindings[rprimId] = shaderId; @@ -361,12 +370,21 @@ class Hd_UnitTestDelegate : public HdSceneDelegate { } GlfTextureRefPtr texture; }; + struct _Camera { + VtDictionary params; + }; + struct _Light { + VtDictionary params; + }; + std::map _meshes; std::map _curves; std::map _points; std::map _instancers; std::map _surfaceShaders; std::map _textures; + std::map _cameras; + std::map _lights; TfHashSet _hiddenRprims; typedef std::map SdfPathMap; From 06f86c99eb8ae0fba4587e24c5d77089391369ee Mon Sep 17 00:00:00 2001 From: takahito-tejima Date: Mon, 29 Aug 2016 21:25:39 -0700 Subject: [PATCH 037/380] [Hd] fix portability issue of GLSL codeGen replacing default function parameter with function overload. (Internal change: 1650472) --- pxr/imaging/lib/hd/codeGen.cpp | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/pxr/imaging/lib/hd/codeGen.cpp b/pxr/imaging/lib/hd/codeGen.cpp index 9524a655ae..100a5e240f 100644 --- a/pxr/imaging/lib/hd/codeGen.cpp +++ b/pxr/imaging/lib/hd/codeGen.cpp @@ -1818,22 +1818,25 @@ Hd_CodeGen::_GenerateShaderParameters() << " return sampler2d_" << it->second.name << ";" << "}\n"; } + // vec4 HdGet_name(vec2 coord) { return texture(sampler2d_name, coord).xyz; } accessors << it->second.dataType << " HdGet_" << it->second.name - << "(vec2 coord = "; + << "(vec2 coord) { return texture(sampler2d_" + << it->second.name << ", coord)" << swizzle << ";}\n"; + // vec4 HdGet_name() { return HdGet_name(HdGet_st().xy); } + accessors + << it->second.dataType + << " HdGet_" << it->second.name + << "() { return HdGet_" << it->second.name << "("; if (not it->second.inPrimVars.empty()) { accessors - << " HdGet_" << it->second.inPrimVars[0] << "().xy"; + << "HdGet_" << it->second.inPrimVars[0] << "().xy"; } else { accessors - << " vec2(0.0, 0.0)"; + << "vec2(0.0, 0.0)"; } - accessors - << ") {\n" - << " return texture(sampler2d_" << it->second.name - << ", coord)" << swizzle << ";\n" // XXX: should be inprimvars - << "}\n"; + accessors << "); }\n"; } else if (bindingType == HdBinding::BINDLESS_TEXTURE_PTEX_TEXEL) { accessors << it->second.dataType From 44dd362714d50e00e61929ca334127642d972f40 Mon Sep 17 00:00:00 2001 From: florianz Date: Mon, 29 Aug 2016 21:26:08 -0700 Subject: [PATCH 038/380] Make sure that the environment variable PXR_WORK_THREAD_LIMIT takes precedence over setting the thread limit via any of the libWork API calls. (Internal change: 1650475) --- pxr/base/lib/work/testenv/testWorkLoops.cpp | 2 +- .../lib/work/testenv/testWorkThreadLimits.cpp | 100 ++++++++++++------ pxr/base/lib/work/threadLimits.cpp | 92 +++++++++++----- pxr/base/lib/work/threadLimits.h | 32 +++--- pxr/base/lib/work/wrapThreadLimits.cpp | 2 +- 5 files changed, 153 insertions(+), 75 deletions(-) diff --git a/pxr/base/lib/work/testenv/testWorkLoops.cpp b/pxr/base/lib/work/testenv/testWorkLoops.cpp index b55c90394d..58c787e099 100644 --- a/pxr/base/lib/work/testenv/testWorkLoops.cpp +++ b/pxr/base/lib/work/testenv/testWorkLoops.cpp @@ -170,7 +170,7 @@ main(int argc, char **argv) WorkSetMaximumConcurrencyLimit(); std::cout << "Initialized with " << - WorkGetMaximumConcurrencyLimit() << " cores..." << std::endl; + WorkGetPhysicalConcurrencyLimit() << " cores..." << std::endl; double tbbSeconds = _DoTBBTest(not perfMode, arraySize, numIterations); diff --git a/pxr/base/lib/work/testenv/testWorkThreadLimits.cpp b/pxr/base/lib/work/testenv/testWorkThreadLimits.cpp index 3c47d968b8..9f6d73dcda 100644 --- a/pxr/base/lib/work/testenv/testWorkThreadLimits.cpp +++ b/pxr/base/lib/work/testenv/testWorkThreadLimits.cpp @@ -53,11 +53,23 @@ _CountThreads(size_t begin, size_t end) _uniqueThreads->insert(pthread_self()); } +static size_t +_ExpectedLimit(const size_t envVal, const size_t n) +{ + // If envVal is non-zero, it wins over n! + return envVal ? envVal : n; +} + static void -_TestThreadLimit(size_t n) +_TestThreadLimit(const size_t envVal, const size_t n) { + const size_t expectedN = _ExpectedLimit(envVal, n); + if (expectedN != n) { + std::cout << " env setting overrides n = " << n << "\n"; + } + const size_t numSamples = 1000000; - std::cout << " maximum " << n << " threads\n"; + std::cout << " expecting maximum " << expectedN << " threads\n"; _uniqueThreads->clear(); @@ -65,56 +77,55 @@ _TestThreadLimit(size_t n) std::cout << " TBB used " << _uniqueThreads->size() << '\n'; - if (_uniqueThreads->size() > n) { + if (_uniqueThreads->size() > expectedN) { TF_FATAL_ERROR("TBB expected less than or equal to %zu threads, got %zu", - n, _uniqueThreads->size()); + expectedN, _uniqueThreads->size()); } } static void -_TestArguments() +_TestArguments(const size_t envVal) { - size_t numCores = WorkGetMaximumConcurrencyLimit(); + // Note that if envVal is set (i.e. non-zero) it will always win over the + // value supplied through the API calls. - // These tests assume we have at least 4 cores. - TF_AXIOM(numCores >= 4); + // Set to maximum concurrency, which should remain within envVal. + const size_t numCores = WorkGetPhysicalConcurrencyLimit(); + WorkSetConcurrencyLimitArgument(numCores); + TF_AXIOM(WorkGetConcurrencyLimit() == _ExpectedLimit(envVal, numCores)); - // n = 0, means full threading + // n = 0, means "no change" WorkSetConcurrencyLimitArgument(0); - TF_AXIOM(WorkGetConcurrencyLimit() == numCores); + TF_AXIOM(WorkGetConcurrencyLimit() == _ExpectedLimit(envVal, numCores)); // n = 1 means no threading WorkSetConcurrencyLimitArgument(1); - TF_AXIOM(WorkGetConcurrencyLimit() == 1); + TF_AXIOM(WorkGetConcurrencyLimit() == _ExpectedLimit(envVal, 1)); // n = 3 means 3 WorkSetConcurrencyLimitArgument(3); - TF_AXIOM(WorkGetConcurrencyLimit() == 3); - - // n = numCores means numCores - WorkSetConcurrencyLimitArgument(numCores); - TF_AXIOM(WorkGetConcurrencyLimit() == numCores); + TF_AXIOM(WorkGetConcurrencyLimit() == _ExpectedLimit(envVal, 3)); - // n = 1000 means max + // n = 1000 means 1000 WorkSetConcurrencyLimitArgument(1000); - TF_AXIOM(WorkGetConcurrencyLimit() == numCores); + TF_AXIOM(WorkGetConcurrencyLimit() == _ExpectedLimit(envVal, 1000)); // n = -1 means numCores - 1 WorkSetConcurrencyLimitArgument(-1); - TF_AXIOM(WorkGetConcurrencyLimit() == numCores-1); + TF_AXIOM(WorkGetConcurrencyLimit() == _ExpectedLimit(envVal, numCores-1)); // n = -3 means numCores - 3 WorkSetConcurrencyLimitArgument(-3); - TF_AXIOM(WorkGetConcurrencyLimit() == numCores-3); + TF_AXIOM(WorkGetConcurrencyLimit() == _ExpectedLimit(envVal, numCores-3)); // n = -numCores means 1 (no threading) WorkSetConcurrencyLimitArgument(-numCores); - TF_AXIOM(WorkGetConcurrencyLimit() == 1); + TF_AXIOM(WorkGetConcurrencyLimit() == _ExpectedLimit(envVal, 1)); // n = -numCores*10 means 1 (no threading) WorkSetConcurrencyLimitArgument(-numCores*10); - TF_AXIOM(WorkGetConcurrencyLimit() == 1); + TF_AXIOM(WorkGetConcurrencyLimit() == _ExpectedLimit(envVal, 1)); } struct _RawTBBCounter @@ -128,8 +139,8 @@ int main(int argc, char **argv) { // Read the env setting used to limit threading - size_t limit = TfGetEnvSetting(PXR_WORK_THREAD_LIMIT); - std::cout << "PXR_WORK_THREAD_LIMIT = " << limit << '\n'; + const size_t envVal = TfGetEnvSetting(PXR_WORK_THREAD_LIMIT); + std::cout << "PXR_WORK_THREAD_LIMIT = " << envVal << '\n'; // Test to make sure that a call to tbb that happens before any of the // libWork API is touched is unrestricted. We need to do this for now to @@ -141,7 +152,7 @@ main(int argc, char **argv) // seem to be a way to limit it again. That's why we test this // functionality by itself. if ((argc == 2) and (strcmp(argv[1], "--rawtbb") == 0)) { - TF_AXIOM(WorkGetMaximumConcurrencyLimit() >= 4); + TF_AXIOM(WorkGetPhysicalConcurrencyLimit() >= 4); std::cout << "Testing that libWork automatically limits tbb " "threading when PXR_WORK_THREAD_LIMIT is set...\n"; @@ -151,16 +162,16 @@ main(int argc, char **argv) std::cout << " default TBB used " << _uniqueThreads->size() << " threads\n"; - if (limit == 0) { + if (envVal == 0) { if (_uniqueThreads->size() < 2) { TF_FATAL_ERROR("tbb only used %zu threads when it should be " "unlimited\n", _uniqueThreads->size()); } } - else if (_uniqueThreads->size() > limit) { + else if (_uniqueThreads->size() > envVal) { TF_FATAL_ERROR("tbb used %zu threads, which is greater than " "PXR_WORK_THREAD_LIMIT=%zu.", _uniqueThreads->size(), - limit); + envVal); } // Stop the test, now that we've initialized tbb, there's no going @@ -169,17 +180,18 @@ main(int argc, char **argv) } // 0 means all cores. + size_t limit = envVal; if (limit == 0) { WorkSetMaximumConcurrencyLimit(); limit = WorkGetConcurrencyLimit(); } - TF_AXIOM(limit > 0 and limit <= WorkGetMaximumConcurrencyLimit()); + TF_AXIOM(limit > 0 and limit <= WorkGetPhysicalConcurrencyLimit()); // Make sure that we get the default thread limit std::cout << "Testing that the thread limit defaults to " " PXR_WORK_THREAD_LIMIT by default...\n"; - _TestThreadLimit(limit); + _TestThreadLimit(envVal, limit); // Now that we've invoked libWork, make sure that raw TBB API also defaults // to PXR_WORK_THREAD_LIMIT. @@ -197,20 +209,40 @@ main(int argc, char **argv) // Test with full concurrency. std::cout << "Testing full concurrency...\n"; WorkSetMaximumConcurrencyLimit(); - _TestThreadLimit(WorkGetMaximumConcurrencyLimit()); + TF_AXIOM(WorkGetConcurrencyLimit() == + _ExpectedLimit(envVal, WorkGetPhysicalConcurrencyLimit())); + _TestThreadLimit(envVal, WorkGetPhysicalConcurrencyLimit()); // Test with no concurrency. std::cout << "Testing turning off concurrency...\n"; WorkSetConcurrencyLimit(1); - _TestThreadLimit(1); + TF_AXIOM(WorkGetConcurrencyLimit() == + _ExpectedLimit(envVal, 1)); + _TestThreadLimit(envVal, 1); + + // Test with 2 threads. + std::cout << "Testing with 2 threads...\n"; + WorkSetConcurrencyLimit(2); + TF_AXIOM(WorkGetConcurrencyLimit() == + _ExpectedLimit(envVal, 2)); + _TestThreadLimit(envVal, 2); // Test with 4 threads. std::cout << "Testing with 4 threads...\n"; WorkSetConcurrencyLimit(4); - _TestThreadLimit(4); + TF_AXIOM(WorkGetConcurrencyLimit() == + _ExpectedLimit(envVal, 4)); + _TestThreadLimit(envVal, 4); + + // Test with 1000 threads. + std::cout << "Testing with 1000 threads...\n"; + WorkSetConcurrencyLimit(1000); + TF_AXIOM(WorkGetConcurrencyLimit() == + _ExpectedLimit(envVal, 1000)); + _TestThreadLimit(envVal, WorkGetPhysicalConcurrencyLimit()); // Test argument parsing std::cout << "Testing argument parsing...\n"; - _TestArguments(); + _TestArguments(envVal); return 0; } diff --git a/pxr/base/lib/work/threadLimits.cpp b/pxr/base/lib/work/threadLimits.cpp index 9d40438833..7be2039aad 100644 --- a/pxr/base/lib/work/threadLimits.cpp +++ b/pxr/base/lib/work/threadLimits.cpp @@ -35,15 +35,22 @@ // The environment variable used to limit the number of threads the application // may spawn: -// 0 - maximum concurrency +// 0 - no change, i.e. defaults to maximum physical concurrency // 1 - single-threaded mode -// positive n - limit to n threads (clamped to the number of machine cores) +// positive n - limit to n threads // negative n - limit to all but n machine cores (minimum 1). // +// Note that the environment variable value always wins over any value passed to +// the API calls below. If PXR_WORK_THREAD_LIMIT is set to a non-zero value, the +// concurrency limit cannot be changed at runtime. +// TF_DEFINE_ENV_SETTING( PXR_WORK_THREAD_LIMIT, 0, "Limits the number of threads the application may spawn. 0 (default) " - "allows for maximum concurrency."); + "allows for maximum concurrency as determined by the number of physical " + "cores, or the process's affinity mask, whichever is smaller. Note that " + "the environment variable (if set to a non-zero value) will override any " + "value passed to Work thread-limiting API calls."); // This is Work's notion of the currently requested thread limit. Due to TBB's // behavior, the first client to create a tbb::task_scheduler_init will @@ -58,7 +65,7 @@ static tbb::atomic _threadLimit; static tbb::task_scheduler_init *_tbbTaskSchedInit; unsigned -WorkGetMaximumConcurrencyLimit() +WorkGetPhysicalConcurrencyLimit() { // Use TBB here, since it pays attention to the affinity mask on Linux and // Windows. @@ -69,34 +76,53 @@ WorkGetMaximumConcurrencyLimit() static unsigned Work_NormalizeThreadCount(const int n) { - // Zero means use all physical cores available. - if (n == 0) - return WorkGetMaximumConcurrencyLimit(); - - // One means use exactly one. - if (n == 1) - return n; - - // Clamp positive integers to the total number of available cores. - if (n > 1) - return std::min(n, WorkGetMaximumConcurrencyLimit()); - + // Zero means "no change", and n >= 1 means exactly n threads, so simply + // pass those values through unchanged. // For negative integers, subtract the absolute value from the total number // of available cores (denoting all but n cores). If n == number of cores, // clamp to 1 to set single-threaded mode. - return std::max(1, n + WorkGetMaximumConcurrencyLimit()); + return n >= 0 ? n : std::max(1, n + WorkGetPhysicalConcurrencyLimit()); +} + +// Returns the normalized thread limit value from the environment setting. Note +// that 0 means "no change", i.e. the environment setting does not apply. +static unsigned +Work_GetConcurrencyLimitSetting() +{ + return Work_NormalizeThreadCount(TfGetEnvSetting(PXR_WORK_THREAD_LIMIT)); +} + +// Overrides weakValue with strongValue if strongValue is non-zero, and returns +// the resulting thread limit. +static unsigned +Work_OverrideConcurrencyLimit(unsigned weakValue, unsigned strongValue) +{ + // If the new limit is 0, i.e. "no change", simply pass the weakValue + // through unchanged. Otherwise, the new value wins. + return strongValue ? strongValue : weakValue; } static void Work_InitializeThreading() { - // Threading is initialized with the value from the environment - // setting. The setting defaults to 0, i.e. maximum concurrency. - int settingVal = TfGetEnvSetting(PXR_WORK_THREAD_LIMIT); - _threadLimit = Work_NormalizeThreadCount(settingVal); - + // Get the thread limit from the environment setting. Note that this value + // can be 0, i.e. the environment setting does not apply. + const unsigned settingVal = Work_GetConcurrencyLimitSetting(); + + // Threading is initialized with maximum physical concurrency. + const unsigned physicalLimit = WorkGetPhysicalConcurrencyLimit(); + + // To assign the thread limit, override the initial limit with the + // environment setting. The environment setting always wins over the initial + // limit, unless it has been set to 0 (default). Semantically, 0 means + // "no change". + _threadLimit = Work_OverrideConcurrencyLimit(physicalLimit, settingVal); + // Only eagerly grab TBB if the PXR_WORK_THREAD_LIMIT setting was set to - // some non-zero value. + // some non-zero value. Otherwise, the scheduler will be default initialized + // with maximum physical concurrency, or will be left untouched if + // previously initialized by the hosting environment (e.g. if we are running + // as a plugin to another application.) if (settingVal) _tbbTaskSchedInit = new tbb::task_scheduler_init(_threadLimit); } @@ -105,8 +131,22 @@ static int _forceInitialization = (Work_InitializeThreading(), 0); void WorkSetConcurrencyLimit(unsigned n) { - // sanity - _threadLimit = std::max(1, n); + // We only assign a new concurrency limit if n is non-zero, since 0 means + // "no change". Note that we need to re-initialize the TBB + // task_scheduler_init instance in either case, because if the client + // explicitly requests a concurrency limit through this library, we need to + // attempt to take control of the TBB scheduler if we can, i.e. if the host + // environment has not already done so. + if (n) { + // Get the thread limit from the environment setting. Note this value + // may be 0 (default). + const unsigned settingVal = Work_GetConcurrencyLimitSetting(); + + // Override n with the environment setting. This will make sure that the + // setting always wins over the specified value n, but only if the + // setting has been set to a non-zero value. + _threadLimit = Work_OverrideConcurrencyLimit(n, settingVal); + } // Note that we need to do some performance testing and decide if it's // better here to simply delete the task_scheduler_init object instead @@ -128,7 +168,7 @@ WorkSetConcurrencyLimit(unsigned n) void WorkSetMaximumConcurrencyLimit() { - WorkSetConcurrencyLimit(WorkGetMaximumConcurrencyLimit()); + WorkSetConcurrencyLimit(WorkGetPhysicalConcurrencyLimit()); } void diff --git a/pxr/base/lib/work/threadLimits.h b/pxr/base/lib/work/threadLimits.h index 4484c12314..12fd56ee9e 100644 --- a/pxr/base/lib/work/threadLimits.h +++ b/pxr/base/lib/work/threadLimits.h @@ -29,11 +29,13 @@ /// Return the current concurrency limit, always >= 1. /// /// The initial value is determined by the PXR_WORK_THREAD_LIMIT env setting, -/// which defaults to WorkGetMaximumConcurrencyLimit(). +/// which defaults to WorkGetPhysicalConcurrencyLimit(). If the env setting +/// has been explicitly set to a non-zero value, it will always override any +/// concurrency limit set via the API calls below. /// /// Note that this can return a value larger than -/// WorkGetMaximumConcurrencyLimit() if WorkSetConcurrencyLimit() was called -/// with such a value. +/// WorkGetPhysicalConcurrencyLimit() if WorkSetConcurrencyLimit() was called +/// with such a value, or if PXR_WORK_THREAD_LIMIT was set with such a value. /// unsigned WorkGetConcurrencyLimit(); @@ -41,11 +43,13 @@ unsigned WorkGetConcurrencyLimit(); /// This is either the number of physical cores on the machine or the number of /// cores specified by the process's affinity mask, whichever is smaller. /// -unsigned WorkGetMaximumConcurrencyLimit(); +unsigned WorkGetPhysicalConcurrencyLimit(); -/// Set the concurrencty limit to max(1, \p n). +/// Set the concurrency limit to \p n, if \p n is a non-zero value. /// -/// Note, calling ths function with n > WorkGetMaximumConcurrencyLimit() may +/// If \p n is zero, then do not change the current concurrency limit. +/// +/// Note, calling this function with n > WorkGetPhysicalConcurrencyLimit() may /// overtax the machine. /// /// In general, very few places should call this function. Call it in places @@ -57,15 +61,17 @@ void WorkSetConcurrencyLimit(unsigned n); /// Sanitize \p n as described below and set the concurrency limit accordingly. /// This function is useful for interpreting command line arguments. /// -/// If \p n is between 1 and WorkGetMaximumConcurrencyLimit() -/// (inclusive) then call WorkSetConcurrencyLimit(n). +/// If \p n is zero, then do not change the current concurrency limit. /// -/// If \p n is 0 or larger than the number of physical cores, call -/// WorkSetMaximumConcurrencyLimit(). +/// If \p n is a positive, non-zero value then call WorkSetConcurrencyLimit(n). +/// Note that calling this method with \p n greater than the value returned by +/// WorkGetPhysicalConcurrencyLimit() may overtax the machine. /// /// If \p n is negative, then set the concurrency limit to all but abs(\p n) -/// cores are used. For examlpe, if \p n is -2, then use all but two cores. If -/// abs(\p n) is greater than the number of physical cores, then call +/// cores. The number of cores is determined by the value returned by +/// WorkGetPhysicalConcurrencyLimit(). +/// For example, if \p n is -2, then use all but two cores. If abs(\p n) is +/// greater than the number of physical cores, then call /// WorkSetConcurrencyLimit(1), effectively disabling concurrency. /// void WorkSetConcurrencyLimitArgument(int n); @@ -73,7 +79,7 @@ void WorkSetConcurrencyLimitArgument(int n); /// Set the concurrency limit to be the maximum recommended for the hardware /// on which it's running. Equivalent to: /// \code -/// WorkSetConcurrencyLimit(WorkGetMaximumConcurrencyLimit()). +/// WorkSetConcurrencyLimit(WorkGetPhysicalConcurrencyLimit()). /// \endcode /// void WorkSetMaximumConcurrencyLimit(); diff --git a/pxr/base/lib/work/wrapThreadLimits.cpp b/pxr/base/lib/work/wrapThreadLimits.cpp index 866b06f6e5..0ed66a16ce 100644 --- a/pxr/base/lib/work/wrapThreadLimits.cpp +++ b/pxr/base/lib/work/wrapThreadLimits.cpp @@ -30,7 +30,7 @@ using namespace boost::python; void wrapThreadLimits() { def("GetConcurrencyLimit", &WorkGetConcurrencyLimit); - def("GetMaximumConcurrencyLimit", &WorkGetMaximumConcurrencyLimit); + def("GetPhysicalConcurrencyLimit", &WorkGetPhysicalConcurrencyLimit); def("SetConcurrencyLimit", &WorkSetConcurrencyLimit); def("SetConcurrencyLimitArgument", &WorkSetConcurrencyLimitArgument); From 928fe897ec7a747de9de0c5afe19a6e95f91e1ae Mon Sep 17 00:00:00 2001 From: mrawde Date: Mon, 29 Aug 2016 21:26:27 -0700 Subject: [PATCH 039/380] Add more API for dealing with indexed primvars. Add BlockIndices() and update IsIndexed() to query this. (Internal change: 1650542) --- pxr/usd/lib/usdGeom/primvar.cpp | 18 ++++++++++++- pxr/usd/lib/usdGeom/primvar.h | 41 +++++++++++++++++++++++++++-- pxr/usd/lib/usdGeom/wrapPrimvar.cpp | 1 + 3 files changed, 57 insertions(+), 3 deletions(-) diff --git a/pxr/usd/lib/usdGeom/primvar.cpp b/pxr/usd/lib/usdGeom/primvar.cpp index f1efd914d8..1fef467f4f 100644 --- a/pxr/usd/lib/usdGeom/primvar.cpp +++ b/pxr/usd/lib/usdGeom/primvar.cpp @@ -219,6 +219,20 @@ UsdGeomPrimvar::SetIndices(const VtIntArray &indices, } +void +UsdGeomPrimvar::BlockIndices() const +{ + // Check if the typeName is array valued here and issue a warning + // if it's not. + SdfValueTypeName typeName = GetTypeName(); + if (not typeName.IsArray()) { + TF_CODING_ERROR("Setting indices on non-array valued primvar of type " + "'%s'.", typeName.GetAsToken().GetText()); + return; + } + _GetIndicesAttr(/*create*/ true).Block(); +} + bool UsdGeomPrimvar::GetIndices(VtIntArray *indices, UsdTimeCode time) const @@ -233,7 +247,9 @@ UsdGeomPrimvar::GetIndices(VtIntArray *indices, bool UsdGeomPrimvar::IsIndexed() const { - return _GetIndicesAttr(/*create*/ false); + // XXX update this to api that can directly see if an attribute is blocked. + VtIntArray dummy; + return _GetIndicesAttr(/*create*/ false).Get(&dummy); } bool diff --git a/pxr/usd/lib/usdGeom/primvar.h b/pxr/usd/lib/usdGeom/primvar.h index ae3b14abde..dc143e271f 100644 --- a/pxr/usd/lib/usdGeom/primvar.h +++ b/pxr/usd/lib/usdGeom/primvar.h @@ -113,6 +113,31 @@ /// ... /// \endcode /// +/// \subsection Usd_Handling_Indexed_Primvars Proper Client Handling of "Indexed" Primvars +/// +/// As discussed in greater detail in +/// \ref UsdGeomPrimvar_Indexed_primvars "Indexed Primvars", primvars can +/// optionally contain a (possibly time-varying) indexing attribute that +/// establishes a sharing topology for elements of the primvar. Consumers +/// can always chose to ignore the possibility of indexed data by exclusively +/// using the ComputeFlattened() API. If a client wishes to preserve indexing +/// in their processing of a primvar, we suggest a pattern like the following, +/// which accounts for the fact that a stronger layer can +/// \ref UsdAttribute::Block() "block" a primvar's indexing from a weaker +/// layer, via UsdGeomPrimvar::BlockIndices(): +/// \code +/// VtValue values; +/// VtIntArray indices; +/// +/// if (primvar.Get(&values, timeCode)){ +/// if (primvar.GetIndices(&indices, timeCode)){ +/// // primvar is indexed: validate/process values and indices together +/// } +/// else { +/// // primvar is not indexed: validate/process values as flat array +/// } +/// } +/// \endcode /// /// \subsection Usd_Primvar_As_Attribute UsdGeomPrimvar and UsdAttribute API /// @@ -336,7 +361,10 @@ class UsdGeomPrimvar /// \sa UsdAttribute::GetTypeName() SdfValueTypeName GetTypeName() const { return _attr.GetTypeName(); } - /// Get the attribute value of the Primvar at \p time + /// Get the attribute value of the Primvar at \p time . + /// + /// \sa Usd_Handling_Indexed_Primvars for proper handling of + /// \ref Usd_Handling_Indexed_Primvars "indexed primvars" template bool Get(T* value, UsdTimeCode time = UsdTimeCode::Default()) const { return _attr.Get(value, time); @@ -371,6 +399,7 @@ class UsdGeomPrimvar /// the unique elements. The final value of the primvar is computed using /// the indices array and the attribute value array. /// + /// See also \ref Usd_Handling_Indexed_Primvars /// Sets the indices value of the indexed primvar at \p time. /// @@ -384,12 +413,20 @@ class UsdGeomPrimvar /// Returns the value of the indices array associated with the indexed /// primvar at \p time. /// - /// \sa SetIndices() + /// \sa SetIndices(), \ref Usd_Handling_Indexed_Primvars bool GetIndices(VtIntArray *indices, UsdTimeCode time = UsdTimeCode::Default()) const; + /// Block the indices that were previously set. This effectively makes an + /// indexed primvar no longer indexed. This is useful when overriding an + /// existing primvar. + void BlockIndices() const; + /// Returns true if the primvar is indexed, i.e., if it has an associated /// "indices" attribute. + /// + /// If you are going to query the indices anyways, prefer to simply + /// consult the return-value of GetIndices(), which will be more efficient. bool IsIndexed() const; diff --git a/pxr/usd/lib/usdGeom/wrapPrimvar.cpp b/pxr/usd/lib/usdGeom/wrapPrimvar.cpp index af2f0e06df..8226a532c6 100644 --- a/pxr/usd/lib/usdGeom/wrapPrimvar.cpp +++ b/pxr/usd/lib/usdGeom/wrapPrimvar.cpp @@ -116,6 +116,7 @@ void wrapUsdGeomPrimvar() .def("SetIndices", &Primvar::SetIndices, (arg("indices"), arg("time")=UsdTimeCode::Default())) + .def("BlockIndices", &Primvar::BlockIndices) .def("GetIndices", _GetIndices, (arg("time")=UsdTimeCode::Default())) .def("IsIndexed", &Primvar::IsIndexed) From 53b38b0d12ecfd0b6ca86905134016e86025bd4e Mon Sep 17 00:00:00 2001 From: comand Date: Mon, 29 Aug 2016 21:27:44 -0700 Subject: [PATCH 040/380] Add a std::list_initializer constructor to VtDictionary. (Internal change: 1650597) --- pxr/base/lib/vt/dictionary.cpp | 5 +++++ pxr/base/lib/vt/dictionary.h | 4 ++++ pxr/base/lib/vt/testenv/testVtCpp.cpp | 23 +++++++++++++++++++++++ 3 files changed, 32 insertions(+) diff --git a/pxr/base/lib/vt/dictionary.cpp b/pxr/base/lib/vt/dictionary.cpp index 54580215ef..a6e5b1b65e 100644 --- a/pxr/base/lib/vt/dictionary.cpp +++ b/pxr/base/lib/vt/dictionary.cpp @@ -59,6 +59,11 @@ VtDictionary::VtDictionary(VtDictionary const& other) { if (other._dictMap) _dictMap.reset(new _Map(*other._dictMap)); } + +VtDictionary::VtDictionary(std::initializer_list init) + : _dictMap(new _Map(init.begin(), init.end())) +{ +} VtDictionary& VtDictionary::operator=(VtDictionary const& other) { if (this != &other) diff --git a/pxr/base/lib/vt/dictionary.h b/pxr/base/lib/vt/dictionary.h index a03ac06ded..e97a18c167 100644 --- a/pxr/base/lib/vt/dictionary.h +++ b/pxr/base/lib/vt/dictionary.h @@ -39,6 +39,7 @@ #include #include +#include #include #include @@ -183,6 +184,9 @@ class VtDictionary { /// Creates a new VtDictionary by moving the supplied \p VtDictionary. VtDictionary(VtDictionary && other) = default; + /// Creates a new VtDictionary from a braced initializer list. + VtDictionary(std::initializer_list init); + /// Copy assignment operator VtDictionary& operator=(VtDictionary const& other); diff --git a/pxr/base/lib/vt/testenv/testVtCpp.cpp b/pxr/base/lib/vt/testenv/testVtCpp.cpp index 0ae0654d7c..9655a16c69 100644 --- a/pxr/base/lib/vt/testenv/testVtCpp.cpp +++ b/pxr/base/lib/vt/testenv/testVtCpp.cpp @@ -619,6 +619,28 @@ testDictionaryIterators() } } +static void +testDictionaryInitializerList() +{ + const VtDictionary dict{}; + TF_AXIOM(dict.empty()); + + const VtDictionary dict2 = { + { "key_a", VtValue(1) }, + { "key_b", VtValue(2) } + }; + TF_AXIOM(not dict2.empty()); + + int i = 0; + for (const string& k : {"key_a", "key_b"}) { + auto it = dict2.find(k); + TF_AXIOM(it != dict2.end()); + TF_AXIOM(it->first == k); + TF_AXIOM(it->second.IsHolding()); + TF_AXIOM(it->second.UncheckedGet() == ++i); + } +} + // dest and source types are flipped so we can allow compiler to infer // source type template @@ -1109,6 +1131,7 @@ int main(int argc, char *argv[]) testDictionaryKeyPathAPI(); testDictionaryOverRecursive(); testDictionaryIterators(); + testDictionaryInitializerList(); testDictionaryPyFormatting(); testValue(); From cf8e6a146e74fc020acef9bfb8b898d88ad40f90 Mon Sep 17 00:00:00 2001 From: sunyab Date: Mon, 29 Aug 2016 21:28:07 -0700 Subject: [PATCH 041/380] Add Travis CI configuration for USD repository on GitHub. (Internal change: 1650646) --- .travis.yml | 157 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 157 insertions(+) create mode 100644 .travis.yml diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000000..f4f461c795 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,157 @@ +# +# 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. +# + +# USD requires several dependencies that are available via +# apt-get if using the trusty build environment. +sudo: required +dist: trusty + +language: cpp + +branches: + only: + - master + - dev + +before_install: + - sudo apt-get -qq update + +install: + ###### + ### DEPENDENCIES FOR USD CORE + ##### + + ### boost v1.55 + ### We install only the packages we need for faster turnaround + - sudo apt-get install libboost-iostreams1.55.0 libboost-iostreams1.55-dev + - sudo apt-get install libboost-python1.55.0 libboost-python1.55-dev + - sudo apt-get install libboost-regex1.55.0 libboost-regex1.55-dev + - sudo apt-get install libboost-system1.55.0 libboost-system1.55-dev + - sudo apt-get install libboost-program-options1.55.0 libboost-program-options1.55-dev + + ### double-conversion + ### USD docs currently claim we require 1.1.1, but apt-get gives us 2.0.1 on trusty. + ### Building 1.1.1 as a shared library is annoying, so we'll go with this for now. + - sudo apt-get install libdouble-conversion-dev + + ### Intel TBB v4.3 update 1 + - if [ ! -d "$HOME/tbb43_20141023oss/lib" ]; then + wget https://www.threadingbuildingblocks.org/sites/default/files/software_releases/linux/tbb43_20141023oss_lin.tgz -O /tmp/tbb.tgz; + tar -xvzf /tmp/tbb.tgz -C $HOME; + else + echo 'Using cached TBB'; + fi + + ### ilmbase and OpenEXR 2.2.0 + - if [ ! -d "$HOME/openexr/lib" ]; then + wget http://download.savannah.nongnu.org/releases/openexr/ilmbase-2.2.0.tar.gz -O /tmp/ilmbase.tgz; + tar -xvzf /tmp/ilmbase.tgz -C $HOME; + pushd $HOME/ilmbase-2.2.0; + ./configure --prefix=$HOME/openexr; + make && make install; + popd; + wget http://download.savannah.nongnu.org/releases/openexr/openexr-2.2.0.tar.gz -O /tmp/openexr.tgz; + tar -xvzf /tmp/openexr.tgz -C $HOME; + pushd $HOME/openexr-2.2.0; + ./configure --prefix=$HOME/openexr --with-pkg-config=no LDFLAGS="-Wl,-rpath -Wl,$HOME/openexr/lib"; + make && make install; + popd; + else + echo 'Using cached OpenEXR'; + fi + + ###### + ### DEPENDENCIES FOR IMAGING + ##### + + ### GLEW 1.10.0 + - sudo apt-get install libglew-dev + + ### OpenSubdiv 3.0.0 + - sudo apt-get install libxrandr-dev libxcursor-dev libxinerama-dev libglfw-dev + - if [ ! -d "$HOME/osd/lib" ]; then + wget https://github.com/PixarAnimationStudios/OpenSubdiv/archive/v3_0_0.tar.gz -O /tmp/osd.tgz; + tar -xvzf /tmp/osd.tgz -C $HOME; + pushd $HOME/OpenSubdiv-3_0_0; + mkdir build && cd build; + cmake -DCMAKE_INSTALL_PREFIX=$HOME/osd -DNO_EXAMPLES=1 -DNO_TUTORIALS=1 -DNO_REGRESSION=1 -D NO_MAYA=1 -D NO_PTEX=1 -D NO_DOC=1 -D NO_OMP=1 -D NO_TBB=1 -D NO_CUDA=1 -D NO_OPENCL=1 -D NO_CLEW=1 ..; + make && make install; + popd; + else + echo 'Using cached OpenSubdiv'; + fi + # XXX: To workaround issue #3, create a symlink at opensubdiv3/ pointing to opensubdiv/ + - rm -f $HOME/osd/include/opensubdiv3 && ln -s $HOME/osd/include/opensubdiv $HOME/osd/include/opensubdiv3 + + ### OpenImageIO 1.5.11 + - sudo apt-get install libboost-filesystem1.55.0 libboost-filesystem1.55-dev + - sudo apt-get install libboost-thread1.55.0 libboost-thread1.55-dev + - if [ ! -d "$HOME/oiio/lib" ]; then + wget https://github.com/OpenImageIO/oiio/archive/Release-1.5.11.tar.gz -O /tmp/oiio.tgz; + tar -xvzf /tmp/oiio.tgz -C $HOME; + pushd $HOME/oiio-Release-1.5.11; + mkdir build && cd build; + cmake -DCMAKE_INSTALL_PREFIX=$HOME/oiio -DILMBASE_HOME=$HOME/openexr -DOPENEXR_HOME=$HOME/openexr ..; + make && make install; + popd; + else + echo 'Using cached OpenImageIO'; + fi + + ### Ptex 2.0.30 + - if [ ! -d "$HOME/ptex/lib" ]; then + wget https://github.com/wdas/ptex/archive/v2.0.30.tar.gz -O /tmp/ptex.tgz; + tar -xvzf /tmp/ptex.tgz -C $HOME; + pushd $HOME/ptex-2.0.30/src; + make; + mv $HOME/ptex-2.0.30/install/* $HOME/ptex; + popd; + else + echo 'Using cached Ptex'; + fi + + ###### + ### DEPENDENCIES FOR USDIMAGING + ##### + + ### PySide 1.2.2 + - sudo apt-get install python-pyside pyside-tools + +cache: + directories: + - $HOME/openexr + - $HOME/osd + - $HOME/oiio + - $HOME/ptex + - $HOME/tbb43_20141023oss + +script: + - mkdir build && cd build + - cmake -DTBB_ROOT_DIR=$HOME/tbb43_20141023oss -DOPENEXR_LOCATION=$HOME/openexr -DOIIO_LOCATION=$HOME/oiio -DOPENSUBDIV_ROOT_DIR=$HOME/osd -DPTEX_LOCATION=$HOME/ptex -DPXR_VALIDATE_GENERATED_CODE=OFF .. + - echo 'Building with -j4' + # XXX: Need to explicitly build cameraUtil before hd due to missing dependency declaration. + # This is fixed in commit 880b04. + - make -j4 cameraUtil + - make -j4 + - make install From c5024e68f4ff0311fbf36420df6848c65c85023d Mon Sep 17 00:00:00 2001 From: blevin Date: Tue, 30 Aug 2016 10:07:38 -0700 Subject: [PATCH 042/380] Pcp: fix relocates update bug PcpLayerStack already records the paths where it discovered relocation opinions. Use that to invalidate the relocations when doing a significant prim resync. (Internal change: 1650665) --- pxr/usd/lib/pcp/cache.cpp | 4 +- pxr/usd/lib/pcp/changes.cpp | 116 ++++++++++++++++++----------- pxr/usd/lib/pcp/statistics.cpp | 15 ++++ pxr/usd/lib/pcp/wrapLayerStack.cpp | 8 +- 4 files changed, 93 insertions(+), 50 deletions(-) diff --git a/pxr/usd/lib/pcp/cache.cpp b/pxr/usd/lib/pcp/cache.cpp index affabd9078..360312f07b 100644 --- a/pxr/usd/lib/pcp/cache.cpp +++ b/pxr/usd/lib/pcp/cache.cpp @@ -1319,10 +1319,8 @@ _AddRelocateEditsForLayerStack( layerStack->GetPathsToPrimsWithRelocates(); TF_FOR_ALL(pathIt, relocatePrimPaths) { TF_FOR_ALL(layerIt, layerStack->GetLayers()) { - // XXX: The prim should always be valid, but might not be due to - // bug 101300 const SdfPrimSpecHandle prim = (*layerIt)->GetPrimAtPath(*pathIt); - if (not prim or not prim->HasRelocates()) { + if (not TF_VERIFY(prim) or not prim->HasRelocates()) { continue; } diff --git a/pxr/usd/lib/pcp/changes.cpp b/pxr/usd/lib/pcp/changes.cpp index 2a92ee4295..1d479c641d 100644 --- a/pxr/usd/lib/pcp/changes.cpp +++ b/pxr/usd/lib/pcp/changes.cpp @@ -721,31 +721,65 @@ PcpChanges::DidChange(const std::vector& caches, // (layer,path). If there aren't any and we want to fallback to our // parent then find all paths in the cache that use the parent. In // either case mark the found paths as having a significant change. - if (not pathsWithSignificantChanges.empty()) { - BOOST_FOREACH(const SdfPath& path, pathsWithSignificantChanges) { - // Compute the closest ancestor that must have dependencies. - SdfPath fallbackPath = findAncestor(path); - - BOOST_FOREACH(PcpCache* cache, caches) { - _DidChangeDependents( - _ChangeTypeSignificant, cache, layer, - path, fallbackPath, debugSummary); - } + BOOST_FOREACH(const SdfPath& path, pathsWithSignificantChanges) { + // Compute the closest ancestor that must have dependencies. + SdfPath fallbackPath = findAncestor(path); + + BOOST_FOREACH(PcpCache* cache, caches) { + _DidChangeDependents( + _ChangeTypeSignificant, cache, layer, + path, fallbackPath, debugSummary); } } // For every path we've found that has a significant change in // a specific cache, use the same logic as above to mark those paths // as having a significant change, but only in the associated cache. - if (not pathsWithSignificantChangesByCache.empty()) { - BOOST_FOREACH(const CacheAndLayerPathPair& p, - pathsWithSignificantChangesByCache) { - // Compute the closest ancestor that must have dependencies. - SdfPath fallbackPath = findAncestor(p.second); + BOOST_FOREACH(const CacheAndLayerPathPair& p, + pathsWithSignificantChangesByCache) { + // Compute the closest ancestor that must have dependencies. + SdfPath fallbackPath = findAncestor(p.second); + + _DidChangeDependents( + _ChangeTypeSignificant, p.first, layer, + p.second, fallbackPath, debugSummary); + } - _DidChangeDependents( - _ChangeTypeSignificant, p.first, layer, - p.second, fallbackPath, debugSummary); + // For every path we've found that has a significant change, + // check layer stacks that have discovered relocations that + // could be affected by that change. + if (not pathsWithSignificantChanges.empty()) { + // If this scope turns out to be expensive, we should look + // at switching PcpLayerStack's _relocatesPrimPaths from + // a std::vector to a path set. _AddRelocateEditsForLayerStack + // also does a traversal and might see a similar benefit. + TRACE_SCOPE("PcpChanges::DidChange -- Checking layer stack " + "relocations against significant prim resyncs"); + + for(const CacheLayerStacks &i: cacheLayerStacks) { + if (i.first->_usd) { + // No relocations in usd mode + continue; + } + for(const PcpLayerStackPtr &layerStack: i.second) { + const SdfPathVector& reloPaths = + layerStack->GetPathsToPrimsWithRelocates(); + if (reloPaths.empty()) { + continue; + } + for(const SdfPath &changedPath: + pathsWithSignificantChanges) { + for(const SdfPath &reloPath: reloPaths) { + if (reloPath.HasPrefix(changedPath)) { + layerStackChangesMap[layerStack] + |= LayerStackRelocatesChange; + goto doneWithLayerStack; + } + } + } + doneWithLayerStack: + ; + } } } @@ -755,33 +789,31 @@ PcpChanges::DidChange(const std::vector& caches, // there aren't any then find all paths in the cache that use the // parent. In either case mark the found paths as needing their // property spec stacks blown. - if (not pathsWithSpecChanges.empty()) { - BOOST_FOREACH(const PathChangeValue& value, pathsWithSpecChanges) { - const SdfPath& path = value.first; - PathChangeBitmask changes = value.second; - - int changeType = 0; - if (changes & PathChangeTargets) { - changeType |= _ChangeTypeTargets; - } - if (changes & PathChangeConnections) { - changeType |= _ChangeTypeConnections; - } + BOOST_FOREACH(const PathChangeValue& value, pathsWithSpecChanges) { + const SdfPath& path = value.first; + PathChangeBitmask changes = value.second; - // If the changes for this path include something other than - // target changes, they must be spec changes. - if (changes & ~(PathChangeTargets | PathChangeConnections)) { - changeType |= _ChangeTypeSpecs; - } + int changeType = 0; + if (changes & PathChangeTargets) { + changeType |= _ChangeTypeTargets; + } + if (changes & PathChangeConnections) { + changeType |= _ChangeTypeConnections; + } - // Compute the closest ancestor that must have dependencies. - SdfPath fallbackPath = findAncestor(path); + // If the changes for this path include something other than + // target changes, they must be spec changes. + if (changes & ~(PathChangeTargets | PathChangeConnections)) { + changeType |= _ChangeTypeSpecs; + } - BOOST_FOREACH(PcpCache* cache, caches) { - _DidChangeDependents( - changeType, cache, layer, - path, fallbackPath, debugSummary); - } + // Compute the closest ancestor that must have dependencies. + SdfPath fallbackPath = findAncestor(path); + + BOOST_FOREACH(PcpCache* cache, caches) { + _DidChangeDependents( + changeType, cache, layer, + path, fallbackPath, debugSummary); } } diff --git a/pxr/usd/lib/pcp/statistics.cpp b/pxr/usd/lib/pcp/statistics.cpp index 6889c8562d..21e09451a1 100644 --- a/pxr/usd/lib/pcp/statistics.cpp +++ b/pxr/usd/lib/pcp/statistics.cpp @@ -24,6 +24,7 @@ #include "pxr/usd/pcp/statistics.h" #include "pxr/usd/pcp/cache.h" +#include "pxr/usd/pcp/layerStackRegistry.h" #include "pxr/usd/pcp/primIndex.h" #include "pxr/usd/pcp/primIndex_Graph.h" @@ -65,6 +66,7 @@ struct Pcp_CacheStats Pcp_GraphStats sharedAllGraphStats; Pcp_GraphStats sharedCulledGraphStats; std::map mapFunctionSizeDistribution; + std::map layerStackRelocationsSizeDistribution; }; class Pcp_Statistics @@ -154,6 +156,13 @@ class Pcp_Statistics size_t size = i->GetSourceToTargetMap().size(); stats->mapFunctionSizeDistribution[size] += 1; } + + // PcpLayerStack _relocatesPrimPaths size distribution + for(const PcpLayerStackPtr &layerStack: + cache->_layerStackCache->GetAllLayerStacks()) { + size_t size = layerStack->GetPathsToPrimsWithRelocates().size(); + stats->layerStackRelocationsSizeDistribution[size] += 1; + } } // Shamelessly stolen from Csd/Scene_PrimCachePopulation.cpp. @@ -309,6 +318,12 @@ class Pcp_Statistics printf("%zu %zu\n", i->first, i->second); } + out << "PcpLayerStack pathsWithRelocates size histogram: " << endl; + out << "SIZE COUNT" << endl; + TF_FOR_ALL(i, stats.layerStackRelocationsSizeDistribution) { + printf("%zu %zu\n", i->first, i->second); + } + // Assert sizes of structs we want to keep a close eye on. BOOST_STATIC_ASSERT(sizeof(PcpMapFunction) == 8); BOOST_STATIC_ASSERT(sizeof(PcpMapExpression) == 8); diff --git a/pxr/usd/lib/pcp/wrapLayerStack.cpp b/pxr/usd/lib/pcp/wrapLayerStack.cpp index c2480bd2fa..b27d4f7184 100644 --- a/pxr/usd/lib/pcp/wrapLayerStack.cpp +++ b/pxr/usd/lib/pcp/wrapLayerStack.cpp @@ -71,29 +71,27 @@ void wrapLayerStack() .add_property("layers", make_function(&_GetLayerStackLayers, return_value_policy())) - .add_property("layerOffsets", make_function(&_GetLayerOffsets, return_value_policy())) - .add_property("layerTree", make_function(&PcpLayerStack::GetLayerTree, return_value_policy())) - .add_property("resolvedAssetPaths", make_function(&_GetResolvedAssetPaths, return_value_policy())) - .add_property("relocatesSourceToTarget", make_function(&PcpLayerStack::GetRelocatesSourceToTarget, return_value_policy())) - .add_property("relocatesTargetToSource", make_function(&PcpLayerStack::GetRelocatesTargetToSource, return_value_policy())) .add_property("localErrors", make_function(&PcpLayerStack::GetLocalErrors, return_value_policy())) + .add_property("pathsToPrimsWithRelocates", + make_function(&PcpLayerStack::GetPathsToPrimsWithRelocates, + return_value_policy())) // TODO: repr, eq, etc. ; } From ae9a623a924cb82970c5c2af242a29e2a30f3249 Mon Sep 17 00:00:00 2001 From: Peter Shinners Date: Sat, 20 Aug 2016 10:32:21 -0700 Subject: [PATCH 043/380] Remove trailing semicolons These do not change are alter the code in any way, but likely come from fingers of habit from C developers. --- pxr/base/lib/gf/testenv/testGfFrustum.py | 6 +++--- pxr/base/lib/gf/testenv/testGfMatrix.py | 2 +- pxr/base/lib/gf/testenv/testGfRange.py | 4 ++-- pxr/base/lib/gf/testenv/testGfRay.py | 4 ++-- pxr/base/lib/gf/testenv/testGfSize.py | 4 ++-- pxr/base/lib/gf/testenv/testGfVec.py | 8 ++++---- pxr/base/lib/plug/testPlug.py | 10 +++++----- pxr/base/lib/tf/testenv/testTfPyDiagnosticNotices.py | 12 ++++++------ pxr/base/lib/tf/testenv/testTfType.py | 2 +- pxr/base/lib/vt/testenv/testVtArray.py | 2 +- pxr/usd/bin/usdcat/usdcat.py | 2 +- pxr/usdImaging/lib/usdviewq/mainWindow.py | 4 ++-- pxr/usdImaging/lib/usdviewq/pythonInterpreter.py | 2 +- pxr/usdImaging/lib/usdviewq/stageView.py | 10 +++++----- .../lib/usdMaya/AEpxrUsdReferenceAssemblyTemplate.py | 6 +++--- 15 files changed, 39 insertions(+), 39 deletions(-) diff --git a/pxr/base/lib/gf/testenv/testGfFrustum.py b/pxr/base/lib/gf/testenv/testGfFrustum.py index 8a173e31fa..c084db134a 100644 --- a/pxr/base/lib/gf/testenv/testGfFrustum.py +++ b/pxr/base/lib/gf/testenv/testGfFrustum.py @@ -56,8 +56,8 @@ def test_PlaneIntersection(self): def test_Position(self): f1 = Gf.Frustum() f2 = Gf.Frustum() - f1.position = Gf.Vec3d(1, 0, 0); - f2.position = Gf.Vec3d(0, 1, 0); + f1.position = Gf.Vec3d(1, 0, 0) + f2.position = Gf.Vec3d(0, 1, 0) self.assertNotEqual(f1, f2) def test_Properties(self): @@ -314,7 +314,7 @@ def test_IntersectionViewVolume(self): 0.0, 4.2418940586972074, 0.0, 0.0, 0.0, 0.0, -1, -1.0, 0.0, 0.0, -20, 0.0) - viewProjMat = viewMat * projMat; + viewProjMat = viewMat * projMat # a typical box entirely in the view b = Gf.BBox3d( Gf.Range3d( Gf.Vec3d( 0, 0, 0 ), Gf.Vec3d( 1, 1, 1 ) ) ) diff --git a/pxr/base/lib/gf/testenv/testGfMatrix.py b/pxr/base/lib/gf/testenv/testGfMatrix.py index 75948d456c..a197180c7d 100644 --- a/pxr/base/lib/gf/testenv/testGfMatrix.py +++ b/pxr/base/lib/gf/testenv/testGfMatrix.py @@ -126,7 +126,7 @@ def runTest(self): v = Vec() for i in range(v.dimension): v[i] = i - m1 = Matrix().SetDiagonal(v); + m1 = Matrix().SetDiagonal(v) m2 = Matrix(0) for i in range(m2.dimension[0]): m2[i,i] = i diff --git a/pxr/base/lib/gf/testenv/testGfRange.py b/pxr/base/lib/gf/testenv/testGfRange.py index 2cdadaac52..3e3d8d7a9c 100644 --- a/pxr/base/lib/gf/testenv/testGfRange.py +++ b/pxr/base/lib/gf/testenv/testGfRange.py @@ -52,9 +52,9 @@ def runTest(self): v = makeValue(Value, [1, 2, 3, 4]) r = Range() - r.min = v; + r.min = v self.assertEqual(r.min, v) - r.max = v; + r.max = v self.assertEqual(r.max, v) r = Range() diff --git a/pxr/base/lib/gf/testenv/testGfRay.py b/pxr/base/lib/gf/testenv/testGfRay.py index 06a41cee38..81cb069ef0 100644 --- a/pxr/base/lib/gf/testenv/testGfRay.py +++ b/pxr/base/lib/gf/testenv/testGfRay.py @@ -308,7 +308,7 @@ def test_IntersectCylinder(self): # Ray behind cylinder, orthogonal to surface x = radius * (1 + random.uniform(epsilon, 1)) - distance = x - radius; + distance = x - radius ray = Gf.Ray(Gf.Vec3d(-x, 0, 0), Gf.Vec3d().XAxis()) (hit, enter, exit) = ray.Intersect(origin, axis, radius) @@ -434,7 +434,7 @@ def test_IntersectCone(self): self.assertAlmostEqual(exit, radius, delta=epsilon) # Ray behind cone, orthogonal to axis - distance = x - radius; + distance = x - radius ray = Gf.Ray(Gf.Vec3d(-x, 0, 0), Gf.Vec3d().XAxis()) (hit, enter, exit) = ray.Intersect(origin, axis, radius, height) diff --git a/pxr/base/lib/gf/testenv/testGfSize.py b/pxr/base/lib/gf/testenv/testGfSize.py index 4b57e55601..95b785d98e 100644 --- a/pxr/base/lib/gf/testenv/testGfSize.py +++ b/pxr/base/lib/gf/testenv/testGfSize.py @@ -46,12 +46,12 @@ def runTest(self): if Size.dimension == 2: self.assertIsInstance(Size(Gf.Vec2i()), Size) self.assertIsInstance(Size(3, 4), Size) - s = Size(); + s = Size() self.assertEqual(s.Set(3,4), Size(3,4)) elif Size.dimension == 3: self.assertIsInstance(Size(Gf.Vec3i()), Size) self.assertIsInstance(Size(3, 4, 5), Size) - s = Size(); + s = Size() self.assertEqual(s.Set(3,4,5), Size(3,4,5)) s = makeValue(Size, (1,2,3)) diff --git a/pxr/base/lib/gf/testenv/testGfVec.py b/pxr/base/lib/gf/testenv/testGfVec.py index f5bdf158ab..8c71adce0a 100644 --- a/pxr/base/lib/gf/testenv/testGfVec.py +++ b/pxr/base/lib/gf/testenv/testGfVec.py @@ -297,18 +297,18 @@ def MethodsTest(self, Vec): # Normalize... SetVec( v1, [3, 1, 4, 1] ) - v2 = Vec(v1); + v2 = Vec(v1) v2.Normalize() nv = Gf.GetNormalized( v1 ) nv2 = v1.GetNormalized() - nvcheck = v1 / Gf.GetLength(v1); + nvcheck = v1 / Gf.GetLength(v1) self.assertTrue(Gf.IsClose(nv, nvcheck, eps)) self.assertTrue(Gf.IsClose(nv2, nvcheck, eps)) self.assertTrue(Gf.IsClose(v2, nvcheck, eps)) SetVec( v1, [3, 1, 4, 1] ) nv = v1.GetNormalized() - nvcheck = v1 / Gf.GetLength(v1); + nvcheck = v1 / Gf.GetLength(v1) self.assertEqual(nv, nvcheck) SetVec(v1, [0,0,0,0]) @@ -357,7 +357,7 @@ def MethodsTest(self, Vec): for i in range(Vec.dimension): v1 = Vec.Axis(i) v2 = Vec() - v2[i] = 1; + v2[i] = 1 self.assertEqual(v1, v2) v1 = Vec.XAxis() diff --git a/pxr/base/lib/plug/testPlug.py b/pxr/base/lib/plug/testPlug.py index 8690f3b962..2817fb9cc3 100644 --- a/pxr/base/lib/plug/testPlug.py +++ b/pxr/base/lib/plug/testPlug.py @@ -252,24 +252,24 @@ def test_ErrorCases(self): # try to register a non-existent plugin path self.assertFalse(os.path.exists('/nowhere')) Plug.Registry().RegisterPlugins('/nowhere') - self.assertEqual(listener.numReceived, 0); + self.assertEqual(listener.numReceived, 0) # try to register an incomplete plugin badPluginPath = testPluginsDso + '/TestPlugDsoIncomplete.framework/Resources/' Plug.Registry().RegisterPlugins(badPluginPath) - self.assertEqual(listener.numReceived, 0); + self.assertEqual(listener.numReceived, 0) # try to register an incomplete python plugin path badPluginPath = testPluginsPython + '/TestPlugModuleIncomplete' Plug.Registry().RegisterPlugins(badPluginPath) - self.assertEqual(listener.numReceived, 0); + self.assertEqual(listener.numReceived, 0) # try to find a plugin for a Tf type which doesn't exist unknownPlug = None with self.assertRaises(RuntimeError): unknownPlug = Plug.Registry().GetPluginForType(Tf.Type.FindByName('Bad')) self.assertFalse(unknownPlug) - self.assertEqual(listener.numReceived, 0); + self.assertEqual(listener.numReceived, 0) # try to load an unloadable plugin badPlugin = Plug.Registry().GetPluginForType('TestPlugUnloadable') @@ -318,4 +318,4 @@ def test_ErrorCases(self): Plug.Registry().RegisterPlugins(testPluginsDsoSearch) Plug.Registry().RegisterPlugins(testPluginsPythonSearch) self.assertEqual(allplugins, Plug.Registry().GetAllPlugins()) - self.assertEqual(listener.numReceived, 0); + self.assertEqual(listener.numReceived, 0) diff --git a/pxr/base/lib/tf/testenv/testTfPyDiagnosticNotices.py b/pxr/base/lib/tf/testenv/testTfPyDiagnosticNotices.py index d22193faf7..d9f8be4495 100644 --- a/pxr/base/lib/tf/testenv/testTfPyDiagnosticNotices.py +++ b/pxr/base/lib/tf/testenv/testTfPyDiagnosticNotices.py @@ -96,24 +96,24 @@ def test_Notices(self): self.log.info("Issuing a couple of different types of errors.") try: - Tf.RaiseRuntimeError("Runtime error!"); + Tf.RaiseRuntimeError("Runtime error!") assert False, "expected exception" except Tf.ErrorException: pass try: - Tf.RaiseCodingError("Coding error!"); + Tf.RaiseCodingError("Coding error!") assert False, "expected exception" except Tf.ErrorException: pass self.log.info("Issuing a few generic warnings.") - Tf.Warn("Warning 1"); - Tf.Warn("Warning 2"); - Tf.Warn("Warning 3"); + Tf.Warn("Warning 1") + Tf.Warn("Warning 2") + Tf.Warn("Warning 3") self.log.info("Issuing a status message.") - Tf.Status("Status: Almost done testing."); + Tf.Status("Status: Almost done testing.") # Assert that two errors, three warnings and one status message were # issued. diff --git a/pxr/base/lib/tf/testenv/testTfType.py b/pxr/base/lib/tf/testenv/testTfType.py index 3c972819b6..a101bad81b 100644 --- a/pxr/base/lib/tf/testenv/testTfType.py +++ b/pxr/base/lib/tf/testenv/testTfType.py @@ -198,7 +198,7 @@ def test_FindDerivedByName(self): def test_PythonSubclassOfCppClass(self): class TestPyDerived( Tf.TestCppBase ): def TestVirtual(self): - return 123; + return 123 tTestCppBase = Tf.Type.Find( Tf.TestCppBase ) tTestPyDerived = Tf.Type.Define( TestPyDerived ) diff --git a/pxr/base/lib/vt/testenv/testVtArray.py b/pxr/base/lib/vt/testenv/testVtArray.py index 56d4e5f711..cb72f44943 100644 --- a/pxr/base/lib/vt/testenv/testVtArray.py +++ b/pxr/base/lib/vt/testenv/testVtArray.py @@ -106,7 +106,7 @@ def test_VtArraySlicingVsPythonSlicing(self): for start in range(-2, 7): for stop in range(-2, 7): for step in range(-5, 6): - if step == 0 : break; + if step == 0 : break sub_a = a[start:stop:step] sub_l = l[start:stop:step] self.assertEqual(len(a), len(l)) diff --git a/pxr/usd/bin/usdcat/usdcat.py b/pxr/usd/bin/usdcat/usdcat.py index b71f54d6d0..549412be52 100644 --- a/pxr/usd/bin/usdcat/usdcat.py +++ b/pxr/usd/bin/usdcat/usdcat.py @@ -25,7 +25,7 @@ import argparse, sys, signal, os def _Err(msg): - sys.stderr.write(msg + '\n'); + sys.stderr.write(msg + '\n') def GetUsdData(filePath): from pxr import Sdf diff --git a/pxr/usdImaging/lib/usdviewq/mainWindow.py b/pxr/usdImaging/lib/usdviewq/mainWindow.py index 9c9486a880..125f2cdc2b 100644 --- a/pxr/usdImaging/lib/usdviewq/mainWindow.py +++ b/pxr/usdImaging/lib/usdviewq/mainWindow.py @@ -1270,7 +1270,7 @@ def _configureRenderGraphPlugins(self): action = self._ui.menuRenderGraph.addAction(name) action.setCheckable(True) action.pluginType = pluginType - self._ui.renderGraphActionGroup.addAction(action); + self._ui.renderGraphActionGroup.addAction(action) QtCore.QObject.connect( action, @@ -3093,7 +3093,7 @@ def _updateAttributeViewInternal(self): tableWidget.item(attributeCount,0).setSelected(True) tableWidget.setCurrentItem(tableWidget.item(attributeCount, 0)) - attributeCount += 1; + attributeCount += 1 tableWidget.resizeColumnToContents(0) diff --git a/pxr/usdImaging/lib/usdviewq/pythonInterpreter.py b/pxr/usdImaging/lib/usdviewq/pythonInterpreter.py index db58395881..38402b791d 100644 --- a/pxr/usdImaging/lib/usdviewq/pythonInterpreter.py +++ b/pxr/usdImaging/lib/usdviewq/pythonInterpreter.py @@ -726,7 +726,7 @@ def mousePressEvent(self, e): def mouseDoubleClickEvent(self, e): self.Parent.mouseDoubleClickEvent(self, e) app = QtGui.QApplication.instance() - self.tripleClickTimer.start(app.doubleClickInterval(), self); + self.tripleClickTimer.start(app.doubleClickInterval(), self) # make a copy here, otherwise tripleClickPoint will always = globalPos self.tripleClickPoint = QtCore.QPoint(e.globalPos()) diff --git a/pxr/usdImaging/lib/usdviewq/stageView.py b/pxr/usdImaging/lib/usdviewq/stageView.py index 2345f7cfbc..289cf97ba8 100644 --- a/pxr/usdImaging/lib/usdviewq/stageView.py +++ b/pxr/usdImaging/lib/usdviewq/stageView.py @@ -1004,11 +1004,11 @@ def _updateBboxGuides(self): # XXX Why aren't these @properties? def setDisplayGuides(self, enabled): self._displayGuides = enabled - self._updateBboxGuides(); + self._updateBboxGuides() def setDisplayRenderingGuides(self, enabled): self._displayRenderingGuides = enabled - self._updateBboxGuides(); + self._updateBboxGuides() def setDisplayCameraOracles(self, enabled): self._displayCameraOracles = enabled @@ -1052,7 +1052,7 @@ def setNodes(self, nodes, frame, resetCam=False, forceComputeBBox=False, if self._bbox.GetRange().IsEmpty(): self._selectionBBox = self._getDefaultBBox() else: - self._selectionBBox = self._bbox; + self._selectionBBox = self._bbox else: self._selectionBBox = self.getSelectionBBox() @@ -1306,7 +1306,7 @@ def paintGL(self): GL.glEnable(GL.GL_DEPTH_TEST) GL.glDepthFunc(GL.GL_LESS) - GL.glBlendFunc(GL.GL_SRC_ALPHA, GL.GL_ONE_MINUS_SRC_ALPHA); + GL.glBlendFunc(GL.GL_SRC_ALPHA, GL.GL_ONE_MINUS_SRC_ALPHA) GL.glEnable(GL.GL_BLEND) frustum = self.computeGfCamera().frustum @@ -1697,7 +1697,7 @@ def detachAndReClipFromCurrentCamera(self): FreeCamera. Then reset the near/far clipping planes based on distance to closest geometry.""" if not self._freeCamera: - self.switchToFreeCamera(); + self.switchToFreeCamera() else: self.computeAndSetClosestDistance() diff --git a/third_party/maya/lib/usdMaya/AEpxrUsdReferenceAssemblyTemplate.py b/third_party/maya/lib/usdMaya/AEpxrUsdReferenceAssemblyTemplate.py index 868092eb4c..9bc797d267 100644 --- a/third_party/maya/lib/usdMaya/AEpxrUsdReferenceAssemblyTemplate.py +++ b/third_party/maya/lib/usdMaya/AEpxrUsdReferenceAssemblyTemplate.py @@ -111,7 +111,7 @@ def variantSets_Replace(nodeAttr, new): if new == True: cmds.frameLayout(frameLayoutName, label='VariantSets', collapse=False) else: - cmds.setParent(frameLayoutName); + cmds.setParent(frameLayoutName) # Remove existing children of layout children = cmds.frameLayout(frameLayoutName, q=True, childArray=True) @@ -131,8 +131,8 @@ def variantSets_Replace(nodeAttr, new): for regVarSet in UsdUtils.GetRegisteredVariantSets()] if usdPrim: - variantSets = usdPrim.GetVariantSets(); - variantSetNames = variantSets.GetNames(); + variantSets = usdPrim.GetVariantSets() + variantSetNames = variantSets.GetNames() for variantSetName in variantSetNames: if regVarSetNames and (variantSetName not in regVarSetNames): From 06a42ed575268da3bef1866690e6fc22154b6f48 Mon Sep 17 00:00:00 2001 From: Peter Shinners Date: Sat, 20 Aug 2016 10:36:08 -0700 Subject: [PATCH 044/380] Remove tab indentation from several python files A handful of Python files in usdviewq have stray tab indentions. This is technically an error, but Python2 tries to guess at the intention of the code. All tabs are removed. --- .../lib/usdviewq/attributeValueEditor.py | 2 +- pxr/usdImaging/lib/usdviewq/common.py | 1 - .../lib/usdviewq/customAttributes.py | 36 ++++---- .../lib/usdviewq/headerContextMenu.py | 2 +- pxr/usdImaging/lib/usdviewq/mainWindow.py | 2 +- .../lib/usdviewq/nodeContextMenuItems.py | 87 +++++++++---------- pxr/usdImaging/lib/usdviewq/nodeViewItem.py | 3 +- pxr/usdImaging/lib/usdviewq/scalarTypes.py | 17 ++-- 8 files changed, 74 insertions(+), 76 deletions(-) diff --git a/pxr/usdImaging/lib/usdviewq/attributeValueEditor.py b/pxr/usdImaging/lib/usdviewq/attributeValueEditor.py index d76a9c9b7c..ab1df0b847 100644 --- a/pxr/usdImaging/lib/usdviewq/attributeValueEditor.py +++ b/pxr/usdImaging/lib/usdviewq/attributeValueEditor.py @@ -201,4 +201,4 @@ def _revert(self, all=False): def _revertAll(self): self._revert(True) - + diff --git a/pxr/usdImaging/lib/usdviewq/common.py b/pxr/usdImaging/lib/usdviewq/common.py index d8221094f6..1112a28758 100644 --- a/pxr/usdImaging/lib/usdviewq/common.py +++ b/pxr/usdImaging/lib/usdviewq/common.py @@ -384,4 +384,3 @@ def DumpMallocTags(stage, contextStr): print "Unable to accumulate memory usage since the Pxr MallocTag system was not initialized" - diff --git a/pxr/usdImaging/lib/usdviewq/customAttributes.py b/pxr/usdImaging/lib/usdviewq/customAttributes.py index 7abe47dc7a..110dec03e2 100644 --- a/pxr/usdImaging/lib/usdviewq/customAttributes.py +++ b/pxr/usdImaging/lib/usdviewq/customAttributes.py @@ -46,18 +46,18 @@ def _GetCustomAttributes(currentNode, bboxCache, xformCache): # class CustomAttribute: def __init__(self, currentNode): - self._currentNode = currentNode + self._currentNode = currentNode def IsVisible(self): - return True + return True # GetName function to match UsdAttribute API def GetName(self): - return "" + return "" # Get function to match UsdAttribute API def Get(self, frame): - return "" + return "" # convenience function to make this look more like a UsdAttribute def GetTypeName(self): @@ -74,16 +74,16 @@ def __init__(self, currentNode, bboxCache): self._bboxCache = bboxCache def GetName(self): - return "World Bounding Box" - + return "World Bounding Box" + def Get(self, frame): - try: + try: bbox = self._bboxCache.ComputeWorldBound(self._currentNode) except RuntimeError, err: - bbox = "Invalid: " + str(err) - - return bbox + bbox = "Invalid: " + str(err) + + return bbox # # Displays the Local to world xform of a node @@ -96,15 +96,15 @@ def __init__(self, currentNode, xformCache): self._xformCache = xformCache def GetName(self): - return "Local to World Xform" - + return "Local to World Xform" + def Get(self, frame): - try: - pwt = self._xformCache.GetLocalToWorldTransform(self._currentNode) - except RuntimeError, err: - pwt = "Invalid: " + str(err) - - return pwt + try: + pwt = self._xformCache.GetLocalToWorldTransform(self._currentNode) + except RuntimeError, err: + pwt = "Invalid: " + str(err) + + return pwt # # Displays a relationship on the node diff --git a/pxr/usdImaging/lib/usdviewq/headerContextMenu.py b/pxr/usdImaging/lib/usdviewq/headerContextMenu.py index 0aaaaaba30..381aa58bca 100644 --- a/pxr/usdImaging/lib/usdviewq/headerContextMenu.py +++ b/pxr/usdImaging/lib/usdviewq/headerContextMenu.py @@ -33,7 +33,7 @@ class HeaderContextMenu(QtGui.QMenu): def __init__(self, parent): QtGui.QMenu.__init__(self, parent) self._menuItems = _GetContextMenuItems(parent) - + for menuItem in self._menuItems: if menuItem.isValid(): # create menu actions diff --git a/pxr/usdImaging/lib/usdviewq/mainWindow.py b/pxr/usdImaging/lib/usdviewq/mainWindow.py index 125f2cdc2b..fcc800c233 100644 --- a/pxr/usdImaging/lib/usdviewq/mainWindow.py +++ b/pxr/usdImaging/lib/usdviewq/mainWindow.py @@ -2838,7 +2838,7 @@ def _currentPathChanged(self): import re newPaths = self._ui.currentPathWidget.text() pathList = re.split(", ?", newPaths) - pathList = filter(lambda path: len(path) != 0, pathList) + pathList = filter(lambda path: len(path) != 0, pathList) itemList = [] for primPath in pathList: diff --git a/pxr/usdImaging/lib/usdviewq/nodeContextMenuItems.py b/pxr/usdImaging/lib/usdviewq/nodeContextMenuItems.py index 664ad5e743..ccee045dab 100644 --- a/pxr/usdImaging/lib/usdviewq/nodeContextMenuItems.py +++ b/pxr/usdImaging/lib/usdviewq/nodeContextMenuItems.py @@ -94,7 +94,7 @@ class JumpToEnclosingModelItem(NodeContextMenuItem): def IsEnabled(self): from common import GetEnclosingModelPrim - + for p in self._currentNodes: if GetEnclosingModelPrim(p) is not None: return True @@ -102,7 +102,7 @@ def IsEnabled(self): def GetText(self): return "Jump to Enclosing Model" - + def RunCommand(self): self._mainWindow.jumpToEnclosingModelSelectedPrims() @@ -114,16 +114,16 @@ class JumpToBoundLookMenuItem(NodeContextMenuItem): def IsEnabled(self): from common import GetClosestBoundLook - + for p in self._currentNodes: look, bound = GetClosestBoundLook(p) if look is not None: return True - return False + return False def GetText(self): return "Jump to Bound Look" - + def RunCommand(self): self._mainWindow.jumpToBoundLookSelectedPrims() @@ -136,11 +136,11 @@ def IsEnabled(self): for p in self._currentNodes: if p.IsInstance(): return True - return False + return False def GetText(self): return "Jump to Master" - + def RunCommand(self): self._mainWindow.jumpToMasterSelectedPrims() @@ -169,7 +169,7 @@ def RunCommand(self): class ToggleVisibilityMenuItem(NodeContextMenuItem): def __init__(self, mainWindow, item): - NodeContextMenuItem.__init__(self, mainWindow, item) + NodeContextMenuItem.__init__(self, mainWindow, item) from pxr import UsdGeom self._imageable = False self._isVisible = False @@ -238,7 +238,7 @@ def RunCommand(self): class LoadOrUnloadMenuItem(NodeContextMenuItem): def __init__(self, mainWindow, item): - NodeContextMenuItem.__init__(self, mainWindow, item) + NodeContextMenuItem.__init__(self, mainWindow, item) from common import GetPrimsLoadability # Use the descendent-pruned selection set to avoid redundant # traversal of the stage to answer isLoaded... @@ -267,14 +267,14 @@ def GetText(self): if len(self._currentNodes) > 1: return "Copy Prim Paths" return "Copy Prim Path" - + def RunCommand(self): - pathlist = [str(p.GetPath()) for p in self._currentNodes] - pathStrings = '\n'.join(pathlist) + pathlist = [str(p.GetPath()) for p in self._currentNodes] + pathStrings = '\n'.join(pathlist) cb = QtGui.QApplication.clipboard() - cb.setText(pathStrings, QtGui.QClipboard.Selection ) - cb.setText(pathStrings, QtGui.QClipboard.Clipboard ) + cb.setText(pathStrings, QtGui.QClipboard.Selection ) + cb.setText(pathStrings, QtGui.QClipboard.Clipboard ) # # Copies the path of the first-selected prim's enclosing model @@ -283,25 +283,25 @@ def RunCommand(self): class CopyModelPathMenuItem(NodeContextMenuItem): def __init__(self, mainWindow, item): - NodeContextMenuItem.__init__(self, mainWindow, item) + NodeContextMenuItem.__init__(self, mainWindow, item) from common import GetEnclosingModelPrim - + self._modelPrim = GetEnclosingModelPrim(self._currentNodes[0]) if \ len(self._currentNodes) == 1 else None def IsEnabled(self): - return self._modelPrim + return self._modelPrim def GetText(self): name = ( "(%s)" % self._modelPrim.GetName() ) if self._modelPrim else "" return "Copy Enclosing Model %s Path" % name - + def RunCommand(self): modelPath = str(self._modelPrim.GetPath()) cb = QtGui.QApplication.clipboard() - cb.setText(modelPath, QtGui.QClipboard.Selection ) - cb.setText(modelPath, QtGui.QClipboard.Clipboard ) - + cb.setText(modelPath, QtGui.QClipboard.Selection ) + cb.setText(modelPath, QtGui.QClipboard.Clipboard ) + # @@ -315,32 +315,32 @@ def GetText(self): return "Isolate Copy of Prim..." def RunCommand(self): - inFile = self._currentNodes[0].GetScene().GetUsdFile() - - guessOutFile = os.getcwd() + "/" + self._currentNodes[0].GetName() + "_copy.usd" + inFile = self._currentNodes[0].GetScene().GetUsdFile() + + guessOutFile = os.getcwd() + "/" + self._currentNodes[0].GetName() + "_copy.usd" (outFile, _) = QtGui.QFileDialog.getSaveFileName(None, "Specify the Usd file to create", guessOutFile, 'Usd files (*.usd)') if (outFile.rsplit('.')[-1] != 'usd'): outFile += '.usd' - - if inFile == outFile: - sys.stderr.write( "Cannot isolate a copy to the source usd!\n" ) - return - sys.stdout.write( "Writing copy to new file '%s' ... " % outFile ) - sys.stdout.flush() - - os.system( 'usdcopy -inUsd ' + inFile + - ' -outUsd ' + outFile + ' ' + - ' -sourcePath ' + self._currentNodes[0].GetPath() + '; ' + - 'usdview ' + outFile + ' &') - - sys.stdout.write( "Done!\n" ) - + if inFile == outFile: + sys.stderr.write( "Cannot isolate a copy to the source usd!\n" ) + return + + sys.stdout.write( "Writing copy to new file '%s' ... " % outFile ) + sys.stdout.flush() + + os.system( 'usdcopy -inUsd ' + inFile + + ' -outUsd ' + outFile + ' ' + + ' -sourcePath ' + self._currentNodes[0].GetPath() + '; ' + + 'usdview ' + outFile + ' &') + + sys.stdout.write( "Done!\n" ) + def IsEnabled(self): - return len(self._currentNodes) == 1 and self._currentNodes[0].GetActive() + return len(self._currentNodes) == 1 and self._currentNodes[0].GetActive() # @@ -350,8 +350,8 @@ def IsEnabled(self): class IsolateAssetMenuItem(NodeContextMenuItem): def __init__(self, mainWindow, item): - NodeContextMenuItem.__init__(self, mainWindow, item) - + NodeContextMenuItem.__init__(self, mainWindow, item) + self._assetName = None if len(self._currentNodes) == 1: from pxr import Usd @@ -369,14 +369,13 @@ def __init__(self, mainWindow, item): self._filePath = layer.realPath def IsEnabled(self): - return self._assetName + return self._assetName def GetText(self): name = ( " '%s'" % self._assetName ) if self._assetName else "" return "usdview asset%s" % name - + def RunCommand(self): print "Spawning usdview %s" % self._filePath os.system("usdview %s &" % self._filePath) - diff --git a/pxr/usdImaging/lib/usdviewq/nodeViewItem.py b/pxr/usdImaging/lib/usdviewq/nodeViewItem.py index 9b1a686039..c9cc6a657c 100644 --- a/pxr/usdImaging/lib/usdviewq/nodeViewItem.py +++ b/pxr/usdImaging/lib/usdviewq/nodeViewItem.py @@ -176,8 +176,7 @@ def _nameData(self, role): elif self.isInstance: toolTip = 'Instanced ' + toolTip if self.hasArcs: - toolTip = toolTip + \ - "
Has composition arcs" + toolTip = toolTip + "
Has composition arcs" return toolTip else: return None diff --git a/pxr/usdImaging/lib/usdviewq/scalarTypes.py b/pxr/usdImaging/lib/usdviewq/scalarTypes.py index 68da6804f0..6101f3a7cb 100644 --- a/pxr/usdImaging/lib/usdviewq/scalarTypes.py +++ b/pxr/usdImaging/lib/usdviewq/scalarTypes.py @@ -22,10 +22,10 @@ # language governing permissions and limitations under the Apache License. # def GetScalarTypeFromAttr(attr): - ''' + ''' returns the (scalar, isArray) where isArray is True if it was an array type ''' - # Usd.Attribute and customAttributes.CustomAttribute have a + # Usd.Attribute and customAttributes.CustomAttribute have a # GetTypeName function, while Sdf.AttributeSpec has a typeName attr. if hasattr(attr, 'GetTypeName'): typeName = attr.GetTypeName() @@ -62,7 +62,7 @@ def ToString(v, typeName=None): # Pretty-print a bounding box if isinstance(v, Gf.BBox3d): - prettyMatrix = ("%s\n%s\n%s\n%s" % (v.matrix[0], v.matrix[1], + prettyMatrix = ("%s\n%s\n%s\n%s" % (v.matrix[0], v.matrix[1], v.matrix[2], v.matrix[3])).replace("(","").replace(")","") result = "Endpts of box diagonal:\n%s\n%s\n\nTransform matrix:\n%s\n" \ % (v.box.GetCorner(0), v.box.GetCorner(7), prettyMatrix) @@ -93,22 +93,23 @@ def ToString(v, typeName=None): # Pretty-print a TfTimeStamp elif isinstance(v, Tf.TimeStamp): from datetime import datetime - dt = datetime.fromtimestamp( v.Get() ) - result = dt.isoformat(' ') + dt = datetime.fromtimestamp( v.Get() ) + result = dt.isoformat(' ') - # pretty print an int + # pretty print an int elif isinstance(v, int): result = "{:,d}".format(v) - # pretty print a float + # pretty print a float elif isinstance(v, float): result = "{:,.6f}".format(v) # print a string as-is elif isinstance(v, str): - result = v + result = v else: + import pprint result = pprint.pformat(v) return result From 27a0875f94291748bcc6889bb4582aa80a238403 Mon Sep 17 00:00:00 2001 From: Peter Shinners Date: Sat, 20 Aug 2016 10:38:23 -0700 Subject: [PATCH 045/380] Remove unused and redundant imports from Python Several files were importing modules never used. There were also several cases of modules being imported at the top module scope and then again later inside functions. --- .../lib/usdviewq/attributeViewContextMenu.py | 3 +-- pxr/usdImaging/lib/usdviewq/customAttributes.py | 4 ---- pxr/usdImaging/lib/usdviewq/mainWindow.py | 15 ++++----------- pxr/usdImaging/lib/usdviewq/nodeContextMenu.py | 4 ++-- .../lib/usdviewq/nodeContextMenuItems.py | 5 +---- pxr/usdImaging/lib/usdviewq/prettyPrint.py | 1 - pxr/usdImaging/lib/usdviewq/scalarTypes.py | 1 - pxr/usdImaging/lib/usdviewq/stageView.py | 8 ++------ 8 files changed, 10 insertions(+), 31 deletions(-) diff --git a/pxr/usdImaging/lib/usdviewq/attributeViewContextMenu.py b/pxr/usdImaging/lib/usdviewq/attributeViewContextMenu.py index 575017c024..cf068791a2 100644 --- a/pxr/usdImaging/lib/usdviewq/attributeViewContextMenu.py +++ b/pxr/usdImaging/lib/usdviewq/attributeViewContextMenu.py @@ -21,9 +21,8 @@ # KIND, either express or implied. See the Apache License for the specific # language governing permissions and limitations under the Apache License. # -from PySide import QtGui, QtCore +from PySide import QtGui from usdviewContextMenuItem import UsdviewContextMenuItem -import os # # Specialized context menu for running commands in the attribute viewer. diff --git a/pxr/usdImaging/lib/usdviewq/customAttributes.py b/pxr/usdImaging/lib/usdviewq/customAttributes.py index 110dec03e2..af2d233d63 100644 --- a/pxr/usdImaging/lib/usdviewq/customAttributes.py +++ b/pxr/usdImaging/lib/usdviewq/customAttributes.py @@ -21,10 +21,6 @@ # KIND, either express or implied. See the Apache License for the specific # language governing permissions and limitations under the Apache License. # -from PySide import QtGui, QtCore -from pxr import Tf -from pxr import UsdGeom -from datetime import datetime # # Edit the following to alter the set of custom attributes. diff --git a/pxr/usdImaging/lib/usdviewq/mainWindow.py b/pxr/usdImaging/lib/usdviewq/mainWindow.py index fcc800c233..a77e080a0e 100644 --- a/pxr/usdImaging/lib/usdviewq/mainWindow.py +++ b/pxr/usdImaging/lib/usdviewq/mainWindow.py @@ -32,9 +32,7 @@ from customAttributes import _GetCustomAttributes from nodeViewItem import NodeViewItem from pxr import Usd, UsdGeom, UsdUtils, UsdImaging -from pxr import Gf from pxr import Glf -from pxr import Pcp from pxr import Sdf from pxr import Tf from pxr import Plug @@ -44,7 +42,7 @@ from collections import deque from collections import OrderedDict from time import time, sleep -import re, sys, os, uuid, tempfile +import re, sys, os import prettyPrint import watchWindow @@ -52,9 +50,9 @@ import referenceEditor from settings import Settings -from common import FallbackTextColor, ClampedTextColor, KeyframeTextColor,\ - DefaultTextColor, HeaderColor, RedColor, BoldFont, \ - GetAttributeColor, Timer, BusyContext, DumpMallocTags +from common import (FallbackTextColor, ClampedTextColor, KeyframeTextColor, + DefaultTextColor, HeaderColor, RedColor, BoldFont, + GetAttributeColor, Timer, BusyContext, DumpMallocTags) # Upper HUD entries (declared in variables for abstraction) PRIM = "Prims" @@ -1087,11 +1085,6 @@ def _openStage(self, usdFilePath): return None if self._mallocTags != 'none': - if self._mallocTags == 'stageAndImaging': - # we want as little python overhead showing up as possible, - # so pre-import what we'll use in a bit before initializing - from pxr import UsdImaging - from pxr import Tf Tf.MallocTag.Initialize() with Timer() as t: diff --git a/pxr/usdImaging/lib/usdviewq/nodeContextMenu.py b/pxr/usdImaging/lib/usdviewq/nodeContextMenu.py index 25661d782d..b5e5c936c6 100644 --- a/pxr/usdImaging/lib/usdviewq/nodeContextMenu.py +++ b/pxr/usdImaging/lib/usdviewq/nodeContextMenu.py @@ -21,8 +21,8 @@ # KIND, either express or implied. See the Apache License for the specific # language governing permissions and limitations under the Apache License. # -from PySide import QtGui, QtCore -from nodeContextMenuItems import NodeContextMenuItem, _GetContextMenuItems +from PySide import QtGui +from nodeContextMenuItems import _GetContextMenuItems # # Specialized context menu for node selection. diff --git a/pxr/usdImaging/lib/usdviewq/nodeContextMenuItems.py b/pxr/usdImaging/lib/usdviewq/nodeContextMenuItems.py index ccee045dab..bfb26d49ed 100644 --- a/pxr/usdImaging/lib/usdviewq/nodeContextMenuItems.py +++ b/pxr/usdImaging/lib/usdviewq/nodeContextMenuItems.py @@ -21,11 +21,8 @@ # KIND, either express or implied. See the Apache License for the specific # language governing permissions and limitations under the Apache License. # -from PySide import QtGui, QtCore -from datetime import datetime -from nodeViewItem import NodeViewItem +from PySide import QtGui from usdviewContextMenuItem import UsdviewContextMenuItem -from pxr import Tf import os import sys diff --git a/pxr/usdImaging/lib/usdviewq/prettyPrint.py b/pxr/usdImaging/lib/usdviewq/prettyPrint.py index 43fd2a1981..0f18c62883 100644 --- a/pxr/usdImaging/lib/usdviewq/prettyPrint.py +++ b/pxr/usdImaging/lib/usdviewq/prettyPrint.py @@ -26,7 +26,6 @@ arrayAttributeView ''' from PySide import QtGui -from pxr import Gf def progressDialog(title, value): dialog = QtGui.QProgressDialog(title, "Cancel", 0, value) diff --git a/pxr/usdImaging/lib/usdviewq/scalarTypes.py b/pxr/usdImaging/lib/usdviewq/scalarTypes.py index 6101f3a7cb..9494ba22ea 100644 --- a/pxr/usdImaging/lib/usdviewq/scalarTypes.py +++ b/pxr/usdImaging/lib/usdviewq/scalarTypes.py @@ -43,7 +43,6 @@ def ToString(v, typeName=None): This string is used in the watch window""" from pxr import Tf, Gf - import pprint if v is None: return 'None' diff --git a/pxr/usdImaging/lib/usdviewq/stageView.py b/pxr/usdImaging/lib/usdviewq/stageView.py index 289cf97ba8..c3283c633d 100644 --- a/pxr/usdImaging/lib/usdviewq/stageView.py +++ b/pxr/usdImaging/lib/usdviewq/stageView.py @@ -25,13 +25,9 @@ Module that provides the StageView class. ''' -import logging -import math -from math import tan, sqrt, atan, degrees -from math import radians as rad +from math import tan, atan, radians as rad import os from time import time -import traceback from PySide import QtGui, QtCore, QtOpenGL @@ -304,7 +300,7 @@ def frameSelection(self, selBBox, frameFit): else: halfFov = self.fov*0.5 or 0.5 # don't divide by zero self.dist = ((self._selSize * frameFit * 0.5) - / math.atan(math.radians(halfFov))) + / atan(rad(halfFov))) def setClosestVisibleDistFromPoint(self, point): frustum = self._camera.frustum From 2d6c4459a0518634ce67e696dd93368cf53cfa63 Mon Sep 17 00:00:00 2001 From: Peter Shinners Date: Sat, 20 Aug 2016 10:39:44 -0700 Subject: [PATCH 046/380] All Python classes use object for base class This is what configures Python to use new style classes. Several of these classes are meant as lightweight placeholders for enumerations, but it still seems consistent to derive everything from object. --- pxr/usdImaging/lib/usdviewq/common.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/pxr/usdImaging/lib/usdviewq/common.py b/pxr/usdImaging/lib/usdviewq/common.py index 1112a28758..62bb8a4a24 100644 --- a/pxr/usdImaging/lib/usdviewq/common.py +++ b/pxr/usdImaging/lib/usdviewq/common.py @@ -61,7 +61,7 @@ AbstractPrimFont = NormalFont # Keys for destinguishing items in the attribute inspector -class AttributeStatus: +class AttributeStatus(object): DEFAULT, CLAMPED, KEYFRAME, FALLBACK, NOVALUE = range(5) def PrintWarning(title, description): @@ -121,7 +121,7 @@ def GetAttributeColor(attribute, frame, hasValue=None, hasAuthoredValue=None, # Gathers information about a layer used as a subLayer, including its # position in the layerStack hierarchy. -class SubLayerInfo: +class SubLayerInfo(object): def __init__(self, sublayer, offset, containingLayer, prefix): self.layer = sublayer self.offset = offset @@ -183,7 +183,7 @@ def PrettyFormatSize(sz): return "%db" % sz -class Timer: +class Timer(object): """Use as a context object with python's "with" statement, like so: with Timer() as t: doSomeStuff() @@ -204,7 +204,7 @@ def PrintTime(self, action): print "Time to %s: %2.3fs" % (action, self.interval) -class BusyContext: +class BusyContext(object): """When used as a context object with python's "with" statement, will set Qt's busy cursor upon entry and pop it on exit. """ From 445c79364c06525cbc86e685f86b5abe1a2264c4 Mon Sep 17 00:00:00 2001 From: Peter Shinners Date: Sat, 20 Aug 2016 10:42:14 -0700 Subject: [PATCH 047/380] Fix undefined variable in mainwindow In an unlikely warning the incorrect variable was being used to format the message. --- pxr/usdImaging/lib/usdviewq/mainWindow.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pxr/usdImaging/lib/usdviewq/mainWindow.py b/pxr/usdImaging/lib/usdviewq/mainWindow.py index a77e080a0e..49dbe907b4 100644 --- a/pxr/usdImaging/lib/usdviewq/mainWindow.py +++ b/pxr/usdImaging/lib/usdviewq/mainWindow.py @@ -472,7 +472,7 @@ def __init__(self, parent, parserData): [str(a.text()) for a in self._ui.pickModeActionGroup.actions()]: print "Warning: Unknown pick mode '%s', falling back to '%s'" % ( - pickMode, + self._stageView.pickMode, str(self._ui.pickModeActionGroup.actions()[0].text())) self._ui.pickModeActionGroup.actions()[0].setChecked(True) From 916d6c66e21f003e3660568448dfb14592ab7556 Mon Sep 17 00:00:00 2001 From: Peter Shinners Date: Sat, 20 Aug 2016 10:44:58 -0700 Subject: [PATCH 048/380] Ensure Qt base class init gets called in python interpreter View The View class derived from QTextEdit was not calling the init method from the base. --- pxr/usdImaging/lib/usdviewq/pythonInterpreter.py | 1 + 1 file changed, 1 insertion(+) diff --git a/pxr/usdImaging/lib/usdviewq/pythonInterpreter.py b/pxr/usdImaging/lib/usdviewq/pythonInterpreter.py index 38402b791d..21f38285b6 100644 --- a/pxr/usdImaging/lib/usdviewq/pythonInterpreter.py +++ b/pxr/usdImaging/lib/usdviewq/pythonInterpreter.py @@ -637,6 +637,7 @@ class View(QtGui.QTextEdit): """ def __init__(self, parent=None): + QtGui.QTextEdit.__init__(self, parent) self.Parent = QtGui.QTextEdit self.Parent.__init__(self, parent) self.promptLength = 0 From 9c78ca666105e0bb0f0828b132d37f10e0aaf2f0 Mon Sep 17 00:00:00 2001 From: Peter Shinners Date: Sat, 20 Aug 2016 10:46:09 -0700 Subject: [PATCH 049/380] Fix missing import in stage view When viewing through something that is not a camera, an error message was missing the import for PrintWarning. --- pxr/usdImaging/lib/usdviewq/stageView.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pxr/usdImaging/lib/usdviewq/stageView.py b/pxr/usdImaging/lib/usdviewq/stageView.py index c3283c633d..795c27d0a3 100644 --- a/pxr/usdImaging/lib/usdviewq/stageView.py +++ b/pxr/usdImaging/lib/usdviewq/stageView.py @@ -63,8 +63,8 @@ class FreeCamera(QtCore.QObject): # is close to camera maxGoodZResolution = 5e4 - """FreeCamera can be either a Z up or Y up camera, based on 'zUp'""" def __init__(self, isZUp): + """FreeCamera can be either a Z up or Y up camera, based on 'zUp'""" super(FreeCamera, self).__init__() self._camera = Gf.Camera() @@ -1126,6 +1126,7 @@ def setCameraPrim(self, cameraPrim): self._freeCamera = None self._cameraPrim = cameraPrim else: + from common import PrintWarning PrintWarning("Incorrect Prim Type", "Attempted to view the scene using the prim '%s', but " "the prim is not a UsdGeom.Camera." %(cameraPrim.GetName())) From 6f8c6baf5e124525913dd8af699e9bcdae4a8d21 Mon Sep 17 00:00:00 2001 From: unhyperbolic Date: Tue, 30 Aug 2016 14:22:23 -0700 Subject: [PATCH 050/380] Add unit test for new GfFrustum API in a72d2ee (Internal change: 1650399) --- pxr/base/lib/gf/testenv/testGfFrustum.py | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/pxr/base/lib/gf/testenv/testGfFrustum.py b/pxr/base/lib/gf/testenv/testGfFrustum.py index c084db134a..f686efb7c8 100644 --- a/pxr/base/lib/gf/testenv/testGfFrustum.py +++ b/pxr/base/lib/gf/testenv/testGfFrustum.py @@ -379,6 +379,21 @@ def test_ConstructFromMatrix(self): self.assertEqual(len(corners), len(results)) for i in range(len(results)): self.assertTrue(Gf.IsClose(corners[i], results[i], 0.0001)) + + corners = f.ComputeCornersAtDistance(20) + for i in range(len(corners)): + self.assertTrue(Gf.IsClose(corners[i], results[i], 0.0001)) + + corners = f.ComputeCornersAtDistance(90) + for i in range(len(corners)): + self.assertTrue(Gf.IsClose(corners[i], results[i+4], 0.0001)) + + corners = f.ComputeCornersAtDistance((20 + 90) / 2.0) + for i in range(len(corners)): + self.assertTrue( + Gf.IsClose(corners[i], (results[i] + results[i+4]) / 2.0, + 0.0001)) + if __name__ == '__main__': unittest.main() From 16ec380558cb5d45799abe7a2c9cead8ec1f2848 Mon Sep 17 00:00:00 2001 From: unhyperbolic Date: Tue, 30 Aug 2016 14:25:40 -0700 Subject: [PATCH 051/380] Removing unused GfFrustum methods. (Internal change: 1650706) --- pxr/base/lib/gf/frustum.cpp | 44 ++----------------------------------- pxr/base/lib/gf/frustum.h | 40 --------------------------------- 2 files changed, 2 insertions(+), 82 deletions(-) diff --git a/pxr/base/lib/gf/frustum.cpp b/pxr/base/lib/gf/frustum.cpp index 550a51c278..3de7531982 100644 --- a/pxr/base/lib/gf/frustum.cpp +++ b/pxr/base/lib/gf/frustum.cpp @@ -58,7 +58,6 @@ GfFrustum::GfFrustum() : _projectionType(GfFrustum::Perspective) { _rotation.SetIdentity(); - _localToFrustum.SetIdentity(); } GfFrustum::GfFrustum(const GfVec3d &position, const GfRotation &rotation, @@ -70,8 +69,7 @@ GfFrustum::GfFrustum(const GfVec3d &position, const GfRotation &rotation, _window(window), _nearFar(nearFar), _viewDistance(viewDistance), - _projectionType(projectionType), - _localToFrustum(1.0) + _projectionType(projectionType) { } @@ -82,8 +80,7 @@ GfFrustum::GfFrustum(const GfMatrix4d &camToWorldXf, _window(window), _nearFar(nearFar), _viewDistance(viewDistance), - _projectionType(projectionType), - _localToFrustum(1.0) + _projectionType(projectionType) { SetPositionAndRotationFromMatrix(camToWorldXf); } @@ -1092,43 +1089,6 @@ GfFrustum::Intersects(const GfVec3d &p0, return false; } -//---------------------------------------------------------------------- -// Local space intersection routines. -// -// These routines are the most efficient way to intersect geometry with -// the frustum. -// -// For now, they consist simply of transforming the point into whatever -// space the frustum is in (as set in GfFrustum::SetTransform). In the -// future these routines can be made about twice as fast by replacing -// _localToFrustum with a matrix that carries the point into the space -// of the "normalized frustum". The normalized frustum has all its vertices -// at with coordinates that are 0, 1, or -1. -// -bool -GfFrustum::IntersectsInLocalSpace(const GfVec3d &p1) const -{ - GfVec3d frustumP1 = _localToFrustum.Transform(p1); - return Intersects( frustumP1); -} - -bool -GfFrustum::IntersectsInLocalSpace(const GfVec3d &p1, const GfVec3d &p2) const -{ - GfVec3d frustumP1 = _localToFrustum.Transform(p1); - GfVec3d frustumP2 = _localToFrustum.Transform(p2); - return Intersects( frustumP1, frustumP2); -} - -bool -GfFrustum::IntersectsInLocalSpace(const GfVec3d &p1, const GfVec3d &p2, const GfVec3d &p3) const -{ - GfVec3d frustumP1 = _localToFrustum.Transform(p1); - GfVec3d frustumP2 = _localToFrustum.Transform(p2); - GfVec3d frustumP3 = _localToFrustum.Transform(p3); - return Intersects( frustumP1, frustumP2, frustumP3); -} - void GfFrustum::_DirtyFrustumPlanes() { diff --git a/pxr/base/lib/gf/frustum.h b/pxr/base/lib/gf/frustum.h index 4f61645819..3638fa4b5b 100644 --- a/pxr/base/lib/gf/frustum.h +++ b/pxr/base/lib/gf/frustum.h @@ -507,26 +507,6 @@ class GfFrustum { /// ///@{ - /// Describes the space in which the geometry is represented. Used only in - /// conjuction with GfFrustum::IntersectsInLocalSpace. The matrix is - /// carries the space of the geometry into the space of the frustum. - /// - /// The IntersectsInLocalSpace routines are the most efficient way to - /// intersect geometry with an arbitrary frustum. - /// - /// Note: There currently isn't a local space intersection routine for - /// bboxes, but if the need arises there is no difficulty in principle to - /// adding it. - /// - void SetLocalSpaceForIntersection( const GfMatrix4d &localToFrustum) { - _localToFrustum = localToFrustum; - } - - /// Returns the matrix set by \c SetLocalSpaceForIntersection(). - GfMatrix4d const& GetLocalSpaceForIntersection() const { - return _localToFrustum; - } - /// Returns true if the given axis-aligned bbox is inside or intersecting /// the frustum. Otherwise, it returns false. Useful when doing picking or /// frustum culling. @@ -536,37 +516,17 @@ class GfFrustum { /// Otherwise, it returns false. bool Intersects(const GfVec3d &point) const; - /// Returns true if the given point is inside or intersecting the frustum. - /// Otherwise, it returns false. The point is in its local space, as - /// described by a call to GfFrustum::SetLocalSpace. - bool IntersectsInLocalSpace(const GfVec3d &point) const; - /// Returns \c true if the line segment formed by the given points is /// inside or intersecting the frustum. Otherwise, it returns false. bool Intersects(const GfVec3d &p0, const GfVec3d &p1) const; - /// Returns \c true if the line segment formed by the given points is - /// inside or intersecting the frustum. Otherwise, it returns false. The - /// endpoints of the line are in local space, as described by a call to - /// GfFrustum::SetLocalSpace. - bool IntersectsInLocalSpace(const GfVec3d &p0, - const GfVec3d &p1) const; - /// Returns \c true if the triangle formed by the given points is inside /// or intersecting the frustum. Otherwise, it returns false. bool Intersects(const GfVec3d &p0, const GfVec3d &p1, const GfVec3d &p2) const; - /// Returns \c true if the triangle formed by the given points is inside - /// or intersecting the frustum. Otherwise, it returns false. The - /// vertices of the triangle are in local space, as described by a call to - /// GfFrustum::SetLocalSpace. - bool IntersectsInLocalSpace(const GfVec3d &p0, - const GfVec3d &p1, - const GfVec3d &p2) const; - /// Returns \c true if the bbox volume intersects the view volume given by /// the view-projection matrix, erring on the side of false positives for /// efficiency. From 81947bd2312c76ab028afefdf55d3f3b6a5e4fa1 Mon Sep 17 00:00:00 2001 From: unhyperbolic Date: Tue, 30 Aug 2016 14:26:27 -0700 Subject: [PATCH 052/380] Remove unused GfFrustum member variable (Internal change: 1650837) --- pxr/base/lib/gf/frustum.h | 3 --- 1 file changed, 3 deletions(-) diff --git a/pxr/base/lib/gf/frustum.h b/pxr/base/lib/gf/frustum.h index 3638fa4b5b..9b33d1a27f 100644 --- a/pxr/base/lib/gf/frustum.h +++ b/pxr/base/lib/gf/frustum.h @@ -595,9 +595,6 @@ class GfFrustum { // Projection type. ProjectionType _projectionType; - // For efficient intersection in local space - GfMatrix4d _localToFrustum; - // Cached planes. // If empty, the planes have not been calculated. mutable std::vector _planes; From ee43e6e434b68ee02b6e0de98db8681b2fc61367 Mon Sep 17 00:00:00 2001 From: c64kernal Date: Tue, 30 Aug 2016 14:27:53 -0700 Subject: [PATCH 053/380] Windows requires CMake version 3.1.1 and boost 1.61, update the docs. (Internal change: 1650842) --- CMakeLists.txt | 7 ++++++- README.md | 4 ++-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index c3c97ddcc1..9093d74910 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,10 @@ project(usd) -cmake_minimum_required(VERSION 2.8.8) + +if (WIN32) + cmake_minimum_required(VERSION 3.1.1) +else() + cmake_minimum_required(VERSION 2.8.8) +endif() set(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake/defaults ${CMAKE_SOURCE_DIR}/cmake/modules diff --git a/README.md b/README.md index 26326c2ee8..7a31cfecf3 100644 --- a/README.md +++ b/README.md @@ -42,9 +42,9 @@ Dependencies | ---- | --------- | | C++ compiler | GCC 4.8, Clang 3.5, MSVC 14.0(VS 2015) | | C compiler | GCC 4.8, Clang 3.5, MSVC 14.0(VS 2015) | -| [CMake](https://cmake.org/documentation/) | 2.8.8 | +| [CMake](https://cmake.org/documentation/) | 2.8.8 (Linux/OS X), 3.1.1 (Windows) | | [Python](https://python.org) | 2.7.5 | -| [Boost](https://boost.org) | 1.55 | +| [Boost](https://boost.org) | 1.55 (Linux/OS X), 1.61.0 (Windows) | | [OpenEXR](https://openexr.org) | 2.2.0 | | [DoubleConversion](https://github.com/google/double-conversion) | 1.1.1 | | [Intel TBB](https://www.threadingbuildingblocks.org/) | 4.3.1 | From a036a9617219d31dffb3f942bc124ffd57d49c2f Mon Sep 17 00:00:00 2001 From: blevin Date: Tue, 30 Aug 2016 14:28:28 -0700 Subject: [PATCH 054/380] Pcp: Remove TF_VERIFY added in change 1650665. Closer analysis reveals that it's totally valid to not have a spec w/ relocate in every layer (duh) and we should just skip layers without relocating specs here. (Internal change: 1650844) --- pxr/usd/lib/pcp/cache.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/pxr/usd/lib/pcp/cache.cpp b/pxr/usd/lib/pcp/cache.cpp index 360312f07b..fc98b98436 100644 --- a/pxr/usd/lib/pcp/cache.cpp +++ b/pxr/usd/lib/pcp/cache.cpp @@ -1320,7 +1320,11 @@ _AddRelocateEditsForLayerStack( TF_FOR_ALL(pathIt, relocatePrimPaths) { TF_FOR_ALL(layerIt, layerStack->GetLayers()) { const SdfPrimSpecHandle prim = (*layerIt)->GetPrimAtPath(*pathIt); - if (not TF_VERIFY(prim) or not prim->HasRelocates()) { + // The relocate we discovered in the layerStack at this path + // doesn't necessarily mean there is a spec with a relocate + // in every layer. Skip layers that don't have a spec with + // a relocate. + if (not prim or not prim->HasRelocates()) { continue; } From 8a42b51e4d4658a20814a76dead0070c603b4d5e Mon Sep 17 00:00:00 2001 From: takahito-tejima Date: Tue, 30 Aug 2016 14:29:43 -0700 Subject: [PATCH 055/380] [UsdImaging, usdviewq] add memory stat display extends usdview's HUD->GPU stats to show GPU memory allocation. (Internal change: 1650845) --- pxr/usdImaging/lib/usdImaging/engine.cpp | 8 ++++++++ pxr/usdImaging/lib/usdImaging/engine.h | 4 ++++ pxr/usdImaging/lib/usdImaging/gl.cpp | 24 ++++++++++++++++++++++ pxr/usdImaging/lib/usdImaging/gl.h | 2 ++ pxr/usdImaging/lib/usdImaging/hdEngine.cpp | 8 ++++++++ pxr/usdImaging/lib/usdImaging/hdEngine.h | 2 ++ pxr/usdImaging/lib/usdImaging/wrapGL.cpp | 1 + pxr/usdImaging/lib/usdviewq/stageView.py | 23 ++++++++++++++++++--- 8 files changed, 69 insertions(+), 3 deletions(-) diff --git a/pxr/usdImaging/lib/usdImaging/engine.cpp b/pxr/usdImaging/lib/usdImaging/engine.cpp index 28b8841e45..9a7add9742 100644 --- a/pxr/usdImaging/lib/usdImaging/engine.cpp +++ b/pxr/usdImaging/lib/usdImaging/engine.cpp @@ -644,3 +644,11 @@ UsdImagingEngine::SetRenderGraphPlugin(TfType const &type) { return false; } + +/* virtual */ +VtDictionary +UsdImagingEngine::GetResourceAllocation() const +{ + return VtDictionary(); +} + diff --git a/pxr/usdImaging/lib/usdImaging/engine.h b/pxr/usdImaging/lib/usdImaging/engine.h index bb0d658814..11bfa15b94 100644 --- a/pxr/usdImaging/lib/usdImaging/engine.h +++ b/pxr/usdImaging/lib/usdImaging/engine.h @@ -34,6 +34,7 @@ #include "pxr/base/gf/matrix4d.h" #include "pxr/base/gf/vec4d.h" #include "pxr/base/gf/vec4i.h" +#include "pxr/base/vt/dictionary.h" #include #include @@ -296,6 +297,9 @@ class UsdImagingEngine : private boost::noncopyable { /// the plugin for the type will be loaded if not yet. virtual bool SetRenderGraphPlugin(TfType const &type); + /// Returns GPU resource allocation info + virtual VtDictionary GetResourceAllocation() const; + protected: // Intentionally putting these under protected so that subclasses can share the usage of draw targets. // Once refEngine goes away and we only have hdEngine, it may be best to move this to private diff --git a/pxr/usdImaging/lib/usdImaging/gl.cpp b/pxr/usdImaging/lib/usdImaging/gl.cpp index 9befcd1ced..e5f7b0f189 100644 --- a/pxr/usdImaging/lib/usdImaging/gl.cpp +++ b/pxr/usdImaging/lib/usdImaging/gl.cpp @@ -33,6 +33,7 @@ #include "pxr/base/tf/diagnostic.h" #include "pxr/imaging/glf/glContext.h" +#include "pxr/imaging/glf/textureRegistry.h" #include @@ -313,3 +314,26 @@ UsdImagingGL::TestIntersectionBatch( worldToLocalSpace, paths, params, pickResolution, pathTranslator, outHit); } + +/* virtual */ +VtDictionary +UsdImagingGL::GetResourceAllocation() const +{ + VtDictionary dict; + dict = _engine->GetResourceAllocation(); + + // append texture usage + size_t texMem = 0; + for (auto const &texInfo : + GlfTextureRegistry::GetInstance().GetTextureInfos()) { + VtDictionary::const_iterator it = texInfo.find("memoryUsed"); + if (it != texInfo.end()) { + VtValue mem = it->second; + if (mem.IsHolding()) { + texMem += mem.Get(); + } + } + } + dict["textureMemoryUsed"] = texMem; + return dict; +} diff --git a/pxr/usdImaging/lib/usdImaging/gl.h b/pxr/usdImaging/lib/usdImaging/gl.h index 88c2debf6a..c61d7f48d9 100644 --- a/pxr/usdImaging/lib/usdImaging/gl.h +++ b/pxr/usdImaging/lib/usdImaging/gl.h @@ -162,6 +162,8 @@ class UsdImagingGL : public UsdImagingEngine { std::function< SdfPath(const SdfPath&) > pathTranslator, HitBatch *outHit); + virtual VtDictionary GetResourceAllocation() const; + private: UsdImagingEngineSharedPtr _engine; }; diff --git a/pxr/usdImaging/lib/usdImaging/hdEngine.cpp b/pxr/usdImaging/lib/usdImaging/hdEngine.cpp index e46ece46a6..6204853778 100644 --- a/pxr/usdImaging/lib/usdImaging/hdEngine.cpp +++ b/pxr/usdImaging/lib/usdImaging/hdEngine.cpp @@ -30,6 +30,7 @@ #include "pxr/imaging/hd/version.h" #include "pxr/imaging/hd/tokens.h" #include "pxr/imaging/hd/renderContextCaps.h" +#include "pxr/imaging/hd/resourceRegistry.h" #include "pxr/imaging/hd/debugCodes.h" #include "pxr/imaging/hdx/intersector.h" @@ -765,3 +766,10 @@ UsdImagingHdEngine::SetRenderGraphPlugin(TfType const &type) return true; } + +/* virtual */ +VtDictionary +UsdImagingHdEngine::GetResourceAllocation() const +{ + return HdResourceRegistry::GetInstance().GetResourceAllocation(); +} diff --git a/pxr/usdImaging/lib/usdImaging/hdEngine.h b/pxr/usdImaging/lib/usdImaging/hdEngine.h index e2acfebe45..363067e591 100644 --- a/pxr/usdImaging/lib/usdImaging/hdEngine.h +++ b/pxr/usdImaging/lib/usdImaging/hdEngine.h @@ -131,6 +131,8 @@ class UsdImagingHdEngine : public UsdImagingEngine std::function< SdfPath(const SdfPath&) > pathTranslator, HitBatch *outHit); + virtual VtDictionary GetResourceAllocation() const; + private: // Helper functions for preparing multiple engines for // batched drawing. diff --git a/pxr/usdImaging/lib/usdImaging/wrapGL.cpp b/pxr/usdImaging/lib/usdImaging/wrapGL.cpp index bc5a42155d..012e83f4ad 100644 --- a/pxr/usdImaging/lib/usdImaging/wrapGL.cpp +++ b/pxr/usdImaging/lib/usdImaging/wrapGL.cpp @@ -104,6 +104,7 @@ void wrapGL() .def("GetRenderGraphPlugins", &UsdImagingGL::GetRenderGraphPlugins, return_value_policy< TfPySequenceToTuple >()) .def("SetRenderGraphPlugin", &UsdImagingGL::SetRenderGraphPlugin) + .def("GetResourceAllocation", &UsdImagingGL::GetResourceAllocation) ; // Wrap the constants. diff --git a/pxr/usdImaging/lib/usdviewq/stageView.py b/pxr/usdImaging/lib/usdviewq/stageView.py index 795c27d0a3..2f7f9752a4 100644 --- a/pxr/usdImaging/lib/usdviewq/stageView.py +++ b/pxr/usdImaging/lib/usdviewq/stageView.py @@ -1554,9 +1554,26 @@ def paintGL(self): self.fpsHUDKeys) # GPU stats (TimeElapsed is in nano seconds) if self.showHUD_GPUstats: - toPrint = { "GL prims" : self._glPrimitiveGeneratedQuery.GetResult(), - "GPU time" : "%.2f ms " % (self._glTimeElapsedQuery.GetResult() / 1000000.0) } - self.printDict(-10, self.height()-60, col, toPrint) + allocInfo = self._renderer.GetResourceAllocation() + gpuMemTotal = 0 + texMem = 0 + if "gpuMemoryUsed" in allocInfo: + gpuMemTotal = allocInfo["gpuMemoryUsed"] + if "textureMemoryUsed" in allocInfo: + texMem = allocInfo["textureMemoryUsed"] + gpuMemTotal += texMem + + from collections import OrderedDict + toPrint = OrderedDict() + toPrint["GL prims "] = self._glPrimitiveGeneratedQuery.GetResult() + toPrint["GPU time "] = "%.2f ms " % (self._glTimeElapsedQuery.GetResult() / 1000000.0) + toPrint["GPU mem "] = gpuMemTotal + toPrint[" primvar "] = allocInfo["primVar"] if "primVar" in allocInfo else "N/A" + toPrint[" topology"] = allocInfo["topology"] if "topology" in allocInfo else "N/A" + toPrint[" shader "] = allocInfo["drawingShader"] if "drawingShader" in allocInfo else "N/A" + toPrint[" texture "] = texMem + + self.printDict(-10, self.height()-30-(15*len(toPrint)), col, toPrint, toPrint.keys()) GL.glPopMatrix() From 225b9e8de5fea330da031e60002b05e22a9911ce Mon Sep 17 00:00:00 2001 From: takahito-tejima Date: Tue, 30 Aug 2016 14:31:02 -0700 Subject: [PATCH 056/380] [Hd, Hdx] refactor drawTarget API this change is the first iteration of refactoring hd drawtarget API. - make HdDrawTargetRenderPass not a HdTask - remove simpleLightingShader dependency from Hd - remove HdRenderPassState from HdDrawTargetRenderPass - HdxDrawTargetTask manages HdRenderPassState and HdSimpleLightingShader along with HdDrawTargetRenderPass. (Internal change: 1650907) --- pxr/imaging/lib/hd/drawTargetRenderPass.cpp | 75 ++------------------ pxr/imaging/lib/hd/drawTargetRenderPass.h | 22 ++---- pxr/imaging/lib/hdx/drawTargetTask.cpp | 77 +++++++++++++++++++-- pxr/imaging/lib/hdx/drawTargetTask.h | 3 + 4 files changed, 84 insertions(+), 93 deletions(-) diff --git a/pxr/imaging/lib/hd/drawTargetRenderPass.cpp b/pxr/imaging/lib/hd/drawTargetRenderPass.cpp index ac20ca62fa..208b4f5809 100644 --- a/pxr/imaging/lib/hd/drawTargetRenderPass.cpp +++ b/pxr/imaging/lib/hd/drawTargetRenderPass.cpp @@ -26,7 +26,6 @@ #include "pxr/imaging/hd/drawTargetRenderPass.h" #include "pxr/imaging/hd/drawTargetRenderPassState.h" -#include "pxr/imaging/hd/camera.h" #include "pxr/imaging/hd/renderPassState.h" static @@ -58,13 +57,9 @@ _ClearBuffer(GLenum buffer, GLint drawBuffer, const VtValue &value) HdDrawTargetRenderPass::HdDrawTargetRenderPass(HdRenderIndex *index) : _renderPass(index) - , _renderPassState(new HdRenderPassState()) , _drawTargetRenderPassState(nullptr) , _drawTarget() , _drawTargetContext() - , _simpleLightingShader(new HdSimpleLightingShader()) - , _viewMatrix(1) - , _projectionMatrix(1) , _collectionObjectVersion(0) { } @@ -84,7 +79,6 @@ HdDrawTargetRenderPass::SetDrawTarget(const GlfDrawTargetRefPtr &drawTarget) } - void HdDrawTargetRenderPass::SetRenderPassState( HdDrawTargetRenderPassState *drawTargetRenderPassState) @@ -92,8 +86,6 @@ HdDrawTargetRenderPass::SetRenderPassState( _drawTargetRenderPassState = drawTargetRenderPassState; } - - void HdDrawTargetRenderPass::SetRprimCollection(HdRprimCollection const& col) { @@ -101,45 +93,12 @@ HdDrawTargetRenderPass::SetRprimCollection(HdRprimCollection const& col) } void -HdDrawTargetRenderPass::_Sync(HdTaskContext* ctx) +HdDrawTargetRenderPass::Sync() { - static const GfMatrix4d yflip = GfMatrix4d().SetScale( - GfVec3d(1.0, -1.0, 1.0)); - - const SdfPath &cameraId = _drawTargetRenderPassState->GetCamera(); - - // XXX: Need to detect when camera changes and only update if - // needed - HdCameraSharedPtr camera - = _renderPass.GetRenderIndex()->GetCamera(cameraId); - - if (!camera) { - // Render pass should not have been added to task list. - TF_CODING_ERROR("Invalid camera for render pass: %s", - cameraId.GetText()); - return; - } - - VtValue viewMatrixVt = camera->Get(HdShaderTokens->worldToViewMatrix); - VtValue projMatrixVt = camera->Get(HdShaderTokens->projectionMatrix); - _viewMatrix = viewMatrixVt.Get(); - const GfMatrix4d &projMatrix = projMatrixVt.Get(); - _projectionMatrix = projMatrix * yflip; - - GfVec2i const &resolution = _drawTarget->GetSize(); - GfVec4d viewport(0, 0, resolution[0], resolution[1]); - - _renderPassState->SetCamera(_viewMatrix, _projectionMatrix, viewport); - - // Update the internal lighting context so it knows about the new camera - // position. - GlfSimpleLightingContextRefPtr lightingContext; - _GetTaskContextData(ctx, HdTokens->lightingContext, &lightingContext); - _UpdateLightingContext(lightingContext); - // Update the collection object if necessary. unsigned int newCollectionVersion = - _drawTargetRenderPassState->GetRprimCollectionVersion(); + _drawTargetRenderPassState->GetRprimCollectionVersion(); + if (_collectionObjectVersion != newCollectionVersion) { SetRprimCollection(_drawTargetRenderPassState->GetRprimCollection()); @@ -152,11 +111,11 @@ HdDrawTargetRenderPass::_Sync(HdTaskContext* ctx) } _renderPass.Sync(); - _renderPassState->Sync(); } void -HdDrawTargetRenderPass::_Execute(HdTaskContext* ctx) +HdDrawTargetRenderPass::Execute( + HdRenderPassStateSharedPtr const &renderPassState) { if (!_drawTarget) { return; @@ -173,7 +132,7 @@ HdDrawTargetRenderPass::_Execute(HdTaskContext* ctx) glViewport(0, 0, resolution[0], resolution[1]); // Perform actual draw - _renderPass.Execute(_renderPassState); + _renderPass.Execute(renderPassState); glPopAttrib(); @@ -197,25 +156,3 @@ HdDrawTargetRenderPass::_ClearBuffers() _ClearBuffer(GL_COLOR, attachmentNum, clearColor); } } - -void -HdDrawTargetRenderPass::_UpdateLightingContext(GlfSimpleLightingContextRefPtr &lightingContext) -{ - GlfSimpleLightingContextRefPtr const& simpleLightingContext = - _simpleLightingShader->GetLightingContext(); - - if (lightingContext) { - simpleLightingContext->SetUseLighting( - lightingContext->GetUseLighting()); - simpleLightingContext->SetLights(lightingContext->GetLights()); - simpleLightingContext->SetMaterial(lightingContext->GetMaterial()); - simpleLightingContext->SetSceneAmbient( - lightingContext->GetSceneAmbient()); - simpleLightingContext->SetShadows(lightingContext->GetShadows()); - simpleLightingContext->SetUseColorMaterialDiffuse( - lightingContext->GetUseColorMaterialDiffuse()); - } - - simpleLightingContext->SetCamera(_viewMatrix, _projectionMatrix); - _renderPassState->SetLightingShader(_simpleLightingShader); -} diff --git a/pxr/imaging/lib/hd/drawTargetRenderPass.h b/pxr/imaging/lib/hd/drawTargetRenderPass.h index 1807a6e93f..6a831e2e19 100644 --- a/pxr/imaging/lib/hd/drawTargetRenderPass.h +++ b/pxr/imaging/lib/hd/drawTargetRenderPass.h @@ -26,7 +26,6 @@ #include "pxr/imaging/hd/renderPass.h" #include "pxr/imaging/hd/rprimCollection.h" -#include "pxr/imaging/hd/simpleLightingShader.h" #include "pxr/imaging/glf/drawTarget.h" @@ -44,7 +43,7 @@ class HdDrawTargetRenderPassState; /// to major changes. It is likely this functionality will be absorbed into /// the base class. /// -class HdDrawTargetRenderPass : public HdTask { +class HdDrawTargetRenderPass : boost::noncopyable { public: HdDrawTargetRenderPass(HdRenderIndex *index); virtual ~HdDrawTargetRenderPass(); @@ -59,21 +58,15 @@ class HdDrawTargetRenderPass : public HdTask { void SetRprimCollection(HdRprimCollection const& col); - HdRenderPassStateSharedPtr const &GetRenderPassState() const { - return _renderPassState; - } - -protected: /// Execute render pass task - virtual void _Sync(HdTaskContext* ctx) override; + void Sync(); /// Sync the render pass resources - virtual void _Execute(HdTaskContext* ctx) override; + void Execute(HdRenderPassStateSharedPtr const &renderPassState); private: - /// RenderPass and state + /// RenderPass HdRenderPass _renderPass; - HdRenderPassStateSharedPtr _renderPassState; /// drawtarget renderPass state HdDrawTargetRenderPassState *_drawTargetRenderPassState; @@ -84,15 +77,8 @@ class HdDrawTargetRenderPass : public HdTask { /// The context which owns the draw target object. GlfGLContextSharedPtr _drawTargetContext; - HdSimpleLightingShaderSharedPtr _simpleLightingShader; - GfMatrix4d _viewMatrix; - GfMatrix4d _projectionMatrix; - unsigned int _collectionObjectVersion; - /// Prepares the lighting context for this specific draw target pass - void _UpdateLightingContext(GlfSimpleLightingContextRefPtr &lightingContext); - /// Clear all color and depth buffers. void _ClearBuffers(); diff --git a/pxr/imaging/lib/hdx/drawTargetTask.cpp b/pxr/imaging/lib/hdx/drawTargetTask.cpp index 42ce82b9f7..40c7e3eae1 100644 --- a/pxr/imaging/lib/hdx/drawTargetTask.cpp +++ b/pxr/imaging/lib/hdx/drawTargetTask.cpp @@ -27,9 +27,11 @@ #include "pxr/imaging/hdx/tokens.h" #include "pxr/imaging/hdx/debugCodes.h" +#include "pxr/imaging/hd/camera.h" #include "pxr/imaging/hd/drawTarget.h" #include "pxr/imaging/hd/drawTargetRenderPass.h" #include "pxr/imaging/hd/renderPassState.h" +#include "pxr/imaging/hd/simpleLightingShader.h" #include "pxr/imaging/glf/drawTarget.h" @@ -124,9 +126,14 @@ HdxDrawTargetTask::_Sync(HdTaskContext* ctx) pass->SetDrawTarget(drawTarget->GetGlfDrawTarget()); pass->SetRenderPassState(drawTarget->GetRenderPassState()); + HdRenderPassStateSharedPtr renderPassState(new HdRenderPassState()); + HdSimpleLightingShaderSharedPtr simpleLightingShader(new HdSimpleLightingShader()); + _renderPasses.emplace_back( RenderPassInfo { std::move(pass), + renderPassState, + simpleLightingShader, drawTarget, drawTarget->GetVersion() }); @@ -154,16 +161,48 @@ HdxDrawTargetTask::_Sync(HdTaskContext* ctx) } } + ///---------------------- + static const GfMatrix4d yflip = GfMatrix4d().SetScale( + GfVec3d(1.0, -1.0, 1.0)); + + // lighting context + GlfSimpleLightingContextRefPtr lightingContext; + _GetTaskContextData(ctx, HdTokens->lightingContext, &lightingContext); + size_t numRenderPasses = _renderPasses.size(); for (size_t renderPassIdx = 0; renderPassIdx < numRenderPasses; ++renderPassIdx) { - HdDrawTargetRenderPass *renderPass = _renderPasses[renderPassIdx].pass.get(); - HdRenderPassStateSharedPtr renderPassState = renderPass->GetRenderPassState(); + RenderPassInfo &renderPassInfo = _renderPasses[renderPassIdx]; + HdDrawTargetRenderPass *renderPass = renderPassInfo.pass.get(); + HdRenderPassStateSharedPtr &renderPassState = renderPassInfo.renderPassState; + HdDrawTargetSharedPtr drawTarget = renderPassInfo.target.lock(); + + const SdfPath &cameraId = drawTarget->GetRenderPassState()->GetCamera(); + + // XXX: Need to detect when camera changes and only update if + // needed + HdCameraSharedPtr camera + = GetDelegate()->GetRenderIndex().GetCamera(cameraId); + + if (!camera) { + // Render pass should not have been added to task list. + TF_CODING_ERROR("Invalid camera for render pass: %s", + cameraId.GetText()); + return; + } + + VtValue viewMatrixVt = camera->Get(HdShaderTokens->worldToViewMatrix); + VtValue projMatrixVt = camera->Get(HdShaderTokens->projectionMatrix); + GfMatrix4d viewMatrix = viewMatrixVt.Get(); + const GfMatrix4d &projMatrix = projMatrixVt.Get(); + GfMatrix4d projectionMatrix = projMatrix * yflip; + + GfVec2i const &resolution = drawTarget->GetGlfDrawTarget()->GetSize(); + GfVec4d viewport(0, 0, resolution[0], resolution[1]); // Update Raster States - // XXX: Share raster state between render passes? renderPassState->SetOverrideColor(_overrideColor); renderPassState->SetWireframeColor(_wireframeColor); renderPassState->SetLightingEnabled(_enableLighting); @@ -172,7 +211,30 @@ HdxDrawTargetTask::_Sync(HdTaskContext* ctx) renderPassState->SetDrawingRange(_drawingRange); renderPassState->SetCullStyle(_cullStyle); - renderPass->Sync(ctx); + HdSimpleLightingShaderSharedPtr &simpleLightingShader + = _renderPasses[renderPassIdx].simpleLightingShader; + GlfSimpleLightingContextRefPtr const& simpleLightingContext = + simpleLightingShader->GetLightingContext(); + + renderPassState->SetLightingShader(simpleLightingShader); + + renderPassState->SetCamera(viewMatrix, projectionMatrix, viewport); + simpleLightingContext->SetCamera(viewMatrix, projectionMatrix); + + if (lightingContext) { + simpleLightingContext->SetUseLighting( + lightingContext->GetUseLighting()); + simpleLightingContext->SetLights(lightingContext->GetLights()); + simpleLightingContext->SetMaterial(lightingContext->GetMaterial()); + simpleLightingContext->SetSceneAmbient( + lightingContext->GetSceneAmbient()); + simpleLightingContext->SetShadows(lightingContext->GetShadows()); + simpleLightingContext->SetUseColorMaterialDiffuse( + lightingContext->GetUseColorMaterialDiffuse()); + } + + renderPassState->Sync(); + renderPass->Sync(); } } @@ -230,8 +292,11 @@ HdxDrawTargetTask::_Execute(HdTaskContext* ctx) renderPassIdx < numRenderPasses; ++renderPassIdx) { - HdDrawTargetRenderPass *renderPass = _renderPasses[renderPassIdx].pass.get(); - renderPass->Execute(ctx); + HdDrawTargetRenderPass *renderPass = + _renderPasses[renderPassIdx].pass.get(); + HdRenderPassStateSharedPtr renderPassState = + _renderPasses[renderPassIdx].renderPassState; + renderPass->Execute(renderPassState); } if (oldAlphaToCoverage) { diff --git a/pxr/imaging/lib/hdx/drawTargetTask.h b/pxr/imaging/lib/hdx/drawTargetTask.h index 78bc001c7b..084050f59e 100644 --- a/pxr/imaging/lib/hdx/drawTargetTask.h +++ b/pxr/imaging/lib/hdx/drawTargetTask.h @@ -27,6 +27,7 @@ #include "pxr/imaging/hdx/version.h" #include "pxr/imaging/hd/task.h" #include "pxr/imaging/hd/drawTargetRenderPass.h" +#include "pxr/imaging/hd/simpleLightingShader.h" #include "pxr/base/gf/vec2f.h" #include "pxr/base/gf/vec4f.h" @@ -55,6 +56,8 @@ class HdxDrawTargetTask : public HdSceneTask { struct RenderPassInfo { HdDrawTargetRenderPassUniquePtr pass; + HdRenderPassStateSharedPtr renderPassState; + HdSimpleLightingShaderSharedPtr simpleLightingShader; HdDrawTargetWeakPtr target; unsigned int version; }; From fb7dc14934f0dbd7028f44cce9fa6bd4889c78b6 Mon Sep 17 00:00:00 2001 From: gitamohr Date: Tue, 30 Aug 2016 14:31:39 -0700 Subject: [PATCH 057/380] usdGeom: Ensure we drop the GIL in UsdGeomBBoxCache::_Resolve before spawning parallel work. The parallel work might invoke plugin code that needs the GIL. (Internal change: 1650916) --- pxr/usd/lib/usdGeom/bboxCache.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/pxr/usd/lib/usdGeom/bboxCache.cpp b/pxr/usd/lib/usdGeom/bboxCache.cpp index fc5a390cc3..68cc9a0c59 100644 --- a/pxr/usd/lib/usdGeom/bboxCache.cpp +++ b/pxr/usd/lib/usdGeom/bboxCache.cpp @@ -36,6 +36,7 @@ #include "pxr/usd/usd/treeIterator.h" #include "pxr/base/tracelite/trace.h" +#include "pxr/base/tf/pyLock.h" #include "pxr/base/tf/token.h" #include @@ -773,6 +774,11 @@ UsdGeomBBoxCache::_Resolve( TRACE_FUNCTION(); // NOTE: Bounds are cached in local space, but computed in world space. + // Drop the GIL here if we have it before we spawn parallel tasks, since + // resolving properties on prims in worker threads may invoke plugin code + // that needs the GIL. + TF_PY_ALLOW_THREADS_IN_SCOPE(); + // If the bound is in the cache, return it. std::vector masterPrims; _Entry* entry = _FindOrCreateEntriesForPrim(prim, &masterPrims); From e5d204aa57e99bfe8d68181f67d4f58f0c9e9d71 Mon Sep 17 00:00:00 2001 From: gitamohr Date: Tue, 30 Aug 2016 14:31:51 -0700 Subject: [PATCH 058/380] usd: Apply memory order to Usd_PrimData reference counting. (Internal change: 1650977) --- pxr/usd/lib/usd/primData.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pxr/usd/lib/usd/primData.h b/pxr/usd/lib/usd/primData.h index cc4a55d7cf..00fa930ae6 100644 --- a/pxr/usd/lib/usd/primData.h +++ b/pxr/usd/lib/usd/primData.h @@ -301,10 +301,10 @@ class Usd_PrimData mutable std::atomic_int _refCount; friend void intrusive_ptr_add_ref(const Usd_PrimData *prim) { - ++prim->_refCount; + prim->_refCount.fetch_add(1, std::memory_order_relaxed); } friend void intrusive_ptr_release(const Usd_PrimData *prim) { - if (--prim->_refCount == 0) + if (prim->_refCount.fetch_sub(1, std::memory_order_release) == 1) delete prim; } From 3c0d89715da04feb483e766bf192572f1fa2b25f Mon Sep 17 00:00:00 2001 From: gitamohr Date: Tue, 30 Aug 2016 14:31:56 -0700 Subject: [PATCH 059/380] pcp: Move TRACE_FUNCTION past early return. (Internal change: 1650978) --- pxr/usd/lib/pcp/primIndex_Graph.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pxr/usd/lib/pcp/primIndex_Graph.cpp b/pxr/usd/lib/pcp/primIndex_Graph.cpp index eeee8ed1a4..62eaf8f067 100644 --- a/pxr/usd/lib/pcp/primIndex_Graph.cpp +++ b/pxr/usd/lib/pcp/primIndex_Graph.cpp @@ -593,8 +593,8 @@ PcpPrimIndex_Graph::_InsertChildInStrengthOrder( void PcpPrimIndex_Graph::_DetachSharedNodePool() { - TRACE_FUNCTION(); if (not _data.unique()) { + TRACE_FUNCTION(); _data.reset(new _SharedData(*_data)); // XXX: This probably causes more finalization than necessary. Only From 01cc28dd698897c9798dee5d931674980cbc2697 Mon Sep 17 00:00:00 2001 From: gitamohr Date: Tue, 30 Aug 2016 14:32:00 -0700 Subject: [PATCH 060/380] tf: Add a warning if this code is ever invoked outside the "main" thread, which is not okay per python docs. (Internal change: 1650979) --- pxr/base/lib/tf/pyInterpreter.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/pxr/base/lib/tf/pyInterpreter.cpp b/pxr/base/lib/tf/pyInterpreter.cpp index ffa4579566..5df8a60ab6 100644 --- a/pxr/base/lib/tf/pyInterpreter.cpp +++ b/pxr/base/lib/tf/pyInterpreter.cpp @@ -30,6 +30,7 @@ #include "pxr/base/arch/symbols.h" #include "pxr/base/arch/systemInfo.h" +#include "pxr/base/arch/threads.h" #include #include @@ -59,6 +60,15 @@ TfPyInitialize() std::lock_guard lock(mutex); if (!Py_IsInitialized()) { + + if (not ArchIsMainThread() and not PyEval_ThreadsInitialized()) { + // Python claims that PyEval_InitThreads "should be called in the + // main thread before creating a second thread or engaging in any + // other thread operations." So we'll issue a warning here. + TF_WARN("Calling PyEval_InitThreads() for the first time outside " + "the 'main thread'. Python doc says not to do this."); + } + // Initialize Python threading. This grabs the GIL. We'll release it // at the end of this function. PyEval_InitThreads(); From 10fec8b33079a51470fbb025b590de45d025a0e7 Mon Sep 17 00:00:00 2001 From: gitamohr Date: Tue, 30 Aug 2016 14:32:10 -0700 Subject: [PATCH 061/380] sdf: Make IsMuted() check faster, we call this on every SetField. Also avoid redundant permission checks on SetField() calls that redirect to EraseField. (Internal change: 1650986) --- pxr/usd/lib/sdf/layer.cpp | 73 +++++++++++++++++++++++++++------------ pxr/usd/lib/sdf/layer.h | 7 ++++ 2 files changed, 57 insertions(+), 23 deletions(-) diff --git a/pxr/usd/lib/sdf/layer.cpp b/pxr/usd/lib/sdf/layer.cpp index f8c03f0a8a..0d203618ea 100644 --- a/pxr/usd/lib/sdf/layer.cpp +++ b/pxr/usd/lib/sdf/layer.cpp @@ -65,9 +65,10 @@ #include #include +#include +#include #include #include -#include using boost::bind; using std::map; @@ -87,6 +88,11 @@ typedef set _MutedLayers; static TfStaticData<_MutedLayers> _mutedLayers; // Global mutex protecting _mutedLayers. static TfStaticData _mutedLayersMutex; +// This is a global revision number that tracks changes to _mutedLayers. Since +// we seldom mute and unmute layers, this lets layers cache their muteness and +// do quick validity checks without taking a lock and looking themselves up in +// _mutedLayers. +static std::atomic_size_t _mutedLayersRevision { 1 }; // A registry for loaded layers. static TfStaticData _layerRegistry; @@ -106,6 +112,8 @@ SdfLayer::SdfLayer( _lastDirtyState(false), _assetInfo(new Sdf_AssetInfo), _assetModificationTime(0), + _mutedLayersRevisionCache(0), + _isMutedCache(false), _permissionToEdit(true), _permissionToSave(true) { @@ -1695,8 +1703,6 @@ SdfLayer::GetRelationshipAtPath(const SdfPath &path) bool SdfLayer::PermissionToEdit() const { - TRACE_FUNCTION(); - return _permissionToEdit and not IsMuted(); } @@ -2227,6 +2233,8 @@ SdfLayer::GetMutedLayers() void SdfLayer::SetMuted(bool muted) { + // XXX Racy... + if (muted == IsMuted()) { return; } @@ -2241,8 +2249,25 @@ SdfLayer::SetMuted(bool muted) bool SdfLayer::IsMuted() const -{ - return IsMuted(_GetMutedPath()); +{ + // Read the current muted revision number. If it's up-to-date we return our + // cache. It's possible that this is racy, but the whole thing is racy + // regardless. Even with a pure locking implementation, say we found this + // layer in the muted set -- by the time we return to the caller with + // 'true', some other thread may have removed this layer from the muted set. + + size_t curRev = _mutedLayersRevision; + if (ARCH_UNLIKELY(_mutedLayersRevisionCache != curRev)) { + string mutedPath = _GetMutedPath(); + std::lock_guard lock(*_mutedLayersMutex); + // Read again, since this is guaranteed to give us the current value + // because we have the lock. _mutedLayersRevision only changes with the + // lock held. + _mutedLayersRevisionCache = _mutedLayersRevision; + _isMutedCache = _mutedLayers->count(mutedPath); + } + + return _isMutedCache; } /*static*/ @@ -2259,7 +2284,9 @@ SdfLayer::AddToMutedLayers(const string &path) { bool didChange = false; { + // Racy... std::lock_guard lock(*_mutedLayersMutex); + ++_mutedLayersRevision; didChange = _mutedLayers->insert(path).second; } if (didChange) { @@ -2276,7 +2303,9 @@ SdfLayer::RemoveFromMutedLayers(const string &path) { bool didChange = false; { + // Racy... std::lock_guard lock(*_mutedLayersMutex); + ++_mutedLayersRevision; didChange = _mutedLayers->erase(path); } if (didChange) { @@ -2802,40 +2831,38 @@ void SdfLayer::SetField(const SdfAbstractDataSpecId& id, const TfToken& fieldName, const VtValue& value) { - if (not PermissionToEdit()) { + if (value.IsEmpty()) + return EraseField(id, fieldName); + + if (ARCH_UNLIKELY(not PermissionToEdit())) { TF_CODING_ERROR("Cannot set %s on <%s>. Layer @%s@ is not editable.", fieldName.GetText(), id.GetString().c_str(), GetIdentifier().c_str()); return; } - if (value.IsEmpty()) { - EraseField(id, fieldName); - } else { - VtValue oldValue = GetField(id, fieldName); - if (value != oldValue) - _PrimSetField(id, fieldName, value, &oldValue); - } + VtValue oldValue = GetField(id, fieldName); + if (value != oldValue) + _PrimSetField(id, fieldName, value, &oldValue); } void SdfLayer::SetField(const SdfAbstractDataSpecId& id, const TfToken& fieldName, const SdfAbstractDataConstValue& value) { - if (not PermissionToEdit()) { + if (value.IsEqual(VtValue())) + return EraseField(id, fieldName); + + if (ARCH_UNLIKELY(not PermissionToEdit())) { TF_CODING_ERROR("Cannot set %s on <%s>. Layer @%s@ is not editable.", fieldName.GetText(), id.GetString().c_str(), GetIdentifier().c_str()); return; } - - if (value.IsEqual(VtValue())) { - EraseField(id, fieldName); - } else { - VtValue oldValue = GetField(id, fieldName); - if (not value.IsEqual(oldValue)) - _PrimSetField(id, fieldName, value, &oldValue); - } + + VtValue oldValue = GetField(id, fieldName); + if (not value.IsEqual(oldValue)) + _PrimSetField(id, fieldName, value, &oldValue); } void @@ -2883,7 +2910,7 @@ SdfLayer::SetFieldDictValueByKey(const SdfAbstractDataSpecId& id, void SdfLayer::EraseField(const SdfAbstractDataSpecId& id, const TfToken& fieldName) { - if (not PermissionToEdit()) { + if (ARCH_UNLIKELY(not PermissionToEdit())) { TF_CODING_ERROR("Cannot erase %s on <%s>. Layer @%s@ is not editable.", fieldName.GetText(), id.GetString().c_str(), GetIdentifier().c_str()); diff --git a/pxr/usd/lib/sdf/layer.h b/pxr/usd/lib/sdf/layer.h index b769280134..03207eb61e 100644 --- a/pxr/usd/lib/sdf/layer.h +++ b/pxr/usd/lib/sdf/layer.h @@ -1454,6 +1454,13 @@ class SdfLayer : public SdfLayerBase // Modification timestamp of the backing file asset when last read. mutable double _assetModificationTime; + // Mutable revision number for cache invalidation. + mutable size_t _mutedLayersRevisionCache; + + // Cache of whether or not this layer is muted. Only valid if + // _mutedLayersRevisionCache is up-to-date with the global revision number. + mutable bool _isMutedCache; + // Layer permission bits. bool _permissionToEdit; bool _permissionToSave; From 8723aeb2d57e1e2333b8c0b8d07b182cd98ce0fd Mon Sep 17 00:00:00 2001 From: gitamohr Date: Tue, 30 Aug 2016 14:32:17 -0700 Subject: [PATCH 062/380] sdf: Remove MAYA_TBB_HANG_WORKAROUND_HACK code. (Internal change: 1650989) --- pxr/usd/lib/sdf/pathNode.cpp | 84 ++---------------------------------- 1 file changed, 4 insertions(+), 80 deletions(-) diff --git a/pxr/usd/lib/sdf/pathNode.cpp b/pxr/usd/lib/sdf/pathNode.cpp index 33a1af72a8..1d2195b45a 100644 --- a/pxr/usd/lib/sdf/pathNode.cpp +++ b/pxr/usd/lib/sdf/pathNode.cpp @@ -41,11 +41,6 @@ #include #include -#if MAYA_TBB_HANG_WORKAROUND_HACK -#include -#include -#endif // MAYA_TBB_HANG_WORKAROUND_HACK - using std::string; using std::vector; @@ -82,16 +77,6 @@ struct _ParentAnd { const Sdf_PathNode *parent; T value; }; // Allow void for 'expression' path case, which has no additional data. template <> struct _ParentAnd { const Sdf_PathNode *parent; }; -#if MAYA_TBB_HANG_WORKAROUND_HACK -template -bool operator==(_ParentAnd const &l, _ParentAnd const &r) { - return l.parent == r.parent && l.value == r.value; -} -bool operator==(_ParentAnd const &l, _ParentAnd const &r) { - return l.parent == r.parent; -} -#endif // MAYA_TBB_HANG_WORKAROUND_HACK - template inline _ParentAnd _MakeParentAnd(const Sdf_PathNode *parent, const T &value) { @@ -126,13 +111,7 @@ struct _HashParentAnd boost::hash_combine(h, t.value); return h; } - -#if MAYA_TBB_HANG_WORKAROUND_HACK - inline size_t operator()(const T &t) const { - return hash(t); - } -#endif // MAYA_TBB_HANG_WORKAROUND_HACK -}; + }; template <> struct _HashParentAnd<_ParentAnd > @@ -145,23 +124,13 @@ struct _HashParentAnd<_ParentAnd > inline size_t hash(const _ParentAnd &t) const { return hash_value(t.parent); } - -#if MAYA_TBB_HANG_WORKAROUND_HACK - inline size_t operator()(const _ParentAnd &t) const { - return hash(t); - } -#endif // MAYA_TBB_HANG_WORKAROUND_HACK }; template struct _Table { -#if MAYA_TBB_HANG_WORKAROUND_HACK - typedef std::unordered_map<_ParentAnd, const Sdf_PathNode *, - _HashParentAnd<_ParentAnd > > Type; -#else - typedef tbb::concurrent_hash_map<_ParentAnd, const Sdf_PathNode *, - _HashParentAnd<_ParentAnd > > Type; -#endif // MAYA_TBB_HANG_WORKAROUND_HACK + typedef tbb::concurrent_hash_map< + _ParentAnd, const Sdf_PathNode *, + _HashParentAnd<_ParentAnd > > Type; }; typedef _Table::Type _TokenTable; @@ -169,30 +138,12 @@ typedef _Table::Type _VarSelTable; typedef _Table::Type _PathTable; typedef _Table::Type _VoidTable; -#if MAYA_TBB_HANG_WORKAROUND_HACK -static tbb::spin_mutex &_GetTableLock() { - static tbb::spin_mutex mutex; - return mutex; -} -#endif // MAYA_TBB_HANG_WORKAROUND_HACK - template inline Sdf_PathNodeConstRefPtr _FindOrCreate(Table &table, const Sdf_PathNodeConstRefPtr &parent, const Arg &arg) { -#if MAYA_TBB_HANG_WORKAROUND_HACK - tbb::spin_mutex::scoped_lock lock(_GetTableLock()); - auto iresult = table.emplace(_MakeParentAnd(parent.get(), arg), nullptr); - if (iresult.second or - Access::GetRefCount(iresult.first->second).fetch_and_increment() == 0) { - Sdf_PathNodeConstRefPtr newNode = Access::New(parent, arg); - iresult.first->second = newNode.get(); - return newNode; - } - return Sdf_PathNodeConstRefPtr(iresult.first->second, /* add_ref = */ false); -#else // MAYA_TBB_HANG_WORKAROUND_HACK typename Table::accessor accessor; if (table.insert(accessor, _MakeParentAnd(parent.get(), arg)) or Access::GetRefCount(accessor->second).fetch_and_increment() == 0) { @@ -206,24 +157,12 @@ _FindOrCreate(Table &table, return newNode; } return Sdf_PathNodeConstRefPtr(accessor->second, /* add_ref = */ false); -#endif // MAYA_TBB_HANG_WORKAROUND_HACK } template inline Sdf_PathNodeConstRefPtr _FindOrCreate(Table &table, const Sdf_PathNodeConstRefPtr &parent) { -#if MAYA_TBB_HANG_WORKAROUND_HACK - tbb::spin_mutex::scoped_lock lock(_GetTableLock()); - auto iresult = table.emplace(_MakeParentAnd(parent.get()), nullptr); - if (iresult.second or - Access::GetRefCount(iresult.first->second).fetch_and_increment() == 0) { - Sdf_PathNodeConstRefPtr newNode = Access::New(parent); - iresult.first->second = newNode.get(); - return newNode; - } - return Sdf_PathNodeConstRefPtr(iresult.first->second, /* add_ref = */ false); -#else // MAYA_TBB_HANG_WORKAROUND_HACK typename Table::accessor accessor; if (table.insert(accessor, _MakeParentAnd(parent.get())) or Access::GetRefCount(accessor->second).fetch_and_increment() == 0) { @@ -237,7 +176,6 @@ _FindOrCreate(Table &table, const Sdf_PathNodeConstRefPtr &parent) return newNode; } return Sdf_PathNodeConstRefPtr(accessor->second, /* add_ref = */ false); -#endif // MAYA_TBB_HANG_WORKAROUND_HACK } template @@ -245,12 +183,6 @@ inline void _Remove(const Sdf_PathNode *pathNode, Table &table, const Sdf_PathNodeConstRefPtr &parent, const Arg &arg) { -#if MAYA_TBB_HANG_WORKAROUND_HACK - tbb::spin_mutex::scoped_lock lock(_GetTableLock()); - auto iter = table.find(_MakeParentAnd(parent.get(), arg)); - if (iter != table.end() and iter->second == pathNode) - table.erase(iter); -#else // MAYA_TBB_HANG_WORKAROUND_HACK // If there's an entry for this key that has pathNode, erase it. Even if // there's an entry present it may not be pathNode, since another node may // have been created since we decremented our refcount and started being @@ -260,7 +192,6 @@ _Remove(const Sdf_PathNode *pathNode, accessor->second == pathNode) { table.erase(accessor); } -#endif // MAYA_TBB_HANG_WORKAROUND_HACK } template @@ -268,12 +199,6 @@ inline void _Remove(const Sdf_PathNode *pathNode, Table &table, const Sdf_PathNodeConstRefPtr &parent) { -#if MAYA_TBB_HANG_WORKAROUND_HACK - tbb::spin_mutex::scoped_lock lock(_GetTableLock()); - auto iter = table.find(_MakeParentAnd(parent.get())); - if (iter != table.end() and iter->second == pathNode) - table.erase(iter); -#else // MAYA_TBB_HANG_WORKAROUND_HACK // If there's an entry for this key that has pathNode, erase it. Even if // there's an entry present it may not be pathNode, since another node may // have been created since we decremented our refcount and started being @@ -283,7 +208,6 @@ _Remove(const Sdf_PathNode *pathNode, accessor->second == pathNode) { table.erase(accessor); } -#endif // MAYA_TBB_HANG_WORKAROUND_HACK } } // anon From 4a1c014e89214ee42f96c66c3f76518e09ff8f27 Mon Sep 17 00:00:00 2001 From: gitamohr Date: Tue, 30 Aug 2016 14:32:24 -0700 Subject: [PATCH 063/380] pcp: Remove MAYA_TBB_HANG_WORKAROUND_HACK code. (Internal change: 1650990) --- pxr/usd/lib/pcp/mapExpression.cpp | 50 ------------------------------- 1 file changed, 50 deletions(-) diff --git a/pxr/usd/lib/pcp/mapExpression.cpp b/pxr/usd/lib/pcp/mapExpression.cpp index 1766e36767..c5522f5edb 100644 --- a/pxr/usd/lib/pcp/mapExpression.cpp +++ b/pxr/usd/lib/pcp/mapExpression.cpp @@ -27,12 +27,7 @@ #include "pxr/base/tracelite/trace.h" -#if MAYA_TBB_HANG_WORKAROUND_HACK -#include -#include -#else #include -#endif // MAYA_TBB_HANG_WORKAROUND_HACK struct Pcp_VariableImpl; @@ -174,24 +169,10 @@ struct _KeyHashEq { inline bool equal(const Key &l, const Key &r) const { return l == r; } inline size_t hash(const Key &k) const { return k.GetHash(); } - -#if MAYA_TBB_HANG_WORKAROUND_HACK - inline size_t operator()(const Key &k) const { return hash(k); } -#endif // MAYA_TBB_HANG_WORKAROUND_HACK }; } // anon -#if MAYA_TBB_HANG_WORKAROUND_HACK -struct PcpMapExpression::_Node::_NodeMap -{ - typedef PcpMapExpression::_Node::Key Key; - typedef std::unordered_map< - Key, PcpMapExpression::_Node *, _KeyHashEq > MapType; - MapType map; - tbb::spin_mutex mutex; -}; -#else struct PcpMapExpression::_Node::_NodeMap { typedef PcpMapExpression::_Node::Key Key; @@ -200,7 +181,6 @@ struct PcpMapExpression::_Node::_NodeMap typedef MapType::accessor accessor; MapType map; }; -#endif // MAYA_TBB_HANG_WORKAROUND_HACK TfStaticData PcpMapExpression::_Node::_nodeRegistry; @@ -253,25 +233,6 @@ PcpMapExpression::_Node::New( _Op op_, if (key.op != _OpVariable) { // Check for existing instance to re-use -#if MAYA_TBB_HANG_WORKAROUND_HACK - tbb::spin_mutex::scoped_lock lock(_nodeRegistry->mutex); - - std::pair<_NodeMap::MapType::iterator, bool> accessor = - _nodeRegistry->map.insert(std::make_pair(key, nullptr)); - if (accessor.second or - accessor.first->second->_refCount.fetch_and_increment() == 0) { - // Either there was no node in the table, or there was but it had - // begun dying (another client dropped its refcount to 0). We have - // to create a new node in the table. When the client that is - // killing the other node it looks for itself in the table, it will - // either not find itself or will find a different node and so won't - // remove it. - _NodeRefPtr newNode(new _Node(key)); - accessor.first->second = newNode.get(); - return newNode; - } - return _NodeRefPtr(accessor.first->second, /*add_ref =*/ false); -#else _NodeMap::accessor accessor; if (_nodeRegistry->map.insert(accessor, key) or accessor->second->_refCount.fetch_and_increment() == 0) { @@ -286,7 +247,6 @@ PcpMapExpression::_Node::New( _Op op_, return newNode; } return _NodeRefPtr(accessor->second, /*add_ref =*/ false); -#endif // MAYA_TBB_HANG_WORKAROUND_HACK } return _NodeRefPtr(new _Node(key)); } @@ -318,22 +278,12 @@ PcpMapExpression::_Node::~_Node() } if (key.op != _OpVariable) { -#if MAYA_TBB_HANG_WORKAROUND_HACK - tbb::spin_mutex::scoped_lock lock(_nodeRegistry->mutex); - // Remove from node map if present. - _NodeMap::MapType::iterator accessor = _nodeRegistry->map.find(key); - if (accessor != _nodeRegistry->map.end() and - accessor->second == this) { - _nodeRegistry->map.erase(accessor); - } -#else // Remove from node map if present. _NodeMap::accessor accessor; if (_nodeRegistry->map.find(accessor, key) and accessor->second == this) { _nodeRegistry->map.erase(accessor); } -#endif // MAYA_TBB_HANG_WORKAROUND_HACK } } From 3b4c62b90a5bb47186557875bca9fe562abf00a8 Mon Sep 17 00:00:00 2001 From: gitamohr Date: Tue, 30 Aug 2016 14:32:31 -0700 Subject: [PATCH 064/380] ar: Remove MAYA_TBB_HANG_WORKAROUND_HACK code. (Internal change: 1650991) --- pxr/usd/lib/ar/defaultResolver.cpp | 28 ---------------------------- 1 file changed, 28 deletions(-) diff --git a/pxr/usd/lib/ar/defaultResolver.cpp b/pxr/usd/lib/ar/defaultResolver.cpp index 67d2b1a8af..1282d5d62d 100644 --- a/pxr/usd/lib/ar/defaultResolver.cpp +++ b/pxr/usd/lib/ar/defaultResolver.cpp @@ -33,33 +33,18 @@ #include "pxr/base/tf/stringUtils.h" #include "pxr/base/vt/value.h" -#if MAYA_TBB_HANG_WORKAROUND_HACK -#include -#include -#else #include -#endif // MAYA_TBB_HANG_WORKAROUND_HACK #include static const char* _FileRelativePathPrefix = "./"; -#if MAYA_TBB_HANG_WORKAROUND_HACK -struct Ar_DefaultResolver::_Cache -{ - using _PathToResolvedPathMap = - std::unordered_map; - _PathToResolvedPathMap _pathToResolvedPathMap; - tbb::spin_mutex _mutex; -}; -#else struct Ar_DefaultResolver::_Cache { using _PathToResolvedPathMap = tbb::concurrent_hash_map; _PathToResolvedPathMap _pathToResolvedPathMap; }; -#endif // MAYA_TBB_HANG_WORKAROUND_HACK Ar_DefaultResolver::Ar_DefaultResolver() { @@ -208,18 +193,6 @@ Ar_DefaultResolver::ResolveWithAssetInfo( return path; } -#if MAYA_TBB_HANG_WORKAROUND_HACK - if (_CachePtr currentCache = _GetCurrentCache()) { - tbb::spin_mutex::scoped_lock lock(currentCache->_mutex); - std::pair<_Cache::_PathToResolvedPathMap::iterator, bool> accessor = - currentCache->_pathToResolvedPathMap.insert( - std::make_pair(path, std::string())); - if (accessor.second) { - accessor.first->second = _ResolveNoCache(path); - } - return accessor.first->second; - } -#else if (_CachePtr currentCache = _GetCurrentCache()) { _Cache::_PathToResolvedPathMap::accessor accessor; if (currentCache->_pathToResolvedPathMap.insert( @@ -228,7 +201,6 @@ Ar_DefaultResolver::ResolveWithAssetInfo( } return accessor->second; } -#endif // MAYA_TBB_HANG_WORKAROUND_HACK return _ResolveNoCache(path); } From 250ab6ba2119d5f3d39040c6867568b4efe53c4a Mon Sep 17 00:00:00 2001 From: florihupf Date: Tue, 30 Aug 2016 20:35:25 -0700 Subject: [PATCH 065/380] pxrTf: Add TF_LOG_ERRORS which logs all errors immediately to stderr. (Internal change: 1651045) --- pxr/base/lib/tf/diagnosticMgr.cpp | 11 ++++++++++- pxr/base/lib/tf/diagnosticMgr.h | 3 ++- .../TfDebugTestEnv/non-specific/debugTestEnv.out | 2 ++ .../non-specific/debugTestEnvList.out | 2 ++ 4 files changed, 16 insertions(+), 2 deletions(-) diff --git a/pxr/base/lib/tf/diagnosticMgr.cpp b/pxr/base/lib/tf/diagnosticMgr.cpp index 3947dc4c4c..b4e26eff1e 100644 --- a/pxr/base/lib/tf/diagnosticMgr.cpp +++ b/pxr/base/lib/tf/diagnosticMgr.cpp @@ -75,6 +75,10 @@ TF_REGISTRY_FUNCTION(TfDebug) TF_ERROR_MARK_TRACKING, "capture stack traces at TfErrorMark ctor/dtor, enable " "TfReportActiveMarks debugging API."); + TF_DEBUG_ENVIRONMENT_SYMBOL(TF_PRINT_ALL_POSTED_ERRORS_TO_STDERR, + "print all posted errors immediately, meaning that even errors that " + "are expected and handled will be printed, producing possibly " + "confusing output"); } @@ -178,8 +182,13 @@ TfDiagnosticMgr::PostError(TfEnum errorCode, const char* errorCodeString, if (TfDebug::IsEnabled(TF_ATTACH_DEBUGGER_ON_ERROR)) ArchDebuggerTrap(); - if (TfDebug::IsEnabled(TF_LOG_STACK_TRACE_ON_ERROR)) { + if (TfDebug::IsEnabled(TF_PRINT_ALL_POSTED_ERRORS_TO_STDERR) or + TfDebug::IsEnabled(TF_LOG_STACK_TRACE_ON_ERROR)) { + _PrintDiagnostic(stderr, errorCode, context, commentary, info); + } + + if (TfDebug::IsEnabled(TF_LOG_STACK_TRACE_ON_ERROR)) { TfLogStackTrace("ERROR", /* logToDb */ false); } diff --git a/pxr/base/lib/tf/diagnosticMgr.h b/pxr/base/lib/tf/diagnosticMgr.h index 0ab507fa96..bc34a82882 100644 --- a/pxr/base/lib/tf/diagnosticMgr.h +++ b/pxr/base/lib/tf/diagnosticMgr.h @@ -53,7 +53,8 @@ TF_DEBUG_CODES( TF_LOG_STACK_TRACE_ON_ERROR, - TF_ERROR_MARK_TRACKING + TF_ERROR_MARK_TRACKING, + TF_PRINT_ALL_POSTED_ERRORS_TO_STDERR ); class TfError; diff --git a/pxr/base/lib/tf/testenv/baseline/TfDebugTestEnv/non-specific/debugTestEnv.out b/pxr/base/lib/tf/testenv/baseline/TfDebugTestEnv/non-specific/debugTestEnv.out index 061629a233..6e6ec66544 100644 --- a/pxr/base/lib/tf/testenv/baseline/TfDebugTestEnv/non-specific/debugTestEnv.out +++ b/pxr/base/lib/tf/testenv/baseline/TfDebugTestEnv/non-specific/debugTestEnv.out @@ -18,6 +18,8 @@ TF_DLOPEN : show files opened by TfDlopen TF_ERROR_MARK_TRACKING : capture stack traces at TfErrorMark ctor/dtor, enable TfReportActiveMarks debugging API. TF_LOG_STACK_TRACE_ON_ERROR: issue stack traces for all errors +TF_PRINT_ALL_POSTED_ERRORS_TO_STDERR: + print all posted errors immediately, meaning that even errors that are expected and handled will be printed, producing possibly confusing output TF_SCRIPT_MODULE_LOADER : show script module loading activity TF_TYPE_REGISTRY : show changes to the TfType registry diff --git a/pxr/base/lib/tf/testenv/baseline/TfDebugTestEnvList/non-specific/debugTestEnvList.out b/pxr/base/lib/tf/testenv/baseline/TfDebugTestEnvList/non-specific/debugTestEnvList.out index 8a08946ccb..63a3e33578 100644 --- a/pxr/base/lib/tf/testenv/baseline/TfDebugTestEnvList/non-specific/debugTestEnvList.out +++ b/pxr/base/lib/tf/testenv/baseline/TfDebugTestEnvList/non-specific/debugTestEnvList.out @@ -12,6 +12,8 @@ TF_DLOPEN : show files opened by TfDlopen TF_ERROR_MARK_TRACKING : capture stack traces at TfErrorMark ctor/dtor, enable TfReportActiveMarks debugging API. TF_LOG_STACK_TRACE_ON_ERROR: issue stack traces for all errors +TF_PRINT_ALL_POSTED_ERRORS_TO_STDERR: + print all posted errors immediately, meaning that even errors that are expected and handled will be printed, producing possibly confusing output TF_SCRIPT_MODULE_LOADER : show script module loading activity TF_TYPE_REGISTRY : show changes to the TfType registry From 905d35169ed871db4e29d7165abb8876117b75ef Mon Sep 17 00:00:00 2001 From: florihupf Date: Tue, 30 Aug 2016 20:35:55 -0700 Subject: [PATCH 066/380] pxrTf: Avoid reading the same debug flag twice. (Internal change: 1651071) --- pxr/base/lib/tf/diagnosticMgr.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/pxr/base/lib/tf/diagnosticMgr.cpp b/pxr/base/lib/tf/diagnosticMgr.cpp index b4e26eff1e..094c3f9405 100644 --- a/pxr/base/lib/tf/diagnosticMgr.cpp +++ b/pxr/base/lib/tf/diagnosticMgr.cpp @@ -182,13 +182,16 @@ TfDiagnosticMgr::PostError(TfEnum errorCode, const char* errorCodeString, if (TfDebug::IsEnabled(TF_ATTACH_DEBUGGER_ON_ERROR)) ArchDebuggerTrap(); - if (TfDebug::IsEnabled(TF_PRINT_ALL_POSTED_ERRORS_TO_STDERR) or - TfDebug::IsEnabled(TF_LOG_STACK_TRACE_ON_ERROR)) { + const bool logStackTraceOnError = + TfDebug::IsEnabled(TF_LOG_STACK_TRACE_ON_ERROR); + + if (logStackTraceOnError or + TfDebug::IsEnabled(TF_PRINT_ALL_POSTED_ERRORS_TO_STDERR)) { _PrintDiagnostic(stderr, errorCode, context, commentary, info); } - if (TfDebug::IsEnabled(TF_LOG_STACK_TRACE_ON_ERROR)) { + if (logStackTraceOnError) { TfLogStackTrace("ERROR", /* logToDb */ false); } From 047c205306e85af956eeafb6e6314bef07569720 Mon Sep 17 00:00:00 2001 From: ryanbujnowicz Date: Tue, 30 Aug 2016 20:36:04 -0700 Subject: [PATCH 067/380] cmake: Determine plugInfo.json "LibraryPath" dynamically. The usdAbc plugInfo.json installs to a different location than the core plugin plugInfo.json files which install to $PREFIX/share/usd/plugins so the hardcoded "LibraryPath" was incorrect for usdAbc. The "LibraryPath" is now determined at build time by finding the relative path between the plugin root and the dynamic library's install location Note: usdAbc is not in the default plugin search path. You can enable it by setting the PXR_PLUGINPATH_NAME envvar to $PREFIX/plugin. (Internal change: 1651195) --- cmake/macros/Private.cmake | 58 ++++++++++++++++++++++++++++---------- cmake/macros/Public.cmake | 40 ++++++++++++++++++++------ 2 files changed, 75 insertions(+), 23 deletions(-) diff --git a/cmake/macros/Private.cmake b/cmake/macros/Private.cmake index cf29c3a381..f000ffe3ea 100644 --- a/cmake/macros/Private.cmake +++ b/cmake/macros/Private.cmake @@ -76,20 +76,12 @@ function(_get_python_module_name LIBRARY_FILENAME MODULE_NAME) ) endfunction() # _get_python_module_name -function(_plugInfo_subst libName plugInfoPath) - # Generate plugInfo.json files from a template. Note that we can't use - # the $ generator expression here because - # configure_file will run at configure time while the generators will only - # run after. - set(libFile ${CMAKE_SHARED_LIBRARY_PREFIX}${libName}${CMAKE_SHARED_LIBRARY_SUFFIX}) - - # The root resource directory is in $PREFIX/share/usd/$LIB/resource but the - # libs are actually in $PREFIX/lib. The lib path can then be specified - # relatively as below. - set(PLUG_INFO_LIBRARY_PATH "../../../../lib/${libFile}") - set(PLUG_INFO_RESOURCE_PATH "resources") - set(PLUG_INFO_PLUGIN_NAME "pxr.${libName}") +function(_plugInfo_subst libTarget plugInfoPath) + # PLUG_INFO_LIBRARY_PATH should be set by the caller (see pxr_plugin and + # pxr_shared_library). + _get_resources_dir_name(PLUG_INFO_RESOURCE_PATH) set(PLUG_INFO_ROOT "..") + set(PLUG_INFO_PLUGIN_NAME "pxr.${libTarget}") configure_file( ${plugInfoPath} @@ -201,6 +193,7 @@ function(_install_resource_files) # resourceFileC # ... # + _get_resources_dir(${PLUGINS_PREFIX} ${LIBRARY_NAME} resourcesPath) foreach(f ${resourceFiles}) # Don't install subdirs for absolute paths, there's no way to tell # what the intended subdir structure is. In practice, any absolute paths @@ -212,7 +205,7 @@ function(_install_resource_files) install( FILES ${f} - DESTINATION ${PLUGINS_PREFIX}/${LIBRARY_NAME}/resources/${dirPath} + DESTINATION ${resourcesPath}/${dirPath} ) endforeach() endfunction() # _install_resource_files @@ -279,7 +272,6 @@ function(_classes LIBRARY_NAME) set(${LIBRARY_NAME}_CPPFILES ${${LIBRARY_NAME}_CPPFILES} PARENT_SCOPE) endfunction() # _classes - function(_get_install_dir path out) if (PXR_INSTALL_SUBDIR) set(${out} ${PXR_INSTALL_SUBDIR}/${path} PARENT_SCOPE) @@ -288,6 +280,42 @@ function(_get_install_dir path out) endif() endfunction() # get_install_dir +function(_get_resources_dir_name output) + set(${output} + resources + PARENT_SCOPE) +endfunction() # _get_resources_dir_name + +function(_get_plugin_root pluginsPrefix pluginName output) + set(${output} + ${pluginsPrefix}/${pluginName} + PARENT_SCOPE) +endfunction() # _get_plugin_root + +function(_get_resources_dir pluginsPrefix pluginName output) + _get_resources_dir_name(resourcesDir) + _get_plugin_root(${pluginsPrefix} ${pluginName} pluginRoot) + set(${output} + ${pluginRoot}/${resourcesDir} + PARENT_SCOPE) +endfunction() # _get_resources_dir + +function(_get_library_file target output) + get_target_property(prefix ${target} PREFIX) + if (NOT prefix AND NOT "" STREQUAL "${prefix}") + set(prefix ${CMAKE_SHARED_LIBRARY_PREFIX}) + endif() + + get_target_property(suffix ${target} SUFFIX) + if (NOT suffix AND NOT "" STREQUAL "${suffix}") + set(suffix ${CMAKE_SHARED_LIBRARY_SUFFIX}) + endif() + + set(${output} + ${prefix}${target}${suffix} + PARENT_SCOPE) +endfunction() # _get_library_file + macro(_get_share_install_dir RESULT) _get_install_dir(share/usd ${RESULT}) endmacro() # _get_share_install_dir diff --git a/cmake/macros/Public.cmake b/cmake/macros/Public.cmake index a04c37499d..d90e994ecd 100644 --- a/cmake/macros/Public.cmake +++ b/cmake/macros/Public.cmake @@ -299,6 +299,17 @@ function(pxr_shared_library LIBRARY_NAME) ) endif() + _get_library_file(${LIBRARY_NAME} LIBRARY_FILE) + + # Figure out the relative path from this targets plugin location to its + # corresponding install location. This is embedded in the plugInfo.json to + # record where to find the plugin. + _get_plugin_root(${PLUGINS_PREFIX} ${LIBRARY_NAME} PLUGIN_ROOT_PATH) + file(RELATIVE_PATH + PLUG_INFO_LIBRARY_PATH + ${CMAKE_INSTALL_PREFIX}/${PLUGIN_ROOT_PATH} + ${CMAKE_INSTALL_PREFIX}/${LIB_INSTALL_PREFIX}/${LIBRARY_FILE}) + if (sl_RESOURCE_FILES) _install_resource_files(${sl_RESOURCE_FILES}) endif() @@ -601,17 +612,24 @@ function(pxr_plugin PLUGIN_NAME) ) endif() - if (sl_RESOURCE_FILES) - _get_install_dir(plugin PLUGINS_PREFIX) - set(LIBRARY_NAME ${PLUGIN_NAME}) + _get_install_dir(plugin PLUGINS_PREFIX) + set(LIBRARY_NAME ${PLUGIN_NAME}) + _get_library_file(${LIBRARY_NAME} LIBRARY_FILE) + + # Figure out the relative path from this targets plugin location to its + # corresponding install location. This is embedded in the plugInfo.json to + # record where to find the plugin. + _get_plugin_root(${PLUGINS_PREFIX} ${LIBRARY_NAME} PLUGIN_ROOT_PATH) + file(RELATIVE_PATH + PLUG_INFO_LIBRARY_PATH + ${CMAKE_INSTALL_PREFIX}/${PLUGIN_ROOT_PATH} + ${CMAKE_INSTALL_PREFIX}/${PLUGIN_INSTALL_PREFIX}/${LIBRARY_FILE}) + if (sl_RESOURCE_FILES) _install_resource_files(${sl_RESOURCE_FILES}) endif() if (sl_PYSIDE_UI_FILES) - _get_install_dir(plugin PLUGINS_PREFIX) - set(LIBRARY_NAME ${PLUGIN_NAME}) - _install_pyside_ui_files(${sl_PYSIDE_UI_FILES}) endif() @@ -843,9 +861,15 @@ endfunction() # pxr_register_test function(pxr_setup_plugins) _get_share_install_dir(SHARE_INSTALL_PREFIX) - # Install a top-level plugInfo.json in the shared area + # Install a top-level plugInfo.json in the shared area and into the + # top-level plugin area + _get_resources_dir_name(resourcesDir) + set(plugInfoContents "{\\n \\\"Includes\\\": [ \\\"*/${resourcesDir}/\\\" ]\\n}\\n") + install(CODE + "file(WRITE \"${CMAKE_INSTALL_PREFIX}/${SHARE_INSTALL_PREFIX}/plugins/plugInfo.json\" ${plugInfoContents})" + ) install(CODE - "file(WRITE \"${CMAKE_INSTALL_PREFIX}/${SHARE_INSTALL_PREFIX}/plugins/plugInfo.json\" \"{\n \\\"Includes\\\": [ \\\"*/resources/\\\" ]\n}\")" + "file(WRITE \"${CMAKE_INSTALL_PREFIX}/plugin/plugInfo.json\" ${plugInfoContents})" ) endfunction() # pxr_setup_plugins From f4960c4bef37f6658095905602f1d70f780af834 Mon Sep 17 00:00:00 2001 From: George ElKoura Date: Tue, 30 Aug 2016 20:57:28 -0700 Subject: [PATCH 068/380] Merged latest dev with latest dev_win_ip. --- .travis.yml | 157 ++++ CMakeLists.txt | 7 +- README.md | 8 +- cmake/macros/Public.cmake | 2 +- cmake/modules/FindPySide.cmake | 3 +- pxr/base/lib/gf/frustum.cpp | 76 +- pxr/base/lib/gf/frustum.h | 34 +- pxr/base/lib/gf/testenv/testGfFrustum.py | 21 +- pxr/base/lib/gf/testenv/testGfMatrix.py | 2 +- pxr/base/lib/gf/testenv/testGfRange.py | 4 +- pxr/base/lib/gf/testenv/testGfRay.py | 4 +- pxr/base/lib/gf/testenv/testGfSize.py | 4 +- pxr/base/lib/gf/testenv/testGfVec.py | 8 +- pxr/base/lib/gf/wrapFrustum.cpp | 3 + pxr/base/lib/plug/testPlug.py | 10 +- pxr/base/lib/tf/pyFunction.h | 19 +- pxr/base/lib/tf/pyInterpreter.cpp | 10 + .../tf/testenv/testTfPyDiagnosticNotices.py | 12 +- pxr/base/lib/tf/testenv/testTfPython.py | 2 + pxr/base/lib/tf/testenv/testTfType.py | 2 +- pxr/base/lib/tf/wrapTestTfPython.cpp | 5 + pxr/base/lib/vt/dictionary.cpp | 5 + pxr/base/lib/vt/dictionary.h | 4 + pxr/base/lib/vt/testenv/testVtArray.py | 2 +- pxr/base/lib/vt/testenv/testVtCpp.cpp | 23 + pxr/base/lib/work/loops.h | 15 +- pxr/base/lib/work/testenv/testWorkLoops.cpp | 2 +- .../lib/work/testenv/testWorkThreadLimits.cpp | 100 ++- pxr/base/lib/work/threadLimits.cpp | 92 ++- pxr/base/lib/work/threadLimits.h | 32 +- pxr/base/lib/work/wrapThreadLimits.cpp | 2 +- pxr/imaging/lib/garch/CMakeLists.txt | 10 + pxr/imaging/lib/garch/__init__.py | 40 + .../lib/garch/glPlatformContextDarwin.mm | 14 + .../glPlatformDebugContext.cpp | 56 +- .../{glfq => garch}/glPlatformDebugContext.h | 22 +- .../selectVisual.mm => garch/module.cpp} | 15 +- pxr/imaging/lib/garch/moduleDeps.cpp | 42 ++ .../wrapPlatformDebugContext.cpp | 8 +- pxr/imaging/lib/glfq/CMakeLists.txt | 7 +- pxr/imaging/lib/glfq/__init__.py | 3 +- pxr/imaging/lib/glfq/glDebugContext.cpp | 6 +- pxr/imaging/lib/glfq/glDebugContext.h | 4 +- pxr/imaging/lib/glfq/module.cpp | 1 - pxr/imaging/lib/hd/changeTracker.cpp | 6 + pxr/imaging/lib/hd/codeGen.cpp | 19 +- pxr/imaging/lib/hd/drawBatch.cpp | 41 +- pxr/imaging/lib/hd/drawBatch.h | 2 +- pxr/imaging/lib/hd/drawTargetRenderPass.cpp | 75 +- pxr/imaging/lib/hd/drawTargetRenderPass.h | 22 +- pxr/imaging/lib/hd/glslProgram.cpp | 8 +- pxr/imaging/lib/hd/light.cpp | 10 +- pxr/imaging/lib/hd/texture.cpp | 57 +- pxr/imaging/lib/hd/textureResource.cpp | 36 +- pxr/imaging/lib/hd/textureResource.h | 2 + pxr/imaging/lib/hd/unitTestDelegate.cpp | 48 ++ pxr/imaging/lib/hd/unitTestDelegate.h | 18 + pxr/imaging/lib/hdx/drawTargetTask.cpp | 77 +- pxr/imaging/lib/hdx/drawTargetTask.h | 3 + pxr/usd/bin/usdcat/usdcat.py | 2 +- pxr/usd/lib/ar/defaultResolver.cpp | 28 - pxr/usd/lib/pcp/cache.cpp | 118 ++- pxr/usd/lib/pcp/cache.h | 101 ++- pxr/usd/lib/pcp/changes.cpp | 116 +-- pxr/usd/lib/pcp/mapExpression.cpp | 50 -- pxr/usd/lib/pcp/primIndex.cpp | 24 +- pxr/usd/lib/pcp/primIndex.h | 36 +- pxr/usd/lib/pcp/primIndex_Graph.cpp | 2 +- pxr/usd/lib/pcp/statistics.cpp | 15 + pxr/usd/lib/pcp/wrapLayerStack.cpp | 8 +- pxr/usd/lib/sdf/layer.cpp | 73 +- pxr/usd/lib/sdf/layer.h | 7 + pxr/usd/lib/sdf/pathNode.cpp | 84 +-- pxr/usd/lib/usd/crateData.cpp | 86 ++- pxr/usd/lib/usd/crateFile.cpp | 2 + pxr/usd/lib/usd/crateFile.h | 7 +- pxr/usd/lib/usd/prim.cpp | 2 +- pxr/usd/lib/usd/primData.cpp | 38 +- pxr/usd/lib/usd/primData.h | 7 +- pxr/usd/lib/usd/primFlags.h | 6 +- pxr/usd/lib/usd/stage.cpp | 126 +++- pxr/usd/lib/usd/stage.h | 17 +- pxr/usd/lib/usd/variantSets.cpp | 16 +- pxr/usd/lib/usdGeom/bboxCache.cpp | 6 + pxr/usd/lib/usdGeom/metrics.h | 2 +- pxr/usd/lib/usdGeom/primvar.cpp | 18 +- pxr/usd/lib/usdGeom/primvar.h | 37 +- pxr/usd/lib/usdGeom/wrapPrimvar.cpp | 1 + pxr/usd/lib/usdUI/overview.dox | 22 + pxr/usd/plugin/usdAbc/wrapAlembicTest.cpp | 4 +- pxr/usdImaging/bin/usdview/CMakeLists.txt | 5 + pxr/usdImaging/lib/usdImaging/delegate.cpp | 84 +++ pxr/usdImaging/lib/usdImaging/engine.cpp | 8 + pxr/usdImaging/lib/usdImaging/engine.h | 4 + pxr/usdImaging/lib/usdImaging/gl.cpp | 24 + pxr/usdImaging/lib/usdImaging/gl.h | 2 + pxr/usdImaging/lib/usdImaging/hdEngine.cpp | 8 + pxr/usdImaging/lib/usdImaging/hdEngine.h | 2 + pxr/usdImaging/lib/usdImaging/wrapGL.cpp | 1 + pxr/usdImaging/lib/usdviewq/CMakeLists.txt | 5 + .../lib/usdviewq/attributeValueEditor.py | 2 +- .../lib/usdviewq/attributeViewContextMenu.py | 3 +- pxr/usdImaging/lib/usdviewq/common.py | 9 +- .../lib/usdviewq/customAttributes.py | 40 +- .../lib/usdviewq/headerContextMenu.py | 2 +- pxr/usdImaging/lib/usdviewq/mainWindow.py | 23 +- .../lib/usdviewq/nodeContextMenu.py | 4 +- .../lib/usdviewq/nodeContextMenuItems.py | 92 ++- pxr/usdImaging/lib/usdviewq/nodeViewItem.py | 3 +- pxr/usdImaging/lib/usdviewq/prettyPrint.py | 1 - .../lib/usdviewq/pythonInterpreter.py | 3 +- pxr/usdImaging/lib/usdviewq/scalarTypes.py | 18 +- pxr/usdImaging/lib/usdviewq/stageView.py | 44 +- .../katana/lib/usdKatana/readCamera.cpp | 5 +- .../lib/usdKatana/readConstraintTarget.cpp | 7 +- .../katana/lib/usdKatana/readGprim.cpp | 12 +- .../katana/lib/usdKatana/readNurbsPatch.cpp | 10 +- .../katana/lib/usdKatana/readPoints.cpp | 20 +- .../katana/lib/usdKatana/readXformable.cpp | 7 +- .../katana/lib/usdKatana/usdInArgs.cpp | 10 +- third_party/katana/lib/usdKatana/usdInArgs.h | 24 +- .../katana/lib/usdKatana/usdInPrivateData.cpp | 49 +- .../katana/lib/usdKatana/usdInPrivateData.h | 2 - third_party/katana/lib/usdKatana/utils.cpp | 13 +- third_party/katana/lib/usdKatana/utils.h | 5 + .../katana/plugin/pxrUsdIn/pxrUsdIn.cpp | 162 +++-- third_party/katana/plugin/vmp_usd/usdVMP.cpp | 30 +- third_party/katana/plugin/vmp_usd/usdVMP.h | 2 + .../maya/lib/pxrUsdMayaGL/CMakeLists.txt | 1 + .../maya/lib/pxrUsdMayaGL/batchRenderer.cpp | 125 +++- .../maya/lib/pxrUsdMayaGL/batchRenderer.h | 10 +- .../lib/pxrUsdMayaGL/softSelectHelper.cpp | 138 ++++ .../maya/lib/pxrUsdMayaGL/softSelectHelper.h | 93 +++ .../AEpxrUsdReferenceAssemblyTemplate.py | 6 +- .../maya/lib/usdMaya/MayaMeshWriter.cpp | 199 +++-- third_party/maya/lib/usdMaya/MayaMeshWriter.h | 84 ++- .../lib/usdMaya/MayaMeshWriter_PrimVars.cpp | 688 ++++++++++++------ .../lib/usdMaya/MayaNurbsSurfaceWriter.cpp | 28 +- third_party/maya/lib/usdMaya/proxyShape.cpp | 37 + third_party/maya/lib/usdMaya/proxyShape.h | 13 +- .../maya/lib/usdMaya/referenceAssembly.cpp | 2 + .../maya/lib/usdMaya/referenceAssembly.h | 15 +- third_party/maya/lib/usdMaya/util.cpp | 313 +++++--- third_party/maya/lib/usdMaya/util.h | 56 +- 144 files changed, 3470 insertions(+), 1466 deletions(-) create mode 100644 .travis.yml create mode 100644 pxr/imaging/lib/garch/__init__.py rename pxr/imaging/lib/{glfq => garch}/glPlatformDebugContext.cpp (79%) rename pxr/imaging/lib/{glfq => garch}/glPlatformDebugContext.h (78%) rename pxr/imaging/lib/{glfq/selectVisual.mm => garch/module.cpp} (74%) create mode 100644 pxr/imaging/lib/garch/moduleDeps.cpp rename pxr/imaging/lib/{glfq => garch}/wrapPlatformDebugContext.cpp (89%) create mode 100644 pxr/usd/lib/usdUI/overview.dox create mode 100644 third_party/maya/lib/pxrUsdMayaGL/softSelectHelper.cpp create mode 100644 third_party/maya/lib/pxrUsdMayaGL/softSelectHelper.h diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000000..f4f461c795 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,157 @@ +# +# 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. +# + +# USD requires several dependencies that are available via +# apt-get if using the trusty build environment. +sudo: required +dist: trusty + +language: cpp + +branches: + only: + - master + - dev + +before_install: + - sudo apt-get -qq update + +install: + ###### + ### DEPENDENCIES FOR USD CORE + ##### + + ### boost v1.55 + ### We install only the packages we need for faster turnaround + - sudo apt-get install libboost-iostreams1.55.0 libboost-iostreams1.55-dev + - sudo apt-get install libboost-python1.55.0 libboost-python1.55-dev + - sudo apt-get install libboost-regex1.55.0 libboost-regex1.55-dev + - sudo apt-get install libboost-system1.55.0 libboost-system1.55-dev + - sudo apt-get install libboost-program-options1.55.0 libboost-program-options1.55-dev + + ### double-conversion + ### USD docs currently claim we require 1.1.1, but apt-get gives us 2.0.1 on trusty. + ### Building 1.1.1 as a shared library is annoying, so we'll go with this for now. + - sudo apt-get install libdouble-conversion-dev + + ### Intel TBB v4.3 update 1 + - if [ ! -d "$HOME/tbb43_20141023oss/lib" ]; then + wget https://www.threadingbuildingblocks.org/sites/default/files/software_releases/linux/tbb43_20141023oss_lin.tgz -O /tmp/tbb.tgz; + tar -xvzf /tmp/tbb.tgz -C $HOME; + else + echo 'Using cached TBB'; + fi + + ### ilmbase and OpenEXR 2.2.0 + - if [ ! -d "$HOME/openexr/lib" ]; then + wget http://download.savannah.nongnu.org/releases/openexr/ilmbase-2.2.0.tar.gz -O /tmp/ilmbase.tgz; + tar -xvzf /tmp/ilmbase.tgz -C $HOME; + pushd $HOME/ilmbase-2.2.0; + ./configure --prefix=$HOME/openexr; + make && make install; + popd; + wget http://download.savannah.nongnu.org/releases/openexr/openexr-2.2.0.tar.gz -O /tmp/openexr.tgz; + tar -xvzf /tmp/openexr.tgz -C $HOME; + pushd $HOME/openexr-2.2.0; + ./configure --prefix=$HOME/openexr --with-pkg-config=no LDFLAGS="-Wl,-rpath -Wl,$HOME/openexr/lib"; + make && make install; + popd; + else + echo 'Using cached OpenEXR'; + fi + + ###### + ### DEPENDENCIES FOR IMAGING + ##### + + ### GLEW 1.10.0 + - sudo apt-get install libglew-dev + + ### OpenSubdiv 3.0.0 + - sudo apt-get install libxrandr-dev libxcursor-dev libxinerama-dev libglfw-dev + - if [ ! -d "$HOME/osd/lib" ]; then + wget https://github.com/PixarAnimationStudios/OpenSubdiv/archive/v3_0_0.tar.gz -O /tmp/osd.tgz; + tar -xvzf /tmp/osd.tgz -C $HOME; + pushd $HOME/OpenSubdiv-3_0_0; + mkdir build && cd build; + cmake -DCMAKE_INSTALL_PREFIX=$HOME/osd -DNO_EXAMPLES=1 -DNO_TUTORIALS=1 -DNO_REGRESSION=1 -D NO_MAYA=1 -D NO_PTEX=1 -D NO_DOC=1 -D NO_OMP=1 -D NO_TBB=1 -D NO_CUDA=1 -D NO_OPENCL=1 -D NO_CLEW=1 ..; + make && make install; + popd; + else + echo 'Using cached OpenSubdiv'; + fi + # XXX: To workaround issue #3, create a symlink at opensubdiv3/ pointing to opensubdiv/ + - rm -f $HOME/osd/include/opensubdiv3 && ln -s $HOME/osd/include/opensubdiv $HOME/osd/include/opensubdiv3 + + ### OpenImageIO 1.5.11 + - sudo apt-get install libboost-filesystem1.55.0 libboost-filesystem1.55-dev + - sudo apt-get install libboost-thread1.55.0 libboost-thread1.55-dev + - if [ ! -d "$HOME/oiio/lib" ]; then + wget https://github.com/OpenImageIO/oiio/archive/Release-1.5.11.tar.gz -O /tmp/oiio.tgz; + tar -xvzf /tmp/oiio.tgz -C $HOME; + pushd $HOME/oiio-Release-1.5.11; + mkdir build && cd build; + cmake -DCMAKE_INSTALL_PREFIX=$HOME/oiio -DILMBASE_HOME=$HOME/openexr -DOPENEXR_HOME=$HOME/openexr ..; + make && make install; + popd; + else + echo 'Using cached OpenImageIO'; + fi + + ### Ptex 2.0.30 + - if [ ! -d "$HOME/ptex/lib" ]; then + wget https://github.com/wdas/ptex/archive/v2.0.30.tar.gz -O /tmp/ptex.tgz; + tar -xvzf /tmp/ptex.tgz -C $HOME; + pushd $HOME/ptex-2.0.30/src; + make; + mv $HOME/ptex-2.0.30/install/* $HOME/ptex; + popd; + else + echo 'Using cached Ptex'; + fi + + ###### + ### DEPENDENCIES FOR USDIMAGING + ##### + + ### PySide 1.2.2 + - sudo apt-get install python-pyside pyside-tools + +cache: + directories: + - $HOME/openexr + - $HOME/osd + - $HOME/oiio + - $HOME/ptex + - $HOME/tbb43_20141023oss + +script: + - mkdir build && cd build + - cmake -DTBB_ROOT_DIR=$HOME/tbb43_20141023oss -DOPENEXR_LOCATION=$HOME/openexr -DOIIO_LOCATION=$HOME/oiio -DOPENSUBDIV_ROOT_DIR=$HOME/osd -DPTEX_LOCATION=$HOME/ptex -DPXR_VALIDATE_GENERATED_CODE=OFF .. + - echo 'Building with -j4' + # XXX: Need to explicitly build cameraUtil before hd due to missing dependency declaration. + # This is fixed in commit 880b04. + - make -j4 cameraUtil + - make -j4 + - make install diff --git a/CMakeLists.txt b/CMakeLists.txt index 46fa62493b..05218b3364 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,10 @@ project(usd) -cmake_minimum_required(VERSION 2.8.8) + +if (WIN32) + cmake_minimum_required(VERSION 3.1.1) +else() + cmake_minimum_required(VERSION 2.8.8) +endif() set(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake/defaults ${CMAKE_SOURCE_DIR}/cmake/modules diff --git a/README.md b/README.md index 06980d6b52..961ae16430 100644 --- a/README.md +++ b/README.md @@ -44,9 +44,9 @@ Dependencies | ---- | --------- | | C++ compiler | GCC 4.8, Clang 3.5, MSVC 14.0(VS 2015) | | C compiler | GCC 4.8, Clang 3.5, MSVC 14.0(VS 2015) | -| [CMake](https://cmake.org/documentation/) | 2.8.8 | +| [CMake](https://cmake.org/documentation/) | 2.8.8 (Linux/OS X), 3.1.1 (Windows) | | [Python](https://python.org) | 2.7.5 | -| [Boost](https://boost.org) | 1.55 | +| [Boost](https://boost.org) | 1.55 (Linux/OS X), 1.61.0 (Windows) | | [OpenEXR](https://openexr.org) | 2.2.0 | | [DoubleConversion](https://github.com/google/double-conversion) | 1.1.1 | | [Intel TBB](https://www.threadingbuildingblocks.org/) | 4.3.1 | @@ -95,7 +95,7 @@ make -j install #### On OS X (experimental) The following will generate an Xcode project that can be used to build USD. -See notes in the [Supported Platforms](#Supported-Platforms) section +See notes in the [Supported Platforms](#supported-platforms) section for more information. ```bash @@ -117,7 +117,7 @@ make -j install The following will generate a Visual Studio 2015 (the minimum required version) sln file which can be used to build USD. See notes in the -[Supported Platforms](#Supported-Platforms) section for more information. +[Supported Platforms](#supported-platforms) section for more information. ```powershell C:\Program Files\CMake\bin\cmake.exe ^ diff --git a/cmake/macros/Public.cmake b/cmake/macros/Public.cmake index 4d24c2146a..03efc94172 100644 --- a/cmake/macros/Public.cmake +++ b/cmake/macros/Public.cmake @@ -34,7 +34,7 @@ function(pxr_python_bins) file(READ ${pyFile} contents) string(REGEX REPLACE "/pxrpythonsubst" ${PXR_PYTHON_SHEBANG} contents "${contents}") - file(WRITE ${CMAKE_BINARY_DIR}/${pyFile} ${contents}) + file(WRITE ${CMAKE_BINARY_DIR}/${pyFile} "${contents}") install(PROGRAMS ${CMAKE_BINARY_DIR}/${pyFile} diff --git a/cmake/modules/FindPySide.cmake b/cmake/modules/FindPySide.cmake index b5722fb44f..045fc72873 100644 --- a/cmake/modules/FindPySide.cmake +++ b/cmake/modules/FindPySide.cmake @@ -37,6 +37,7 @@ execute_process( pySideImportResult ) -if (pySideImportResult EQUAL 0 AND EXISTS(${PYSIDEUICBINARY})) +if (pySideImportResult EQUAL 0 AND EXISTS ${PYSIDEUICBINARY}) + message(STATUS "Found PySide: ${PYSIDEUICBINARY}") set(PYSIDE_FOUND True) endif() diff --git a/pxr/base/lib/gf/frustum.cpp b/pxr/base/lib/gf/frustum.cpp index 9db372468a..27b533a576 100644 --- a/pxr/base/lib/gf/frustum.cpp +++ b/pxr/base/lib/gf/frustum.cpp @@ -58,7 +58,6 @@ GfFrustum::GfFrustum() : _projectionType(GfFrustum::Perspective) { _rotation.SetIdentity(); - _localToFrustum.SetIdentity(); } GfFrustum::GfFrustum(const GfVec3d &position, const GfRotation &rotation, @@ -70,8 +69,7 @@ GfFrustum::GfFrustum(const GfVec3d &position, const GfRotation &rotation, _window(window), _nearFar(nearFar), _viewDistance(viewDistance), - _projectionType(projectionType), - _localToFrustum(1.0) + _projectionType(projectionType) { } @@ -82,8 +80,7 @@ GfFrustum::GfFrustum(const GfMatrix4d &camToWorldXf, _window(window), _nearFar(nearFar), _viewDistance(viewDistance), - _projectionType(projectionType), - _localToFrustum(1.0) + _projectionType(projectionType) { SetPositionAndRotationFromMatrix(camToWorldXf); } @@ -653,6 +650,38 @@ GfFrustum::ComputeCorners() const return corners; } +vector +GfFrustum::ComputeCornersAtDistance(double d) const +{ + const GfVec2d &winMin = _window.GetMin(); + const GfVec2d &winMax = _window.GetMax(); + + vector corners; + corners.reserve(4); + + if (_projectionType == Perspective) { + // Similar to ComputeCorners + corners.push_back(GfVec3d(d * winMin[0], d * winMin[1], -d)); + corners.push_back(GfVec3d(d * winMax[0], d * winMin[1], -d)); + corners.push_back(GfVec3d(d * winMin[0], d * winMax[1], -d)); + corners.push_back(GfVec3d(d * winMax[0], d * winMax[1], -d)); + } + else { + corners.push_back(GfVec3d(winMin[0], winMin[1], -d)); + corners.push_back(GfVec3d(winMax[0], winMin[1], -d)); + corners.push_back(GfVec3d(winMin[0], winMax[1], -d)); + corners.push_back(GfVec3d(winMax[0], winMax[1], -d)); + } + + // Each corner is then transformed into world space by the inverse + // of the view matrix. + const GfMatrix4d m = ComputeViewInverse(); + for (int i = 0; i < 4; i++) + corners[i] = m.Transform(corners[i]); + + return corners; +} + GfFrustum GfFrustum::ComputeNarrowedFrustum(const GfVec2d &point, const GfVec2d &halfSize) const @@ -1060,43 +1089,6 @@ GfFrustum::Intersects(const GfVec3d &p0, return false; } -//---------------------------------------------------------------------- -// Local space intersection routines. -// -// These routines are the most efficient way to intersect geometry with -// the frustum. -// -// For now, they consist simply of transforming the point into whatever -// space the frustum is in (as set in GfFrustum::SetTransform). In the -// future these routines can be made about twice as fast by replacing -// _localToFrustum with a matrix that carries the point into the space -// of the "normalized frustum". The normalized frustum has all its vertices -// at with coordinates that are 0, 1, or -1. -// -bool -GfFrustum::IntersectsInLocalSpace(const GfVec3d &p1) const -{ - GfVec3d frustumP1 = _localToFrustum.Transform(p1); - return Intersects( frustumP1); -} - -bool -GfFrustum::IntersectsInLocalSpace(const GfVec3d &p1, const GfVec3d &p2) const -{ - GfVec3d frustumP1 = _localToFrustum.Transform(p1); - GfVec3d frustumP2 = _localToFrustum.Transform(p2); - return Intersects( frustumP1, frustumP2); -} - -bool -GfFrustum::IntersectsInLocalSpace(const GfVec3d &p1, const GfVec3d &p2, const GfVec3d &p3) const -{ - GfVec3d frustumP1 = _localToFrustum.Transform(p1); - GfVec3d frustumP2 = _localToFrustum.Transform(p2); - GfVec3d frustumP3 = _localToFrustum.Transform(p3); - return Intersects( frustumP1, frustumP2, frustumP3); -} - void GfFrustum::_DirtyFrustumPlanes() { diff --git a/pxr/base/lib/gf/frustum.h b/pxr/base/lib/gf/frustum.h index 2ccd27d28d..6b2ededd07 100644 --- a/pxr/base/lib/gf/frustum.h +++ b/pxr/base/lib/gf/frustum.h @@ -430,6 +430,17 @@ class GfFrustum { GF_API std::vector ComputeCorners() const; + /// Returns the world-space corners of the intersection of the frustum + /// with a plane parallel to the near/far plane at distance d from the + /// apex, ordered as: + /// \li Left bottom + /// \li Right bottom + /// \li Left top + /// \li Right top + /// In particular, it gives the partial result of ComputeCorners when given + /// near or far distance. + std::vector ComputeCornersAtDistance(double d) const; + /// Returns a frustum that is a narrowed-down version of this frustum, /// such that the frustum rectangle on the near plane encloses \p point /// with at most \p halfSize[0] distance on the left and right and at most @@ -500,26 +511,6 @@ class GfFrustum { /// ///@{ - /// Describes the space in which the geometry is represented. Used only in - /// conjuction with GfFrustum::IntersectsInLocalSpace. The matrix is - /// carries the space of the geometry into the space of the frustum. - /// - /// The IntersectsInLocalSpace routines are the most efficient way to - /// intersect geometry with an arbitrary frustum. - /// - /// Note: There currently isn't a local space intersection routine for - /// bboxes, but if the need arises there is no difficulty in principle to - /// adding it. - /// - void SetLocalSpaceForIntersection( const GfMatrix4d &localToFrustum) { - _localToFrustum = localToFrustum; - } - - /// Returns the matrix set by \c SetLocalSpaceForIntersection(). - GfMatrix4d const& GetLocalSpaceForIntersection() const { - return _localToFrustum; - } - /// Returns true if the given axis-aligned bbox is inside or intersecting /// the frustum. Otherwise, it returns false. Useful when doing picking or /// frustum culling. @@ -628,9 +619,6 @@ class GfFrustum { // Projection type. ProjectionType _projectionType; - // For efficient intersection in local space - GfMatrix4d _localToFrustum; - // Cached planes. // If empty, the planes have not been calculated. mutable std::vector _planes; diff --git a/pxr/base/lib/gf/testenv/testGfFrustum.py b/pxr/base/lib/gf/testenv/testGfFrustum.py index 8a173e31fa..f686efb7c8 100644 --- a/pxr/base/lib/gf/testenv/testGfFrustum.py +++ b/pxr/base/lib/gf/testenv/testGfFrustum.py @@ -56,8 +56,8 @@ def test_PlaneIntersection(self): def test_Position(self): f1 = Gf.Frustum() f2 = Gf.Frustum() - f1.position = Gf.Vec3d(1, 0, 0); - f2.position = Gf.Vec3d(0, 1, 0); + f1.position = Gf.Vec3d(1, 0, 0) + f2.position = Gf.Vec3d(0, 1, 0) self.assertNotEqual(f1, f2) def test_Properties(self): @@ -314,7 +314,7 @@ def test_IntersectionViewVolume(self): 0.0, 4.2418940586972074, 0.0, 0.0, 0.0, 0.0, -1, -1.0, 0.0, 0.0, -20, 0.0) - viewProjMat = viewMat * projMat; + viewProjMat = viewMat * projMat # a typical box entirely in the view b = Gf.BBox3d( Gf.Range3d( Gf.Vec3d( 0, 0, 0 ), Gf.Vec3d( 1, 1, 1 ) ) ) @@ -379,6 +379,21 @@ def test_ConstructFromMatrix(self): self.assertEqual(len(corners), len(results)) for i in range(len(results)): self.assertTrue(Gf.IsClose(corners[i], results[i], 0.0001)) + + corners = f.ComputeCornersAtDistance(20) + for i in range(len(corners)): + self.assertTrue(Gf.IsClose(corners[i], results[i], 0.0001)) + + corners = f.ComputeCornersAtDistance(90) + for i in range(len(corners)): + self.assertTrue(Gf.IsClose(corners[i], results[i+4], 0.0001)) + + corners = f.ComputeCornersAtDistance((20 + 90) / 2.0) + for i in range(len(corners)): + self.assertTrue( + Gf.IsClose(corners[i], (results[i] + results[i+4]) / 2.0, + 0.0001)) + if __name__ == '__main__': unittest.main() diff --git a/pxr/base/lib/gf/testenv/testGfMatrix.py b/pxr/base/lib/gf/testenv/testGfMatrix.py index 75948d456c..a197180c7d 100644 --- a/pxr/base/lib/gf/testenv/testGfMatrix.py +++ b/pxr/base/lib/gf/testenv/testGfMatrix.py @@ -126,7 +126,7 @@ def runTest(self): v = Vec() for i in range(v.dimension): v[i] = i - m1 = Matrix().SetDiagonal(v); + m1 = Matrix().SetDiagonal(v) m2 = Matrix(0) for i in range(m2.dimension[0]): m2[i,i] = i diff --git a/pxr/base/lib/gf/testenv/testGfRange.py b/pxr/base/lib/gf/testenv/testGfRange.py index 2cdadaac52..3e3d8d7a9c 100644 --- a/pxr/base/lib/gf/testenv/testGfRange.py +++ b/pxr/base/lib/gf/testenv/testGfRange.py @@ -52,9 +52,9 @@ def runTest(self): v = makeValue(Value, [1, 2, 3, 4]) r = Range() - r.min = v; + r.min = v self.assertEqual(r.min, v) - r.max = v; + r.max = v self.assertEqual(r.max, v) r = Range() diff --git a/pxr/base/lib/gf/testenv/testGfRay.py b/pxr/base/lib/gf/testenv/testGfRay.py index 06a41cee38..81cb069ef0 100644 --- a/pxr/base/lib/gf/testenv/testGfRay.py +++ b/pxr/base/lib/gf/testenv/testGfRay.py @@ -308,7 +308,7 @@ def test_IntersectCylinder(self): # Ray behind cylinder, orthogonal to surface x = radius * (1 + random.uniform(epsilon, 1)) - distance = x - radius; + distance = x - radius ray = Gf.Ray(Gf.Vec3d(-x, 0, 0), Gf.Vec3d().XAxis()) (hit, enter, exit) = ray.Intersect(origin, axis, radius) @@ -434,7 +434,7 @@ def test_IntersectCone(self): self.assertAlmostEqual(exit, radius, delta=epsilon) # Ray behind cone, orthogonal to axis - distance = x - radius; + distance = x - radius ray = Gf.Ray(Gf.Vec3d(-x, 0, 0), Gf.Vec3d().XAxis()) (hit, enter, exit) = ray.Intersect(origin, axis, radius, height) diff --git a/pxr/base/lib/gf/testenv/testGfSize.py b/pxr/base/lib/gf/testenv/testGfSize.py index 4b57e55601..95b785d98e 100644 --- a/pxr/base/lib/gf/testenv/testGfSize.py +++ b/pxr/base/lib/gf/testenv/testGfSize.py @@ -46,12 +46,12 @@ def runTest(self): if Size.dimension == 2: self.assertIsInstance(Size(Gf.Vec2i()), Size) self.assertIsInstance(Size(3, 4), Size) - s = Size(); + s = Size() self.assertEqual(s.Set(3,4), Size(3,4)) elif Size.dimension == 3: self.assertIsInstance(Size(Gf.Vec3i()), Size) self.assertIsInstance(Size(3, 4, 5), Size) - s = Size(); + s = Size() self.assertEqual(s.Set(3,4,5), Size(3,4,5)) s = makeValue(Size, (1,2,3)) diff --git a/pxr/base/lib/gf/testenv/testGfVec.py b/pxr/base/lib/gf/testenv/testGfVec.py index f5bdf158ab..8c71adce0a 100644 --- a/pxr/base/lib/gf/testenv/testGfVec.py +++ b/pxr/base/lib/gf/testenv/testGfVec.py @@ -297,18 +297,18 @@ def MethodsTest(self, Vec): # Normalize... SetVec( v1, [3, 1, 4, 1] ) - v2 = Vec(v1); + v2 = Vec(v1) v2.Normalize() nv = Gf.GetNormalized( v1 ) nv2 = v1.GetNormalized() - nvcheck = v1 / Gf.GetLength(v1); + nvcheck = v1 / Gf.GetLength(v1) self.assertTrue(Gf.IsClose(nv, nvcheck, eps)) self.assertTrue(Gf.IsClose(nv2, nvcheck, eps)) self.assertTrue(Gf.IsClose(v2, nvcheck, eps)) SetVec( v1, [3, 1, 4, 1] ) nv = v1.GetNormalized() - nvcheck = v1 / Gf.GetLength(v1); + nvcheck = v1 / Gf.GetLength(v1) self.assertEqual(nv, nvcheck) SetVec(v1, [0,0,0,0]) @@ -357,7 +357,7 @@ def MethodsTest(self, Vec): for i in range(Vec.dimension): v1 = Vec.Axis(i) v2 = Vec() - v2[i] = 1; + v2[i] = 1 self.assertEqual(v1, v2) v1 = Vec.XAxis() diff --git a/pxr/base/lib/gf/wrapFrustum.cpp b/pxr/base/lib/gf/wrapFrustum.cpp index 5bc6011225..01a6eb9c58 100644 --- a/pxr/base/lib/gf/wrapFrustum.cpp +++ b/pxr/base/lib/gf/wrapFrustum.cpp @@ -205,6 +205,9 @@ void wrapFrustum() .def("ComputeCorners", &This::ComputeCorners, return_value_policy()) + .def("ComputeCornersAtDistance", &This::ComputeCornersAtDistance, + return_value_policy()) + .def("ComputeNarrowedFrustum", (GfFrustum (This::*)(const GfVec2d &, const GfVec2d &) const) &This::ComputeNarrowedFrustum) diff --git a/pxr/base/lib/plug/testPlug.py b/pxr/base/lib/plug/testPlug.py index 8690f3b962..2817fb9cc3 100644 --- a/pxr/base/lib/plug/testPlug.py +++ b/pxr/base/lib/plug/testPlug.py @@ -252,24 +252,24 @@ def test_ErrorCases(self): # try to register a non-existent plugin path self.assertFalse(os.path.exists('/nowhere')) Plug.Registry().RegisterPlugins('/nowhere') - self.assertEqual(listener.numReceived, 0); + self.assertEqual(listener.numReceived, 0) # try to register an incomplete plugin badPluginPath = testPluginsDso + '/TestPlugDsoIncomplete.framework/Resources/' Plug.Registry().RegisterPlugins(badPluginPath) - self.assertEqual(listener.numReceived, 0); + self.assertEqual(listener.numReceived, 0) # try to register an incomplete python plugin path badPluginPath = testPluginsPython + '/TestPlugModuleIncomplete' Plug.Registry().RegisterPlugins(badPluginPath) - self.assertEqual(listener.numReceived, 0); + self.assertEqual(listener.numReceived, 0) # try to find a plugin for a Tf type which doesn't exist unknownPlug = None with self.assertRaises(RuntimeError): unknownPlug = Plug.Registry().GetPluginForType(Tf.Type.FindByName('Bad')) self.assertFalse(unknownPlug) - self.assertEqual(listener.numReceived, 0); + self.assertEqual(listener.numReceived, 0) # try to load an unloadable plugin badPlugin = Plug.Registry().GetPluginForType('TestPlugUnloadable') @@ -318,4 +318,4 @@ def test_ErrorCases(self): Plug.Registry().RegisterPlugins(testPluginsDsoSearch) Plug.Registry().RegisterPlugins(testPluginsPythonSearch) self.assertEqual(allplugins, Plug.Registry().GetAllPlugins()) - self.assertEqual(listener.numReceived, 0); + self.assertEqual(listener.numReceived, 0) diff --git a/pxr/base/lib/tf/pyFunction.h b/pxr/base/lib/tf/pyFunction.h index deed2dc3b3..a67595c8eb 100644 --- a/pxr/base/lib/tf/pyFunction.h +++ b/pxr/base/lib/tf/pyFunction.h @@ -146,22 +146,23 @@ struct TfPyFunctionFromPython // for most usage patterns. object callable(handle<>(borrowed(src))); - - if (PyMethod_Check(callable.ptr())) { + PyObject *pyCallable = callable.ptr(); + PyObject *self = + PyMethod_Check(pyCallable) ? PyMethod_GET_SELF(pyCallable) : NULL; + + if (self) { // Deconstruct the method and attempt to get a weak reference to // the self instance. - PyObject *method = callable.ptr(); - object cls(handle<>(borrowed(PyMethod_GET_CLASS(method)))); - object func(handle<>(borrowed(PyMethod_GET_FUNCTION(method)))); - object weakSelf - (handle<>(PyWeakref_NewRef(PyMethod_GET_SELF(method), NULL))); + object cls(handle<>(borrowed(PyMethod_GET_CLASS(pyCallable)))); + object func(handle<>(borrowed(PyMethod_GET_FUNCTION(pyCallable)))); + object weakSelf(handle<>(PyWeakref_NewRef(self, NULL))); new (storage) FuncType(bind(CallMethod, TfPyObjWrapper(func), TfPyObjWrapper(weakSelf), TfPyObjWrapper(cls) BOOST_PP_ENUM_TRAILING(N, PLACEHOLDER, ~))); - } else if (PyObject_HasAttrString(callable.ptr(), "__name__") and + } else if (PyObject_HasAttrString(pyCallable, "__name__") and extract(callable.attr("__name__"))() == "") { // Explicitly hold on to strong references to lambdas. new (storage) @@ -170,7 +171,7 @@ struct TfPyFunctionFromPython } else { // Attempt to get a weak reference to the callable. if (PyObject *weakCallable = - PyWeakref_NewRef(callable.ptr(), NULL)) { + PyWeakref_NewRef(pyCallable, NULL)) { new (storage) FuncType(bind(CallWeak, TfPyObjWrapper(object(handle<>(weakCallable))) diff --git a/pxr/base/lib/tf/pyInterpreter.cpp b/pxr/base/lib/tf/pyInterpreter.cpp index dc43ef3ac6..1f63d25231 100644 --- a/pxr/base/lib/tf/pyInterpreter.cpp +++ b/pxr/base/lib/tf/pyInterpreter.cpp @@ -31,6 +31,7 @@ #include "pxr/base/arch/fileSystem.h" #include "pxr/base/arch/symbols.h" #include "pxr/base/arch/systemInfo.h" +#include "pxr/base/arch/threads.h" #include #include @@ -67,6 +68,15 @@ TfPyInitialize() std::lock_guard lock(mutex); if (!Py_IsInitialized()) { + + if (not ArchIsMainThread() and not PyEval_ThreadsInitialized()) { + // Python claims that PyEval_InitThreads "should be called in the + // main thread before creating a second thread or engaging in any + // other thread operations." So we'll issue a warning here. + TF_WARN("Calling PyEval_InitThreads() for the first time outside " + "the 'main thread'. Python doc says not to do this."); + } + static std::string programName(ArchGetExecutablePath()); // Initialize Python threading. This grabs the GIL. We'll release it diff --git a/pxr/base/lib/tf/testenv/testTfPyDiagnosticNotices.py b/pxr/base/lib/tf/testenv/testTfPyDiagnosticNotices.py index d22193faf7..d9f8be4495 100644 --- a/pxr/base/lib/tf/testenv/testTfPyDiagnosticNotices.py +++ b/pxr/base/lib/tf/testenv/testTfPyDiagnosticNotices.py @@ -96,24 +96,24 @@ def test_Notices(self): self.log.info("Issuing a couple of different types of errors.") try: - Tf.RaiseRuntimeError("Runtime error!"); + Tf.RaiseRuntimeError("Runtime error!") assert False, "expected exception" except Tf.ErrorException: pass try: - Tf.RaiseCodingError("Coding error!"); + Tf.RaiseCodingError("Coding error!") assert False, "expected exception" except Tf.ErrorException: pass self.log.info("Issuing a few generic warnings.") - Tf.Warn("Warning 1"); - Tf.Warn("Warning 2"); - Tf.Warn("Warning 3"); + Tf.Warn("Warning 1") + Tf.Warn("Warning 2") + Tf.Warn("Warning 3") self.log.info("Issuing a status message.") - Tf.Status("Status: Almost done testing."); + Tf.Status("Status: Almost done testing.") # Assert that two errors, three warnings and one status message were # issued. diff --git a/pxr/base/lib/tf/testenv/testTfPython.py b/pxr/base/lib/tf/testenv/testTfPython.py index 6dbf7491ac..3d8f1aad4d 100644 --- a/pxr/base/lib/tf/testenv/testTfPython.py +++ b/pxr/base/lib/tf/testenv/testTfPython.py @@ -324,6 +324,8 @@ def method(self): del l self.assertEqual('python lambda', Tf._invokeTestCallback()) + # Test unbound instance method. + self.assertEqual('test', Tf._callUnboundInstance(str.lower, "TEST")) # the callback is a function, it should not stay alive def func(): diff --git a/pxr/base/lib/tf/testenv/testTfType.py b/pxr/base/lib/tf/testenv/testTfType.py index 3c972819b6..a101bad81b 100644 --- a/pxr/base/lib/tf/testenv/testTfType.py +++ b/pxr/base/lib/tf/testenv/testTfType.py @@ -198,7 +198,7 @@ def test_FindDerivedByName(self): def test_PythonSubclassOfCppClass(self): class TestPyDerived( Tf.TestCppBase ): def TestVirtual(self): - return 123; + return 123 tTestCppBase = Tf.Type.Find( Tf.TestCppBase ) tTestPyDerived = Tf.Type.Define( TestPyDerived ) diff --git a/pxr/base/lib/tf/wrapTestTfPython.cpp b/pxr/base/lib/tf/wrapTestTfPython.cpp index 986427f6b6..887642ac4e 100644 --- a/pxr/base/lib/tf/wrapTestTfPython.cpp +++ b/pxr/base/lib/tf/wrapTestTfPython.cpp @@ -326,6 +326,10 @@ static string stringStringCallback(boost::function const &f) { return f("c++ is calling..."); } +static string callUnboundInstance(boost::function const &f, + string const &str) { + return f(str); +} static TfStaticData > _testCallback; @@ -444,6 +448,7 @@ void wrapTf_TestTfPython() def("_stringStringCallback", stringStringCallback); def("_setTestCallback", setTestCallback); def("_invokeTestCallback", invokeTestCallback); + def("_callUnboundInstance", callUnboundInstance); TfPyWrapEnum(); diff --git a/pxr/base/lib/vt/dictionary.cpp b/pxr/base/lib/vt/dictionary.cpp index 54580215ef..a6e5b1b65e 100644 --- a/pxr/base/lib/vt/dictionary.cpp +++ b/pxr/base/lib/vt/dictionary.cpp @@ -59,6 +59,11 @@ VtDictionary::VtDictionary(VtDictionary const& other) { if (other._dictMap) _dictMap.reset(new _Map(*other._dictMap)); } + +VtDictionary::VtDictionary(std::initializer_list init) + : _dictMap(new _Map(init.begin(), init.end())) +{ +} VtDictionary& VtDictionary::operator=(VtDictionary const& other) { if (this != &other) diff --git a/pxr/base/lib/vt/dictionary.h b/pxr/base/lib/vt/dictionary.h index 080c94d437..7841724fe2 100644 --- a/pxr/base/lib/vt/dictionary.h +++ b/pxr/base/lib/vt/dictionary.h @@ -40,6 +40,7 @@ #include #include +#include #include #include @@ -186,6 +187,9 @@ class VtDictionary { VT_API VtDictionary(VtDictionary && other) = default; + /// Creates a new VtDictionary from a braced initializer list. + VtDictionary(std::initializer_list init); + /// Copy assignment operator VT_API VtDictionary& operator=(VtDictionary const& other); diff --git a/pxr/base/lib/vt/testenv/testVtArray.py b/pxr/base/lib/vt/testenv/testVtArray.py index 56d4e5f711..cb72f44943 100644 --- a/pxr/base/lib/vt/testenv/testVtArray.py +++ b/pxr/base/lib/vt/testenv/testVtArray.py @@ -106,7 +106,7 @@ def test_VtArraySlicingVsPythonSlicing(self): for start in range(-2, 7): for stop in range(-2, 7): for step in range(-5, 6): - if step == 0 : break; + if step == 0 : break sub_a = a[start:stop:step] sub_l = l[start:stop:step] self.assertEqual(len(a), len(l)) diff --git a/pxr/base/lib/vt/testenv/testVtCpp.cpp b/pxr/base/lib/vt/testenv/testVtCpp.cpp index 0ae0654d7c..9655a16c69 100644 --- a/pxr/base/lib/vt/testenv/testVtCpp.cpp +++ b/pxr/base/lib/vt/testenv/testVtCpp.cpp @@ -619,6 +619,28 @@ testDictionaryIterators() } } +static void +testDictionaryInitializerList() +{ + const VtDictionary dict{}; + TF_AXIOM(dict.empty()); + + const VtDictionary dict2 = { + { "key_a", VtValue(1) }, + { "key_b", VtValue(2) } + }; + TF_AXIOM(not dict2.empty()); + + int i = 0; + for (const string& k : {"key_a", "key_b"}) { + auto it = dict2.find(k); + TF_AXIOM(it != dict2.end()); + TF_AXIOM(it->first == k); + TF_AXIOM(it->second.IsHolding()); + TF_AXIOM(it->second.UncheckedGet() == ++i); + } +} + // dest and source types are flipped so we can allow compiler to infer // source type template @@ -1109,6 +1131,7 @@ int main(int argc, char *argv[]) testDictionaryKeyPathAPI(); testDictionaryOverRecursive(); testDictionaryIterators(); + testDictionaryInitializerList(); testDictionaryPyFormatting(); testValue(); diff --git a/pxr/base/lib/work/loops.h b/pxr/base/lib/work/loops.h index 1adf263c7e..7edd5049a3 100644 --- a/pxr/base/lib/work/loops.h +++ b/pxr/base/lib/work/loops.h @@ -79,18 +79,19 @@ WorkParallelForN(size_t n, Fn &&callback) class Work_ParallelForN_TBB: boost::noncopyable { public: - // Private constructor because no one is allowed to create one of - // these objects from the outside. - Work_ParallelForN_TBB(Fn &&fn) : _fn(std::forward(fn)) { } - Work_ParallelForN_TBB(const Work_ParallelForN_TBB& rhs): - _fn(std::move(rhs._fn)) {} + Work_ParallelForN_TBB(Fn &fn) : _fn(fn) { } void operator()(const tbb::blocked_range &r) const { + // Note that we std::forward _fn using Fn in order get the + // right operator(). + // We maintain the right type in this way: + // If Fn is T&, then reference collapsing gives us T& for _fn + // If Fn is T, then std::forward correctly gives us T&& for _fn std::forward(_fn)(r.begin(), r.end()); } private: - Fn &&_fn; + Fn &_fn; }; // Note that for the tbb version in the future, we will likely want to @@ -99,7 +100,7 @@ WorkParallelForN(size_t n, Fn &&callback) // parent context, so we create an isolated task group context. tbb::task_group_context ctx(tbb::task_group_context::isolated); tbb::parallel_for(tbb::blocked_range(0,n), - Work_ParallelForN_TBB(std::forward(callback)), + Work_ParallelForN_TBB(callback), ctx); } else { diff --git a/pxr/base/lib/work/testenv/testWorkLoops.cpp b/pxr/base/lib/work/testenv/testWorkLoops.cpp index b55c90394d..58c787e099 100644 --- a/pxr/base/lib/work/testenv/testWorkLoops.cpp +++ b/pxr/base/lib/work/testenv/testWorkLoops.cpp @@ -170,7 +170,7 @@ main(int argc, char **argv) WorkSetMaximumConcurrencyLimit(); std::cout << "Initialized with " << - WorkGetMaximumConcurrencyLimit() << " cores..." << std::endl; + WorkGetPhysicalConcurrencyLimit() << " cores..." << std::endl; double tbbSeconds = _DoTBBTest(not perfMode, arraySize, numIterations); diff --git a/pxr/base/lib/work/testenv/testWorkThreadLimits.cpp b/pxr/base/lib/work/testenv/testWorkThreadLimits.cpp index 3c47d968b8..9f6d73dcda 100644 --- a/pxr/base/lib/work/testenv/testWorkThreadLimits.cpp +++ b/pxr/base/lib/work/testenv/testWorkThreadLimits.cpp @@ -53,11 +53,23 @@ _CountThreads(size_t begin, size_t end) _uniqueThreads->insert(pthread_self()); } +static size_t +_ExpectedLimit(const size_t envVal, const size_t n) +{ + // If envVal is non-zero, it wins over n! + return envVal ? envVal : n; +} + static void -_TestThreadLimit(size_t n) +_TestThreadLimit(const size_t envVal, const size_t n) { + const size_t expectedN = _ExpectedLimit(envVal, n); + if (expectedN != n) { + std::cout << " env setting overrides n = " << n << "\n"; + } + const size_t numSamples = 1000000; - std::cout << " maximum " << n << " threads\n"; + std::cout << " expecting maximum " << expectedN << " threads\n"; _uniqueThreads->clear(); @@ -65,56 +77,55 @@ _TestThreadLimit(size_t n) std::cout << " TBB used " << _uniqueThreads->size() << '\n'; - if (_uniqueThreads->size() > n) { + if (_uniqueThreads->size() > expectedN) { TF_FATAL_ERROR("TBB expected less than or equal to %zu threads, got %zu", - n, _uniqueThreads->size()); + expectedN, _uniqueThreads->size()); } } static void -_TestArguments() +_TestArguments(const size_t envVal) { - size_t numCores = WorkGetMaximumConcurrencyLimit(); + // Note that if envVal is set (i.e. non-zero) it will always win over the + // value supplied through the API calls. - // These tests assume we have at least 4 cores. - TF_AXIOM(numCores >= 4); + // Set to maximum concurrency, which should remain within envVal. + const size_t numCores = WorkGetPhysicalConcurrencyLimit(); + WorkSetConcurrencyLimitArgument(numCores); + TF_AXIOM(WorkGetConcurrencyLimit() == _ExpectedLimit(envVal, numCores)); - // n = 0, means full threading + // n = 0, means "no change" WorkSetConcurrencyLimitArgument(0); - TF_AXIOM(WorkGetConcurrencyLimit() == numCores); + TF_AXIOM(WorkGetConcurrencyLimit() == _ExpectedLimit(envVal, numCores)); // n = 1 means no threading WorkSetConcurrencyLimitArgument(1); - TF_AXIOM(WorkGetConcurrencyLimit() == 1); + TF_AXIOM(WorkGetConcurrencyLimit() == _ExpectedLimit(envVal, 1)); // n = 3 means 3 WorkSetConcurrencyLimitArgument(3); - TF_AXIOM(WorkGetConcurrencyLimit() == 3); - - // n = numCores means numCores - WorkSetConcurrencyLimitArgument(numCores); - TF_AXIOM(WorkGetConcurrencyLimit() == numCores); + TF_AXIOM(WorkGetConcurrencyLimit() == _ExpectedLimit(envVal, 3)); - // n = 1000 means max + // n = 1000 means 1000 WorkSetConcurrencyLimitArgument(1000); - TF_AXIOM(WorkGetConcurrencyLimit() == numCores); + TF_AXIOM(WorkGetConcurrencyLimit() == _ExpectedLimit(envVal, 1000)); // n = -1 means numCores - 1 WorkSetConcurrencyLimitArgument(-1); - TF_AXIOM(WorkGetConcurrencyLimit() == numCores-1); + TF_AXIOM(WorkGetConcurrencyLimit() == _ExpectedLimit(envVal, numCores-1)); // n = -3 means numCores - 3 WorkSetConcurrencyLimitArgument(-3); - TF_AXIOM(WorkGetConcurrencyLimit() == numCores-3); + TF_AXIOM(WorkGetConcurrencyLimit() == _ExpectedLimit(envVal, numCores-3)); // n = -numCores means 1 (no threading) WorkSetConcurrencyLimitArgument(-numCores); - TF_AXIOM(WorkGetConcurrencyLimit() == 1); + TF_AXIOM(WorkGetConcurrencyLimit() == _ExpectedLimit(envVal, 1)); // n = -numCores*10 means 1 (no threading) WorkSetConcurrencyLimitArgument(-numCores*10); - TF_AXIOM(WorkGetConcurrencyLimit() == 1); + TF_AXIOM(WorkGetConcurrencyLimit() == _ExpectedLimit(envVal, 1)); } struct _RawTBBCounter @@ -128,8 +139,8 @@ int main(int argc, char **argv) { // Read the env setting used to limit threading - size_t limit = TfGetEnvSetting(PXR_WORK_THREAD_LIMIT); - std::cout << "PXR_WORK_THREAD_LIMIT = " << limit << '\n'; + const size_t envVal = TfGetEnvSetting(PXR_WORK_THREAD_LIMIT); + std::cout << "PXR_WORK_THREAD_LIMIT = " << envVal << '\n'; // Test to make sure that a call to tbb that happens before any of the // libWork API is touched is unrestricted. We need to do this for now to @@ -141,7 +152,7 @@ main(int argc, char **argv) // seem to be a way to limit it again. That's why we test this // functionality by itself. if ((argc == 2) and (strcmp(argv[1], "--rawtbb") == 0)) { - TF_AXIOM(WorkGetMaximumConcurrencyLimit() >= 4); + TF_AXIOM(WorkGetPhysicalConcurrencyLimit() >= 4); std::cout << "Testing that libWork automatically limits tbb " "threading when PXR_WORK_THREAD_LIMIT is set...\n"; @@ -151,16 +162,16 @@ main(int argc, char **argv) std::cout << " default TBB used " << _uniqueThreads->size() << " threads\n"; - if (limit == 0) { + if (envVal == 0) { if (_uniqueThreads->size() < 2) { TF_FATAL_ERROR("tbb only used %zu threads when it should be " "unlimited\n", _uniqueThreads->size()); } } - else if (_uniqueThreads->size() > limit) { + else if (_uniqueThreads->size() > envVal) { TF_FATAL_ERROR("tbb used %zu threads, which is greater than " "PXR_WORK_THREAD_LIMIT=%zu.", _uniqueThreads->size(), - limit); + envVal); } // Stop the test, now that we've initialized tbb, there's no going @@ -169,17 +180,18 @@ main(int argc, char **argv) } // 0 means all cores. + size_t limit = envVal; if (limit == 0) { WorkSetMaximumConcurrencyLimit(); limit = WorkGetConcurrencyLimit(); } - TF_AXIOM(limit > 0 and limit <= WorkGetMaximumConcurrencyLimit()); + TF_AXIOM(limit > 0 and limit <= WorkGetPhysicalConcurrencyLimit()); // Make sure that we get the default thread limit std::cout << "Testing that the thread limit defaults to " " PXR_WORK_THREAD_LIMIT by default...\n"; - _TestThreadLimit(limit); + _TestThreadLimit(envVal, limit); // Now that we've invoked libWork, make sure that raw TBB API also defaults // to PXR_WORK_THREAD_LIMIT. @@ -197,20 +209,40 @@ main(int argc, char **argv) // Test with full concurrency. std::cout << "Testing full concurrency...\n"; WorkSetMaximumConcurrencyLimit(); - _TestThreadLimit(WorkGetMaximumConcurrencyLimit()); + TF_AXIOM(WorkGetConcurrencyLimit() == + _ExpectedLimit(envVal, WorkGetPhysicalConcurrencyLimit())); + _TestThreadLimit(envVal, WorkGetPhysicalConcurrencyLimit()); // Test with no concurrency. std::cout << "Testing turning off concurrency...\n"; WorkSetConcurrencyLimit(1); - _TestThreadLimit(1); + TF_AXIOM(WorkGetConcurrencyLimit() == + _ExpectedLimit(envVal, 1)); + _TestThreadLimit(envVal, 1); + + // Test with 2 threads. + std::cout << "Testing with 2 threads...\n"; + WorkSetConcurrencyLimit(2); + TF_AXIOM(WorkGetConcurrencyLimit() == + _ExpectedLimit(envVal, 2)); + _TestThreadLimit(envVal, 2); // Test with 4 threads. std::cout << "Testing with 4 threads...\n"; WorkSetConcurrencyLimit(4); - _TestThreadLimit(4); + TF_AXIOM(WorkGetConcurrencyLimit() == + _ExpectedLimit(envVal, 4)); + _TestThreadLimit(envVal, 4); + + // Test with 1000 threads. + std::cout << "Testing with 1000 threads...\n"; + WorkSetConcurrencyLimit(1000); + TF_AXIOM(WorkGetConcurrencyLimit() == + _ExpectedLimit(envVal, 1000)); + _TestThreadLimit(envVal, WorkGetPhysicalConcurrencyLimit()); // Test argument parsing std::cout << "Testing argument parsing...\n"; - _TestArguments(); + _TestArguments(envVal); return 0; } diff --git a/pxr/base/lib/work/threadLimits.cpp b/pxr/base/lib/work/threadLimits.cpp index 26bc502b14..f6cb9cc691 100644 --- a/pxr/base/lib/work/threadLimits.cpp +++ b/pxr/base/lib/work/threadLimits.cpp @@ -36,15 +36,22 @@ // The environment variable used to limit the number of threads the application // may spawn: -// 0 - maximum concurrency +// 0 - no change, i.e. defaults to maximum physical concurrency // 1 - single-threaded mode -// positive n - limit to n threads (clamped to the number of machine cores) +// positive n - limit to n threads // negative n - limit to all but n machine cores (minimum 1). // +// Note that the environment variable value always wins over any value passed to +// the API calls below. If PXR_WORK_THREAD_LIMIT is set to a non-zero value, the +// concurrency limit cannot be changed at runtime. +// TF_DEFINE_ENV_SETTING( PXR_WORK_THREAD_LIMIT, 0, "Limits the number of threads the application may spawn. 0 (default) " - "allows for maximum concurrency."); + "allows for maximum concurrency as determined by the number of physical " + "cores, or the process's affinity mask, whichever is smaller. Note that " + "the environment variable (if set to a non-zero value) will override any " + "value passed to Work thread-limiting API calls."); // This is Work's notion of the currently requested thread limit. Due to TBB's // behavior, the first client to create a tbb::task_scheduler_init will @@ -59,7 +66,7 @@ static tbb::atomic _threadLimit; static tbb::task_scheduler_init *_tbbTaskSchedInit; unsigned -WorkGetMaximumConcurrencyLimit() +WorkGetPhysicalConcurrencyLimit() { // Use TBB here, since it pays attention to the affinity mask on Linux and // Windows. @@ -70,34 +77,53 @@ WorkGetMaximumConcurrencyLimit() static unsigned Work_NormalizeThreadCount(const int n) { - // Zero means use all physical cores available. - if (n == 0) - return WorkGetMaximumConcurrencyLimit(); - - // One means use exactly one. - if (n == 1) - return n; - - // Clamp positive integers to the total number of available cores. - if (n > 1) - return std::min(n, WorkGetMaximumConcurrencyLimit()); - + // Zero means "no change", and n >= 1 means exactly n threads, so simply + // pass those values through unchanged. // For negative integers, subtract the absolute value from the total number // of available cores (denoting all but n cores). If n == number of cores, // clamp to 1 to set single-threaded mode. - return std::max(1, n + WorkGetMaximumConcurrencyLimit()); + return n >= 0 ? n : std::max(1, n + WorkGetPhysicalConcurrencyLimit()); +} + +// Returns the normalized thread limit value from the environment setting. Note +// that 0 means "no change", i.e. the environment setting does not apply. +static unsigned +Work_GetConcurrencyLimitSetting() +{ + return Work_NormalizeThreadCount(TfGetEnvSetting(PXR_WORK_THREAD_LIMIT)); +} + +// Overrides weakValue with strongValue if strongValue is non-zero, and returns +// the resulting thread limit. +static unsigned +Work_OverrideConcurrencyLimit(unsigned weakValue, unsigned strongValue) +{ + // If the new limit is 0, i.e. "no change", simply pass the weakValue + // through unchanged. Otherwise, the new value wins. + return strongValue ? strongValue : weakValue; } static void Work_InitializeThreading() { - // Threading is initialized with the value from the environment - // setting. The setting defaults to 0, i.e. maximum concurrency. - int settingVal = TfGetEnvSetting(PXR_WORK_THREAD_LIMIT); - _threadLimit = Work_NormalizeThreadCount(settingVal); - + // Get the thread limit from the environment setting. Note that this value + // can be 0, i.e. the environment setting does not apply. + const unsigned settingVal = Work_GetConcurrencyLimitSetting(); + + // Threading is initialized with maximum physical concurrency. + const unsigned physicalLimit = WorkGetPhysicalConcurrencyLimit(); + + // To assign the thread limit, override the initial limit with the + // environment setting. The environment setting always wins over the initial + // limit, unless it has been set to 0 (default). Semantically, 0 means + // "no change". + _threadLimit = Work_OverrideConcurrencyLimit(physicalLimit, settingVal); + // Only eagerly grab TBB if the PXR_WORK_THREAD_LIMIT setting was set to - // some non-zero value. + // some non-zero value. Otherwise, the scheduler will be default initialized + // with maximum physical concurrency, or will be left untouched if + // previously initialized by the hosting environment (e.g. if we are running + // as a plugin to another application.) if (settingVal) _tbbTaskSchedInit = new tbb::task_scheduler_init(_threadLimit); } @@ -106,8 +132,22 @@ static int _forceInitialization = (Work_InitializeThreading(), 0); void WorkSetConcurrencyLimit(unsigned n) { - // sanity - _threadLimit = std::max(1, n); + // We only assign a new concurrency limit if n is non-zero, since 0 means + // "no change". Note that we need to re-initialize the TBB + // task_scheduler_init instance in either case, because if the client + // explicitly requests a concurrency limit through this library, we need to + // attempt to take control of the TBB scheduler if we can, i.e. if the host + // environment has not already done so. + if (n) { + // Get the thread limit from the environment setting. Note this value + // may be 0 (default). + const unsigned settingVal = Work_GetConcurrencyLimitSetting(); + + // Override n with the environment setting. This will make sure that the + // setting always wins over the specified value n, but only if the + // setting has been set to a non-zero value. + _threadLimit = Work_OverrideConcurrencyLimit(n, settingVal); + } // Note that we need to do some performance testing and decide if it's // better here to simply delete the task_scheduler_init object instead @@ -129,7 +169,7 @@ WorkSetConcurrencyLimit(unsigned n) void WorkSetMaximumConcurrencyLimit() { - WorkSetConcurrencyLimit(WorkGetMaximumConcurrencyLimit()); + WorkSetConcurrencyLimit(WorkGetPhysicalConcurrencyLimit()); } void diff --git a/pxr/base/lib/work/threadLimits.h b/pxr/base/lib/work/threadLimits.h index 5b69f5ee77..7c4add3907 100644 --- a/pxr/base/lib/work/threadLimits.h +++ b/pxr/base/lib/work/threadLimits.h @@ -32,11 +32,13 @@ /// Return the current concurrency limit, always >= 1. /// /// The initial value is determined by the PXR_WORK_THREAD_LIMIT env setting, -/// which defaults to WorkGetMaximumConcurrencyLimit(). +/// which defaults to WorkGetPhysicalConcurrencyLimit(). If the env setting +/// has been explicitly set to a non-zero value, it will always override any +/// concurrency limit set via the API calls below. /// /// Note that this can return a value larger than -/// WorkGetMaximumConcurrencyLimit() if WorkSetConcurrencyLimit() was called -/// with such a value. +/// WorkGetPhysicalConcurrencyLimit() if WorkSetConcurrencyLimit() was called +/// with such a value, or if PXR_WORK_THREAD_LIMIT was set with such a value. /// WORK_API unsigned WorkGetConcurrencyLimit(); @@ -44,11 +46,13 @@ WORK_API unsigned WorkGetConcurrencyLimit(); /// This is either the number of physical cores on the machine or the number of /// cores specified by the process's affinity mask, whichever is smaller. /// -WORK_API unsigned WorkGetMaximumConcurrencyLimit(); +WORK_API unsigned WorkGetPhysicalConcurrencyLimit(); -/// Set the concurrencty limit to max(1, \p n). +/// Set the concurrency limit to \p n, if \p n is a non-zero value. /// -/// Note, calling ths function with n > WorkGetMaximumConcurrencyLimit() may +/// If \p n is zero, then do not change the current concurrency limit. +/// +/// Note, calling this function with n > WorkGetPhysicalConcurrencyLimit() may /// overtax the machine. /// /// In general, very few places should call this function. Call it in places @@ -60,15 +64,17 @@ WORK_API void WorkSetConcurrencyLimit(unsigned n); /// Sanitize \p n as described below and set the concurrency limit accordingly. /// This function is useful for interpreting command line arguments. /// -/// If \p n is between 1 and WorkGetMaximumConcurrencyLimit() -/// (inclusive) then call WorkSetConcurrencyLimit(n). +/// If \p n is zero, then do not change the current concurrency limit. /// -/// If \p n is 0 or larger than the number of physical cores, call -/// WorkSetMaximumConcurrencyLimit(). +/// If \p n is a positive, non-zero value then call WorkSetConcurrencyLimit(n). +/// Note that calling this method with \p n greater than the value returned by +/// WorkGetPhysicalConcurrencyLimit() may overtax the machine. /// /// If \p n is negative, then set the concurrency limit to all but abs(\p n) -/// cores are used. For examlpe, if \p n is -2, then use all but two cores. If -/// abs(\p n) is greater than the number of physical cores, then call +/// cores. The number of cores is determined by the value returned by +/// WorkGetPhysicalConcurrencyLimit(). +/// For example, if \p n is -2, then use all but two cores. If abs(\p n) is +/// greater than the number of physical cores, then call /// WorkSetConcurrencyLimit(1), effectively disabling concurrency. /// WORK_API void WorkSetConcurrencyLimitArgument(int n); @@ -76,7 +82,7 @@ WORK_API void WorkSetConcurrencyLimitArgument(int n); /// Set the concurrency limit to be the maximum recommended for the hardware /// on which it's running. Equivalent to: /// \code -/// WorkSetConcurrencyLimit(WorkGetMaximumConcurrencyLimit()). +/// WorkSetConcurrencyLimit(WorkGetPhysicalConcurrencyLimit()). /// \endcode /// WORK_API void WorkSetMaximumConcurrencyLimit(); diff --git a/pxr/base/lib/work/wrapThreadLimits.cpp b/pxr/base/lib/work/wrapThreadLimits.cpp index 866b06f6e5..0ed66a16ce 100644 --- a/pxr/base/lib/work/wrapThreadLimits.cpp +++ b/pxr/base/lib/work/wrapThreadLimits.cpp @@ -30,7 +30,7 @@ using namespace boost::python; void wrapThreadLimits() { def("GetConcurrencyLimit", &WorkGetConcurrencyLimit); - def("GetMaximumConcurrencyLimit", &WorkGetMaximumConcurrencyLimit); + def("GetPhysicalConcurrencyLimit", &WorkGetPhysicalConcurrencyLimit); def("SetConcurrencyLimit", &WorkSetConcurrencyLimit); def("SetConcurrencyLimitArgument", &WorkSetConcurrencyLimitArgument); diff --git a/pxr/imaging/lib/garch/CMakeLists.txt b/pxr/imaging/lib/garch/CMakeLists.txt index c11822f4f8..cb4beed57d 100644 --- a/pxr/imaging/lib/garch/CMakeLists.txt +++ b/pxr/imaging/lib/garch/CMakeLists.txt @@ -16,6 +16,7 @@ endif() pxr_shared_library(garch LIBRARIES arch + tf ${Boost_SYSTEM_LIBRARY} ${OPENGL_gl_LIBRARY} ${APPKIT_LIBRARY} @@ -28,6 +29,7 @@ pxr_shared_library(garch PUBLIC_CLASSES glPlatformContext + glPlatformDebugContext PUBLIC_HEADERS api.h @@ -38,5 +40,13 @@ pxr_shared_library(garch ${GLPLATFORMCONTEXT_H} CPPFILES + moduleDeps.cpp ${GLPLATFORMCONTEXT_CPP} + + PYMODULE_CPPFILES + module.cpp + wrapPlatformDebugContext.cpp + + PYTHON_FILES + __init__.py ) diff --git a/pxr/imaging/lib/garch/__init__.py b/pxr/imaging/lib/garch/__init__.py new file mode 100644 index 0000000000..5968f1ab70 --- /dev/null +++ b/pxr/imaging/lib/garch/__init__.py @@ -0,0 +1,40 @@ +# +# 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. +# +""" +garch + +""" + +import _garch +from pxr import Tf +Tf.PrepareModule(_garch, locals()) +del _garch, Tf + +try: + from . import __DOC + __DOC.Execute(locals()) + del __DOC +except Exception: + pass + diff --git a/pxr/imaging/lib/garch/glPlatformContextDarwin.mm b/pxr/imaging/lib/garch/glPlatformContextDarwin.mm index f3789b75d8..2f4c255d41 100644 --- a/pxr/imaging/lib/garch/glPlatformContextDarwin.mm +++ b/pxr/imaging/lib/garch/glPlatformContextDarwin.mm @@ -106,3 +106,17 @@ { return GarchNSGLContextState(GarchNSGLContextState::NullState::nullstate); } + +void * +GarchSelectCoreProfileMacVisual() +{ + NSOpenGLPixelFormatAttribute attribs[10]; + int c = 0; + + attribs[c++] = NSOpenGLPFAOpenGLProfile; + attribs[c++] = NSOpenGLProfileVersion3_2Core; + attribs[c++] = NSOpenGLPFADoubleBuffer; + attribs[c++] = 0; + + return [[NSOpenGLPixelFormat alloc] initWithAttributes:attribs]; +} diff --git a/pxr/imaging/lib/glfq/glPlatformDebugContext.cpp b/pxr/imaging/lib/garch/glPlatformDebugContext.cpp similarity index 79% rename from pxr/imaging/lib/glfq/glPlatformDebugContext.cpp rename to pxr/imaging/lib/garch/glPlatformDebugContext.cpp index 470a91f9f0..c0649aae92 100644 --- a/pxr/imaging/lib/glfq/glPlatformDebugContext.cpp +++ b/pxr/imaging/lib/garch/glPlatformDebugContext.cpp @@ -21,7 +21,7 @@ // KIND, either express or implied. See the Apache License for the specific // language governing permissions and limitations under the Apache License. // -#include "pxr/imaging/glfq/glPlatformDebugContext.h" +#include "pxr/imaging/garch/glPlatformDebugContext.h" #include "pxr/imaging/garch/gl.h" #include "pxr/base/tf/diagnostic.h" @@ -30,7 +30,7 @@ /* static */ bool -GlfQGLPlatformDebugContext::IsEnabledDebugOutput() +GarchGLPlatformDebugContext::IsEnabledDebugOutput() { static bool isEnabledDebugOutput = TfGetenvBool("GLF_ENABLE_DEBUG_OUTPUT", false); @@ -39,7 +39,7 @@ GlfQGLPlatformDebugContext::IsEnabledDebugOutput() /* static */ bool -GlfQGLPlatformDebugContext::IsEnabledCoreProfile() +GarchGLPlatformDebugContext::IsEnabledCoreProfile() { static bool isEnabledCoreProfile = TfGetenvBool("GLF_ENABLE_CORE_PROFILE", false); @@ -54,12 +54,12 @@ GlfQGLPlatformDebugContext::IsEnabledCoreProfile() #include #include -class GlfQGLPlatformDebugContextPrivate { +class GarchGLPlatformDebugContextPrivate { public: - GlfQGLPlatformDebugContextPrivate( + GarchGLPlatformDebugContextPrivate( int majorVersion, int minorVersion, bool coreProfile, bool directRendering); - ~GlfQGLPlatformDebugContextPrivate(); + ~GarchGLPlatformDebugContextPrivate(); void MakeCurrent(); @@ -67,7 +67,7 @@ class GlfQGLPlatformDebugContextPrivate { GLXContext _ctx; }; -GlfQGLPlatformDebugContextPrivate::GlfQGLPlatformDebugContextPrivate( +GarchGLPlatformDebugContextPrivate::GarchGLPlatformDebugContextPrivate( int majorVersion, int minorVersion, bool coreProfile, bool directRendering) : _dpy(NULL) @@ -128,7 +128,7 @@ GlfQGLPlatformDebugContextPrivate::GlfQGLPlatformDebugContextPrivate( _dpy = shareDisplay; } -GlfQGLPlatformDebugContextPrivate::~GlfQGLPlatformDebugContextPrivate() +GarchGLPlatformDebugContextPrivate::~GarchGLPlatformDebugContextPrivate() { if (_dpy and _ctx) { glXDestroyContext(_dpy, _ctx); @@ -136,12 +136,12 @@ GlfQGLPlatformDebugContextPrivate::~GlfQGLPlatformDebugContextPrivate() } void -GlfQGLPlatformDebugContextPrivate::MakeCurrent() +GarchGLPlatformDebugContextPrivate::MakeCurrent() { glXMakeCurrent(glXGetCurrentDisplay(), glXGetCurrentDrawable(), _ctx); } -void *GlfqSelectCoreProfileMacVisual() +void *GarchSelectCoreProfileMacVisual() { return nullptr; } @@ -153,17 +153,17 @@ void *GlfqSelectCoreProfileMacVisual() #if defined(ARCH_OS_DARWIN) // XXX: implement debug context -class GlfQGLPlatformDebugContextPrivate { +class GarchGLPlatformDebugContextPrivate { public: - GlfQGLPlatformDebugContextPrivate( + GarchGLPlatformDebugContextPrivate( int majorVersion, int minorVersion, bool coreProfile, bool directRendering) {} - ~GlfQGLPlatformDebugContextPrivate() {} + ~GarchGLPlatformDebugContextPrivate() {} void MakeCurrent() {} }; -void *GlfqSelectCoreProfileMacVisual(); // extern obj-c +void *GarchSelectCoreProfileMacVisual(); // extern obj-c #endif @@ -173,17 +173,17 @@ void *GlfqSelectCoreProfileMacVisual(); // extern obj-c #if defined(ARCH_OS_WINDOWS) // XXX: implement debug context -class GlfQGLPlatformDebugContextPrivate { +class GarchGLPlatformDebugContextPrivate { public: - GlfQGLPlatformDebugContextPrivate( + GarchGLPlatformDebugContextPrivate( int majorVersion, int minorVersion, bool coreProfile, bool directRendering) {} - ~GlfQGLPlatformDebugContextPrivate() {} + ~GarchGLPlatformDebugContextPrivate() {} void MakeCurrent() {} }; -void *GlfqSelectCoreProfileMacVisual() +void *GarchSelectCoreProfileMacVisual() { return nullptr; } @@ -193,7 +193,7 @@ void *GlfqSelectCoreProfileMacVisual() //////////////////////////////////////////////////////////// -GlfQGLPlatformDebugContext::GlfQGLPlatformDebugContext(int majorVersion, +GarchGLPlatformDebugContext::GarchGLPlatformDebugContext(int majorVersion, int minorVersion, bool coreProfile, bool directRendering) @@ -203,28 +203,28 @@ GlfQGLPlatformDebugContext::GlfQGLPlatformDebugContext(int majorVersion, #endif { - if (not GlfQGLPlatformDebugContext::IsEnabledDebugOutput()) { + if (not GarchGLPlatformDebugContext::IsEnabledDebugOutput()) { return; } #if !defined(ARCH_OS_WINDOWS) - _private.reset(new GlfQGLPlatformDebugContextPrivate(majorVersion, + _private.reset(new GarchGLPlatformDebugContextPrivate(majorVersion, minorVersion, coreProfile, directRendering)); #endif } -GlfQGLPlatformDebugContext::~GlfQGLPlatformDebugContext() +GarchGLPlatformDebugContext::~GarchGLPlatformDebugContext() { // nothing } /* virtual */ void -GlfQGLPlatformDebugContext::makeCurrent() +GarchGLPlatformDebugContext::makeCurrent() { #if !defined(ARCH_OS_WINDOWS) - if (not GlfQGLPlatformDebugContext::IsEnabledDebugOutput()) { + if (not GarchGLPlatformDebugContext::IsEnabledDebugOutput()) { return; } @@ -238,14 +238,14 @@ GlfQGLPlatformDebugContext::makeCurrent() #if defined(ARCH_OS_DARWIN) void* -GlfQGLPlatformDebugContext::chooseMacVisual() +GarchGLPlatformDebugContext::chooseMacVisual() { if (_coreProfile or - GlfQGLPlatformDebugContext::IsEnabledCoreProfile()) { - return GlfqSelectCoreProfileMacVisual(); + GarchGLPlatformDebugContext::IsEnabledCoreProfile()) { + return GarchSelectCoreProfileMacVisual(); } else { return nullptr; } return nullptr; } -#endif \ No newline at end of file +#endif diff --git a/pxr/imaging/lib/glfq/glPlatformDebugContext.h b/pxr/imaging/lib/garch/glPlatformDebugContext.h similarity index 78% rename from pxr/imaging/lib/glfq/glPlatformDebugContext.h rename to pxr/imaging/lib/garch/glPlatformDebugContext.h index f58d42d2b6..301913b8e6 100644 --- a/pxr/imaging/lib/glfq/glPlatformDebugContext.h +++ b/pxr/imaging/lib/garch/glPlatformDebugContext.h @@ -21,8 +21,8 @@ // KIND, either express or implied. See the Apache License for the specific // language governing permissions and limitations under the Apache License. // -#ifndef GLFQ_GLPLATFORM_DEBUG_CONTEXT_H -#define GLFQ_GLPLATFORM_DEBUG_CONTEXT_H +#ifndef GARCH_GLPLATFORM_DEBUG_CONTEXT_H +#define GARCH_GLPLATFORM_DEBUG_CONTEXT_H #include "pxr/imaging/glfq/api.h" #include "pxr/base/tf/declarePtrs.h" @@ -31,25 +31,23 @@ #include #if !defined(ARCH_OS_WINDOWS) -class GlfQGLPlatformDebugContextPrivate; +class GarchGLPlatformDebugContextPrivate; #endif -TF_DECLARE_WEAK_PTRS(GlfQGLPlatformDebugContext); +TF_DECLARE_WEAK_PTRS(GarchGLPlatformDebugContext); -/// \class GlfQGLPlatformDebugContext +/// \class GarchGLPlatformDebugContext /// /// Platform specific context (e.g. X11/GLX) which supports debug output. /// -class GlfQGLPlatformDebugContext : public TfWeakBase { +class GarchGLPlatformDebugContext : public TfWeakBase { public: GLFQ_API - GlfQGLPlatformDebugContext(int majorVersion, + GarchGLPlatformDebugContext(int majorVersion, int minorVersion, bool coreProfile, bool directRenderering); - - GLFQ_API - virtual ~GlfQGLPlatformDebugContext(); + virtual ~GarchGLPlatformDebugContext(); GLFQ_API static bool IsEnabledDebugOutput(); @@ -65,9 +63,9 @@ class GlfQGLPlatformDebugContext : public TfWeakBase { public: #if !defined(ARCH_OS_WINDOWS) - boost::scoped_ptr _private; + boost::scoped_ptr _private; bool _coreProfile; #endif }; -#endif // GLFQ_GLPLATFORM_DEBUG_CONTEXT_H +#endif // GARCH_GLPLATFORM_DEBUG_CONTEXT_H diff --git a/pxr/imaging/lib/glfq/selectVisual.mm b/pxr/imaging/lib/garch/module.cpp similarity index 74% rename from pxr/imaging/lib/glfq/selectVisual.mm rename to pxr/imaging/lib/garch/module.cpp index 541900338d..33017b8623 100644 --- a/pxr/imaging/lib/glfq/selectVisual.mm +++ b/pxr/imaging/lib/garch/module.cpp @@ -21,18 +21,9 @@ // KIND, either express or implied. See the Apache License for the specific // language governing permissions and limitations under the Apache License. // +#include "pxr/base/tf/pyModule.h" -#include - -void *GlfqSelectCoreProfileMacVisual() +TF_WRAP_MODULE { - NSOpenGLPixelFormatAttribute attribs[10]; - int c = 0; - - attribs[c++] = NSOpenGLPFAOpenGLProfile; - attribs[c++] = NSOpenGLProfileVersion3_2Core; - attribs[c++] = NSOpenGLPFADoubleBuffer; - attribs[c++] = 0; - - return [[NSOpenGLPixelFormat alloc] initWithAttributes:attribs]; + TF_WRAP( PlatformDebugContext ); } diff --git a/pxr/imaging/lib/garch/moduleDeps.cpp b/pxr/imaging/lib/garch/moduleDeps.cpp new file mode 100644 index 0000000000..e8e58ca9d0 --- /dev/null +++ b/pxr/imaging/lib/garch/moduleDeps.cpp @@ -0,0 +1,42 @@ +// +// 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. +// +//////////////////////////////////////////////////////////////////////// +// This file is generated by the makeScriptModuleLoader script. Do not +// edit directly. + +#include "pxr/base/tf/registryManager.h" +#include "pxr/base/tf/scriptModuleLoader.h" +#include "pxr/base/tf/token.h" + +#include + +TF_REGISTRY_FUNCTION(TfScriptModuleLoader) { + std::vector reqs; + reqs.reserve(2); + reqs.push_back(TfToken("arch")); + reqs.push_back(TfToken("tf")); + TfScriptModuleLoader::GetInstance(). + RegisterLibrary(TfToken("garch"), TfToken("pxr.Garch"), reqs); +} + diff --git a/pxr/imaging/lib/glfq/wrapPlatformDebugContext.cpp b/pxr/imaging/lib/garch/wrapPlatformDebugContext.cpp similarity index 89% rename from pxr/imaging/lib/glfq/wrapPlatformDebugContext.cpp rename to pxr/imaging/lib/garch/wrapPlatformDebugContext.cpp index f7419c60ef..6f726da71c 100644 --- a/pxr/imaging/lib/glfq/wrapPlatformDebugContext.cpp +++ b/pxr/imaging/lib/garch/wrapPlatformDebugContext.cpp @@ -21,7 +21,7 @@ // KIND, either express or implied. See the Apache License for the specific // language governing permissions and limitations under the Apache License. // -#include "pxr/imaging/glfq/glPlatformDebugContext.h" +#include "pxr/imaging/garch/glPlatformDebugContext.h" #include "pxr/base/tf/makePyConstructor.h" #include "pxr/base/tf/pyPtrHelpers.h" @@ -30,18 +30,18 @@ using namespace boost::python; -static GlfQGLPlatformDebugContextPtr +static GarchGLPlatformDebugContextPtr _New(int majorVersion, int minorVersion, bool coreProfile, bool directRendering) { return TfCreateWeakPtr(new - GlfQGLPlatformDebugContext(majorVersion, minorVersion, + GarchGLPlatformDebugContext(majorVersion, minorVersion, coreProfile, directRendering)); } void wrapPlatformDebugContext() { - typedef GlfQGLPlatformDebugContext This; + typedef GarchGLPlatformDebugContext This; class_, boost::noncopyable>("GLPlatformDebugContext", no_init) diff --git a/pxr/imaging/lib/glfq/CMakeLists.txt b/pxr/imaging/lib/glfq/CMakeLists.txt index 7ea1a6851e..e5858e2097 100644 --- a/pxr/imaging/lib/glfq/CMakeLists.txt +++ b/pxr/imaging/lib/glfq/CMakeLists.txt @@ -22,28 +22,27 @@ pxr_shared_library(glfq Qt4::QtOpenGL Qt4::QtXml Qt4::QtNetwork + ${Boost_SYSTEM_LIBRARY} ${OPENGL_gl_LIBRARY} ${GLEW_LIBRARY} - ${COCOA_LIBRARY} INCLUDE_DIRS + ${Boost_INCLUDE_DIRS} ${GLEW_INCLUDE_DIR} PUBLIC_CLASSES glDebugContext - glPlatformDebugContext PUBLIC_HEADERS api.h CPPFILES moduleDeps.cpp - ${COCOA_SRC} PYMODULE_CPPFILES module.cpp - wrapPlatformDebugContext.cpp PYTHON_FILES __init__.py + ) diff --git a/pxr/imaging/lib/glfq/__init__.py b/pxr/imaging/lib/glfq/__init__.py index ce96e90eac..ca14ab81b3 100644 --- a/pxr/imaging/lib/glfq/__init__.py +++ b/pxr/imaging/lib/glfq/__init__.py @@ -43,9 +43,10 @@ def create(self, shareContext): return QtOpenGL.QGLContext.create(self, shareContext) def makeCurrent(self): + from pxr import Garch QtOpenGL.QGLContext.makeCurrent(self) if not self._platformContext: - self._platformContext = GLPlatformDebugContext( + self._platformContext = Garch.GLPlatformDebugContext( self.format().majorVersion(), self.format().minorVersion(), self.format().profile() == QtOpenGL.QGLFormat.CoreProfile, diff --git a/pxr/imaging/lib/glfq/glDebugContext.cpp b/pxr/imaging/lib/glfq/glDebugContext.cpp index 27acd991ff..90eb140702 100644 --- a/pxr/imaging/lib/glfq/glDebugContext.cpp +++ b/pxr/imaging/lib/glfq/glDebugContext.cpp @@ -22,7 +22,7 @@ // language governing permissions and limitations under the Apache License. // #include "pxr/imaging/glfq/glDebugContext.h" -#include "pxr/imaging/glfq/glPlatformDebugContext.h" +#include "pxr/imaging/garch/glPlatformDebugContext.h" #include "pxr/base/tf/diagnostic.h" @@ -52,7 +52,7 @@ GlfQGLDebugContext::makeCurrent() Parent::makeCurrent(); if (not _platformContext) { _platformContext.reset(new - GlfQGLPlatformDebugContext( + GarchGLPlatformDebugContext( format().majorVersion(), format().minorVersion(), format().profile() == QGLFormat::CoreProfile, @@ -70,7 +70,7 @@ GlfQGLDebugContext::chooseMacVisual(GDHandle handle) { if (not _platformContext) { _platformContext.reset(new - GlfQGLPlatformDebugContext( + GarchGLPlatformDebugContext( format().majorVersion(), format().minorVersion(), format().profile() == QGLFormat::CoreProfile, diff --git a/pxr/imaging/lib/glfq/glDebugContext.h b/pxr/imaging/lib/glfq/glDebugContext.h index 809ecbf8e3..5d044cb3f5 100644 --- a/pxr/imaging/lib/glfq/glDebugContext.h +++ b/pxr/imaging/lib/glfq/glDebugContext.h @@ -32,7 +32,7 @@ #include -class GlfQGLPlatformDebugContext; +class GarchGLPlatformDebugContext; TF_DECLARE_WEAK_PTRS(GlfQGLDebugContext); @@ -65,7 +65,7 @@ class GlfQGLDebugContext : public QGLContext, public TfWeakBase { #endif public: - boost::scoped_ptr _platformContext; + boost::scoped_ptr _platformContext; }; #endif // GLFQ_GL_DEBUG_CONTEXT_H diff --git a/pxr/imaging/lib/glfq/module.cpp b/pxr/imaging/lib/glfq/module.cpp index 33017b8623..70395ad5c5 100644 --- a/pxr/imaging/lib/glfq/module.cpp +++ b/pxr/imaging/lib/glfq/module.cpp @@ -25,5 +25,4 @@ TF_WRAP_MODULE { - TF_WRAP( PlatformDebugContext ); } diff --git a/pxr/imaging/lib/hd/changeTracker.cpp b/pxr/imaging/lib/hd/changeTracker.cpp index 820e91897f..484150a5a2 100644 --- a/pxr/imaging/lib/hd/changeTracker.cpp +++ b/pxr/imaging/lib/hd/changeTracker.cpp @@ -795,6 +795,8 @@ HdChangeTracker::GetRprimDirtyBits(SdfPath const& id) const void HdChangeTracker::AddCollection(TfToken const& collectionName) { + HD_TRACE_FUNCTION(); + _CollectionStateMap::iterator it = _collectionState.find(collectionName); // if it already exists, just return. if (it != _collectionState.end()) { @@ -806,6 +808,8 @@ HdChangeTracker::AddCollection(TfToken const& collectionName) void HdChangeTracker::MarkCollectionDirty(TfToken const& collectionName) { + HD_TRACE_FUNCTION(); + _CollectionStateMap::iterator it = _collectionState.find(collectionName); if (not TF_VERIFY(it != _collectionState.end(), "Collection %s not found\n", collectionName.GetText())) { @@ -824,6 +828,8 @@ HdChangeTracker::MarkCollectionDirty(TfToken const& collectionName) void HdChangeTracker::MarkAllCollectionsDirty() { + HD_TRACE_FUNCTION(); + ++_indexVersion; ++_varyingStateVersion; diff --git a/pxr/imaging/lib/hd/codeGen.cpp b/pxr/imaging/lib/hd/codeGen.cpp index 9524a655ae..100a5e240f 100644 --- a/pxr/imaging/lib/hd/codeGen.cpp +++ b/pxr/imaging/lib/hd/codeGen.cpp @@ -1818,22 +1818,25 @@ Hd_CodeGen::_GenerateShaderParameters() << " return sampler2d_" << it->second.name << ";" << "}\n"; } + // vec4 HdGet_name(vec2 coord) { return texture(sampler2d_name, coord).xyz; } accessors << it->second.dataType << " HdGet_" << it->second.name - << "(vec2 coord = "; + << "(vec2 coord) { return texture(sampler2d_" + << it->second.name << ", coord)" << swizzle << ";}\n"; + // vec4 HdGet_name() { return HdGet_name(HdGet_st().xy); } + accessors + << it->second.dataType + << " HdGet_" << it->second.name + << "() { return HdGet_" << it->second.name << "("; if (not it->second.inPrimVars.empty()) { accessors - << " HdGet_" << it->second.inPrimVars[0] << "().xy"; + << "HdGet_" << it->second.inPrimVars[0] << "().xy"; } else { accessors - << " vec2(0.0, 0.0)"; + << "vec2(0.0, 0.0)"; } - accessors - << ") {\n" - << " return texture(sampler2d_" << it->second.name - << ", coord)" << swizzle << ";\n" // XXX: should be inprimvars - << "}\n"; + accessors << "); }\n"; } else if (bindingType == HdBinding::BINDLESS_TEXTURE_PTEX_TEXEL) { accessors << it->second.dataType diff --git a/pxr/imaging/lib/hd/drawBatch.cpp b/pxr/imaging/lib/hd/drawBatch.cpp index f7148b965e..859bd4ff03 100644 --- a/pxr/imaging/lib/hd/drawBatch.cpp +++ b/pxr/imaging/lib/hd/drawBatch.cpp @@ -28,9 +28,11 @@ #include "pxr/imaging/hd/codeGen.h" #include "pxr/imaging/hd/commandBuffer.h" #include "pxr/imaging/hd/geometricShader.h" +#include "pxr/imaging/hd/glslfxShader.h" #include "pxr/imaging/hd/glslProgram.h" #include "pxr/imaging/hd/lightingShader.h" #include "pxr/imaging/hd/mesh.h" +#include "pxr/imaging/hd/package.h" #include "pxr/imaging/hd/perfLog.h" #include "pxr/imaging/hd/renderPassState.h" #include "pxr/imaging/hd/renderPassShader.h" @@ -198,9 +200,38 @@ Hd_DrawBatch::_GetDrawingProgram(HdRenderPassStateSharedPtr const &state, shaders[2] = overrideShader ? overrideShader : firstDrawItem->GetSurfaceShader(); - _program.CompileShader(firstDrawItem, + if (not _program.CompileShader(firstDrawItem, + firstDrawItem->GetGeometricShader(), + shaders, indirect)) { + + // If we failed to compile the surface shader, replace it with the + // fallback surface shader and try again. + // XXX: Note that we only say "surface shader" here because it is + // currently the only one that we allow customization for. We + // expect all the other shaders to compile or else the shipping + // code is broken and needs to be fixed. When we open up more + // shaders for customization, we will need to check them as well. + + typedef boost::shared_ptr GlfGLSLFXSharedPtr; + typedef boost::shared_ptr + HdSurfaceShaderSharedPtr; + + GlfGLSLFXSharedPtr glslSurfaceFallback = + GlfGLSLFXSharedPtr( + new GlfGLSLFX(HdPackageFallbackSurfaceShader())); + + HdSurfaceShaderSharedPtr fallbackSurface = + HdSurfaceShaderSharedPtr( + new HdGLSLFXShader(glslSurfaceFallback)); + + shaders[2] = fallbackSurface; + + bool res = _program.CompileShader(firstDrawItem, firstDrawItem->GetGeometricShader(), shaders, indirect); + // We expect the fallback shader to always compile. + TF_VERIFY(res); + } _shaderHash = shaderHash; } @@ -208,7 +239,7 @@ Hd_DrawBatch::_GetDrawingProgram(HdRenderPassStateSharedPtr const &state, return _program; } -void +bool Hd_DrawBatch::_DrawingProgram::CompileShader( HdDrawItem const *drawItem, Hd_GeometricShaderPtr const &geometricShader, @@ -220,7 +251,7 @@ Hd_DrawBatch::_DrawingProgram::CompileShader( // glew has to be intialized if (not glLinkProgram) - return; + return false; // determine binding points and populate metaData HdBindingRequestVector customBindings; @@ -266,8 +297,12 @@ Hd_DrawBatch::_DrawingProgram::CompileShader( if (_glslProgram) { _resourceBinder.IntrospectBindings(_glslProgram->GetProgram().GetId()); + } else { + // Failed to compile and link a valid glsl program. + return false; } } + return true; } /* virtual */ diff --git a/pxr/imaging/lib/hd/drawBatch.h b/pxr/imaging/lib/hd/drawBatch.h index d62c630601..5f31e39f3b 100644 --- a/pxr/imaging/lib/hd/drawBatch.h +++ b/pxr/imaging/lib/hd/drawBatch.h @@ -97,7 +97,7 @@ class Hd_DrawBatch { public: _DrawingProgram() {} - void CompileShader( + bool CompileShader( HdDrawItem const *drawItem, Hd_GeometricShaderSharedPtr const &geometricShader, HdShaderSharedPtrVector const &shaders, diff --git a/pxr/imaging/lib/hd/drawTargetRenderPass.cpp b/pxr/imaging/lib/hd/drawTargetRenderPass.cpp index b8be33729c..962696cf8a 100644 --- a/pxr/imaging/lib/hd/drawTargetRenderPass.cpp +++ b/pxr/imaging/lib/hd/drawTargetRenderPass.cpp @@ -26,7 +26,6 @@ #include "pxr/imaging/hd/drawTargetRenderPass.h" #include "pxr/imaging/hd/drawTargetRenderPassState.h" -#include "pxr/imaging/hd/camera.h" #include "pxr/imaging/hd/renderPassState.h" static @@ -58,13 +57,9 @@ _ClearBuffer(GLenum buffer, GLint drawBuffer, const VtValue &value) HdDrawTargetRenderPass::HdDrawTargetRenderPass(HdRenderIndex *index) : _renderPass(index) - , _renderPassState(new HdRenderPassState()) , _drawTargetRenderPassState(nullptr) , _drawTarget() , _drawTargetContext() - , _simpleLightingShader(new HdSimpleLightingShader()) - , _viewMatrix(1) - , _projectionMatrix(1) , _collectionObjectVersion(0) { } @@ -84,7 +79,6 @@ HdDrawTargetRenderPass::SetDrawTarget(const GlfDrawTargetRefPtr &drawTarget) } - void HdDrawTargetRenderPass::SetRenderPassState( HdDrawTargetRenderPassState *drawTargetRenderPassState) @@ -92,8 +86,6 @@ HdDrawTargetRenderPass::SetRenderPassState( _drawTargetRenderPassState = drawTargetRenderPassState; } - - void HdDrawTargetRenderPass::SetRprimCollection(HdRprimCollection const& col) { @@ -101,45 +93,12 @@ HdDrawTargetRenderPass::SetRprimCollection(HdRprimCollection const& col) } void -HdDrawTargetRenderPass::_Sync(HdTaskContext* ctx) +HdDrawTargetRenderPass::Sync() { - static const GfMatrix4d yflip = GfMatrix4d().SetScale( - GfVec3d(1.0, -1.0, 1.0)); - - const SdfPath &cameraId = _drawTargetRenderPassState->GetCamera(); - - // XXX: Need to detect when camera changes and only update if - // needed - HdCameraSharedPtr camera - = _renderPass.GetRenderIndex()->GetCamera(cameraId); - - if (!camera) { - // Render pass should not have been added to task list. - TF_CODING_ERROR("Invalid camera for render pass: %s", - cameraId.GetText()); - return; - } - - VtValue viewMatrixVt = camera->Get(HdShaderTokens->worldToViewMatrix); - VtValue projMatrixVt = camera->Get(HdShaderTokens->projectionMatrix); - _viewMatrix = viewMatrixVt.Get(); - const GfMatrix4d &projMatrix = projMatrixVt.Get(); - _projectionMatrix = projMatrix * yflip; - - GfVec2i const &resolution = _drawTarget->GetSize(); - GfVec4d viewport(0, 0, resolution[0], resolution[1]); - - _renderPassState->SetCamera(_viewMatrix, _projectionMatrix, viewport); - - // Update the internal lighting context so it knows about the new camera - // position. - GlfSimpleLightingContextRefPtr lightingContext; - _GetTaskContextData(ctx, HdTokens->lightingContext, &lightingContext); - _UpdateLightingContext(lightingContext); - // Update the collection object if necessary. unsigned int newCollectionVersion = - _drawTargetRenderPassState->GetRprimCollectionVersion(); + _drawTargetRenderPassState->GetRprimCollectionVersion(); + if (_collectionObjectVersion != newCollectionVersion) { SetRprimCollection(_drawTargetRenderPassState->GetRprimCollection()); @@ -152,11 +111,11 @@ HdDrawTargetRenderPass::_Sync(HdTaskContext* ctx) } _renderPass.Sync(); - _renderPassState->Sync(); } void -HdDrawTargetRenderPass::_Execute(HdTaskContext* ctx) +HdDrawTargetRenderPass::Execute( + HdRenderPassStateSharedPtr const &renderPassState) { if (!_drawTarget) { return; @@ -173,7 +132,7 @@ HdDrawTargetRenderPass::_Execute(HdTaskContext* ctx) glViewport(0, 0, resolution[0], resolution[1]); // Perform actual draw - _renderPass.Execute(_renderPassState); + _renderPass.Execute(renderPassState); glPopAttrib(); @@ -197,25 +156,3 @@ HdDrawTargetRenderPass::_ClearBuffers() _ClearBuffer(GL_COLOR, (GLint)attachmentNum, clearColor); } } - -void -HdDrawTargetRenderPass::_UpdateLightingContext(GlfSimpleLightingContextRefPtr &lightingContext) -{ - GlfSimpleLightingContextRefPtr const& simpleLightingContext = - _simpleLightingShader->GetLightingContext(); - - if (lightingContext) { - simpleLightingContext->SetUseLighting( - lightingContext->GetUseLighting()); - simpleLightingContext->SetLights(lightingContext->GetLights()); - simpleLightingContext->SetMaterial(lightingContext->GetMaterial()); - simpleLightingContext->SetSceneAmbient( - lightingContext->GetSceneAmbient()); - simpleLightingContext->SetShadows(lightingContext->GetShadows()); - simpleLightingContext->SetUseColorMaterialDiffuse( - lightingContext->GetUseColorMaterialDiffuse()); - } - - simpleLightingContext->SetCamera(_viewMatrix, _projectionMatrix); - _renderPassState->SetLightingShader(_simpleLightingShader); -} diff --git a/pxr/imaging/lib/hd/drawTargetRenderPass.h b/pxr/imaging/lib/hd/drawTargetRenderPass.h index 0b6839d9ce..b9d0d9619f 100644 --- a/pxr/imaging/lib/hd/drawTargetRenderPass.h +++ b/pxr/imaging/lib/hd/drawTargetRenderPass.h @@ -27,7 +27,6 @@ #include "pxr/imaging/hd/api.h" #include "pxr/imaging/hd/renderPass.h" #include "pxr/imaging/hd/rprimCollection.h" -#include "pxr/imaging/hd/simpleLightingShader.h" #include "pxr/imaging/glf/drawTarget.h" @@ -45,7 +44,7 @@ class HdDrawTargetRenderPassState; /// to major changes. It is likely this functionality will be absorbed into /// the base class. /// -class HdDrawTargetRenderPass : public HdTask { +class HdDrawTargetRenderPass : boost::noncopyable { public: HDLIB_API HdDrawTargetRenderPass(HdRenderIndex *index); @@ -65,21 +64,15 @@ class HdDrawTargetRenderPass : public HdTask { HDLIB_API void SetRprimCollection(HdRprimCollection const& col); - HdRenderPassStateSharedPtr const &GetRenderPassState() const { - return _renderPassState; - } - -protected: /// Execute render pass task - virtual void _Sync(HdTaskContext* ctx) override; + void Sync(); /// Sync the render pass resources - virtual void _Execute(HdTaskContext* ctx) override; + void Execute(HdRenderPassStateSharedPtr const &renderPassState); private: - /// RenderPass and state + /// RenderPass HdRenderPass _renderPass; - HdRenderPassStateSharedPtr _renderPassState; /// drawtarget renderPass state HdDrawTargetRenderPassState *_drawTargetRenderPassState; @@ -90,15 +83,8 @@ class HdDrawTargetRenderPass : public HdTask { /// The context which owns the draw target object. GlfGLContextSharedPtr _drawTargetContext; - HdSimpleLightingShaderSharedPtr _simpleLightingShader; - GfMatrix4d _viewMatrix; - GfMatrix4d _projectionMatrix; - unsigned int _collectionObjectVersion; - /// Prepares the lighting context for this specific draw target pass - void _UpdateLightingContext(GlfSimpleLightingContextRefPtr &lightingContext); - /// Clear all color and depth buffers. void _ClearBuffers(); diff --git a/pxr/imaging/lib/hd/glslProgram.cpp b/pxr/imaging/lib/hd/glslProgram.cpp index cb9b61d68a..91d32390ae 100644 --- a/pxr/imaging/lib/hd/glslProgram.cpp +++ b/pxr/imaging/lib/hd/glslProgram.cpp @@ -129,8 +129,9 @@ HdGLSLProgram::CompileShader(GLenum type, std::string logString; if (not HdGLUtils::GetShaderCompileStatus(shader, &logString)) { - TF_CODING_ERROR("Failed to compile shader (%s): \n%s", - shaderType, logString.c_str()); + // XXX:validation + TF_WARN("Failed to compile shader (%s): \n%s", + shaderType, logString.c_str()); } // attach the shader to the program @@ -167,7 +168,8 @@ HdGLSLProgram::Link() std::string logString; bool success = true; if (not HdGLUtils::GetProgramLinkStatus(program, &logString)) { - TF_CODING_ERROR("Failed to link shader: \n%s", logString.c_str()); + // XXX:validation + TF_WARN("Failed to link shader: \n%s", logString.c_str()); success = false; } diff --git a/pxr/imaging/lib/hd/light.cpp b/pxr/imaging/lib/hd/light.cpp index 9da4bad574..0bb5901047 100644 --- a/pxr/imaging/lib/hd/light.cpp +++ b/pxr/imaging/lib/hd/light.cpp @@ -94,10 +94,14 @@ HdLight::Sync() // Optional if (vtShadowCollection.IsHolding()) { - _shadowCollection = - vtShadowCollection.UncheckedGet(); + HdRprimCollection newCollection = + vtShadowCollection.UncheckedGet(); + + if (_shadowCollection != newCollection) { + _shadowCollection = newCollection; + changeTracker.MarkCollectionDirty(_shadowCollection.GetName()); + } - changeTracker.MarkCollectionDirty(_shadowCollection.GetName()); } else { _shadowCollection = HdRprimCollection(); } diff --git a/pxr/imaging/lib/hd/texture.cpp b/pxr/imaging/lib/hd/texture.cpp index fbb878a863..336d798889 100644 --- a/pxr/imaging/lib/hd/texture.cpp +++ b/pxr/imaging/lib/hd/texture.cpp @@ -23,6 +23,8 @@ // #include "pxr/imaging/hd/texture.h" +#include "pxr/imaging/glf/textureRegistry.h" +#include "pxr/imaging/glf/uvTextureStorage.h" #include "pxr/imaging/hd/bufferArrayRange.h" #include "pxr/imaging/hd/resource.h" #include "pxr/imaging/hd/resourceRegistry.h" @@ -67,33 +69,38 @@ HdTexture::Sync() bits & HdChangeTracker::DirtyParams or bits & HdChangeTracker::DirtyTexture) { - HdTextureResourceSharedPtr texResource = - delegate->GetTextureResource(id); -#if 0 - if (texResource->GetTexelsTextureId() == 0) { - // fail to load a texture. use fallback default - - if (texResource->IsPtex()) { - const size_t defaultPtexId = 0x48510398a84ebf94; - HdInstance - defaultTexInstance = resourceRegistry->RegisterTextureResource(defaultPtexId); - if (defaultTexInstance.IsFirstInstance()) { - HdTextureResourceSharedPtr defaultTexResource(new Hd_DefaultPtexTextureResource()); - defaultTexInstance.SetValue(defaultTexResource); - } - texResource = defaultTexInstance.GetValue(); - } else { - const size_t defaultUVId = 0x48510398a84ebf95; - HdInstance - defaultTexInstance = resourceRegistry->RegisterTextureResource(defaultUVId); - if (defaultTexInstance.IsFirstInstance()) { - HdTextureResourceSharedPtr defaultTexResource(new Hd_DefaultUVTextureResource()); - defaultTexInstance.SetValue(defaultTexResource); + HdTextureResourceSharedPtr texResource; + if (texID == HdTextureResource::ComputeFallbackUVHash()) { + GlfUVTextureStorageRefPtr texPtr = + GlfUVTextureStorage::New(1,1,VtValue(GfVec3d(0.0, 0.0, 0.0))); + GlfTextureHandleRefPtr texture = + GlfTextureRegistry::GetInstance().GetTextureHandle(texPtr); + texture->AddMemoryRequest(0); + texResource = HdTextureResourceSharedPtr( + new HdSimpleTextureResource(texture, false)); + } else if (texID == HdTextureResource::ComputeFallbackPtexHash()) { + texResource = + delegate->GetTextureResource(id); + // Hacky Ptex Fallback Implementation (nonfunctional) + // For future reference + /*if (texResource->GetTexelsTextureId() == 0) { + // fail to load a texture. use fallback default + if (texResource->IsPtex()) { + const size_t defaultPtexId = 0x48510398a84ebf94; + HdInstance + defaultTexInstance = resourceRegistry->RegisterTextureResource(defaultPtexId); + if (defaultTexInstance.IsFirstInstance()) { + HdTextureResourceSharedPtr defaultTexResource(new Hd_DefaultPtexTextureResource()); + defaultTexInstance.SetValue(defaultTexResource); + } + texResource = defaultTexInstance.GetValue(); } - texResource = defaultTexInstance.GetValue(); - } + }*/ + } else { + texResource = + delegate->GetTextureResource(id); } -#endif + texInstance.SetValue(texResource); } } diff --git a/pxr/imaging/lib/hd/textureResource.cpp b/pxr/imaging/lib/hd/textureResource.cpp index bd2ba3d433..ccabb38eee 100644 --- a/pxr/imaging/lib/hd/textureResource.cpp +++ b/pxr/imaging/lib/hd/textureResource.cpp @@ -30,7 +30,13 @@ #include "pxr/imaging/hd/renderContextCaps.h" #include "pxr/imaging/glf/baseTexture.h" #include "pxr/imaging/glf/ptexTexture.h" -#include "pxr/imaging/glf/uvTexture.h" + +TF_DEFINE_PRIVATE_TOKENS( + _tokens, + + ((fallbackPtexPath, "PtExNoNsEnSe")) + ((fallbackUVPath, "UvNoNsEnSe")) +); HdTextureResource::~HdTextureResource() { @@ -49,6 +55,32 @@ HdTextureResource::ComputeHash(TfToken const &sourceFile) return hash; } +/* static */ +HdTextureResource::ID +HdTextureResource::ComputeFallbackPtexHash() +{ + HD_TRACE_FUNCTION(); + + uint32_t hash = 0; + std::string const &filename = _tokens->fallbackPtexPath.GetString(); + hash = ArchHash(filename.c_str(), filename.size(), hash); + + return hash; +} + +/* static */ +HdTextureResource::ID +HdTextureResource::ComputeFallbackUVHash() +{ + HD_TRACE_FUNCTION(); + + uint32_t hash = 0; + std::string const &filename = _tokens->fallbackUVPath.GetString(); + hash = ArchHash(filename.c_str(), filename.size(), hash); + + return hash; +} + // HdSimpleTextureResource implementation HdSimpleTextureResource::HdSimpleTextureResource( @@ -125,7 +157,7 @@ GLuint HdSimpleTextureResource::GetTexelsTextureId() return TfDynamic_cast(_texture)->GetTexelsTextureName(); } - return TfDynamic_cast(_texture)->GetGlTextureName(); + return TfDynamic_cast(_texture)->GetGlTextureName(); } GLuint HdSimpleTextureResource::GetTexelsSamplerId() diff --git a/pxr/imaging/lib/hd/textureResource.h b/pxr/imaging/lib/hd/textureResource.h index 37080b118a..c87ce6a9ad 100644 --- a/pxr/imaging/lib/hd/textureResource.h +++ b/pxr/imaging/lib/hd/textureResource.h @@ -46,6 +46,8 @@ class HdTextureResource { /// Returns the hash value of the texture for \a sourceFile HDLIB_API static ID ComputeHash(TfToken const & sourceFile); + static ID ComputeFallbackPtexHash(); + static ID ComputeFallbackUVHash(); HDLIB_API virtual ~HdTextureResource(); diff --git a/pxr/imaging/lib/hd/unitTestDelegate.cpp b/pxr/imaging/lib/hd/unitTestDelegate.cpp index dbb67034de..f7bcd6162a 100644 --- a/pxr/imaging/lib/hd/unitTestDelegate.cpp +++ b/pxr/imaging/lib/hd/unitTestDelegate.cpp @@ -24,6 +24,8 @@ #include "pxr/imaging/hd/unitTestDelegate.h" #include "pxr/imaging/hd/basisCurves.h" +#include "pxr/imaging/hd/camera.h" +#include "pxr/imaging/hd/light.h" #include "pxr/imaging/hd/mesh.h" #include "pxr/imaging/hd/meshTopology.h" #include "pxr/imaging/hd/points.h" @@ -35,6 +37,7 @@ #include "pxr/base/gf/matrix4f.h" #include "pxr/base/gf/rotation.h" +#include "pxr/imaging/glf/simpleLight.h" #include "pxr/imaging/glf/textureRegistry.h" #include "pxr/imaging/glf/ptexTexture.h" @@ -256,6 +259,28 @@ Hd_UnitTestDelegate::AddTexture(SdfPath const& id, _textures[id] = _Texture(texture); } +void +Hd_UnitTestDelegate::AddCamera(SdfPath const &id) +{ + HdRenderIndex& index = GetRenderIndex(); + index.InsertCamera(this, id); + _cameras[id].params[HdShaderTokens->worldToViewMatrix] + = VtValue(GfMatrix4d(1)); + _cameras[id].params[HdShaderTokens->projectionMatrix] + = VtValue(GfMatrix4d(1)); +} + +void +Hd_UnitTestDelegate::AddLight(SdfPath const &id) +{ + HdRenderIndex& index = GetRenderIndex(); + index.InsertLight(this, id); + _lights[id].params[HdTokens->lightParams] + = VtValue(GlfSimpleLight()); + _lights[id].params[HdTokens->lightShadowCollection] + = VtValue(HdRprimCollection(HdTokens->geometry, HdTokens->hull)); +} + void Hd_UnitTestDelegate::HideRprim(SdfPath const& id) { @@ -383,6 +408,22 @@ Hd_UnitTestDelegate::UpdateInstancerPrototypes(float time) } } +void +Hd_UnitTestDelegate::UpdateCamera(SdfPath const &id, + TfToken const &key, + VtValue value) +{ + _cameras[id].params[key] = value; +} + +void +Hd_UnitTestDelegate::UpdateLight(SdfPath const &id, + TfToken const &key, + VtValue value) +{ + _lights[id].params[key] = value; +} + /*virtual*/ bool Hd_UnitTestDelegate::IsInCollection(SdfPath const& id, @@ -642,6 +683,13 @@ Hd_UnitTestDelegate::Get(SdfPath const& id, TfToken const& key) { HD_TRACE_FUNCTION(); + // camera and light + if (_cameras.find(id) != _cameras.end()) { + return _cameras[id].params[key]; + } else if (_lights.find(id) != _lights.end()) { + return _lights[id].params[key]; + } + VtValue value; if (key == HdTokens->points) { // We could be a mesh or a cuve diff --git a/pxr/imaging/lib/hd/unitTestDelegate.h b/pxr/imaging/lib/hd/unitTestDelegate.h index 0b2bed3852..cd684e3266 100644 --- a/pxr/imaging/lib/hd/unitTestDelegate.h +++ b/pxr/imaging/lib/hd/unitTestDelegate.h @@ -196,6 +196,12 @@ class Hd_UnitTestDelegate : public HdSceneDelegate { HDLIB_API void AddTexture(SdfPath const& id, GlfTextureRefPtr const& texture); + /// Camera + void AddCamera(SdfPath const &id); + + /// Light + void AddLight(SdfPath const &id); + /// Remove a prim HDLIB_API void Remove(SdfPath const &id); @@ -234,6 +240,9 @@ class Hd_UnitTestDelegate : public HdSceneDelegate { HDLIB_API void UpdateInstancerPrototypes(float time); + void UpdateCamera(SdfPath const &id, TfToken const &key, VtValue value); + void UpdateLight(SdfPath const &id, TfToken const &key, VtValue value); + void BindSurfaceShader(SdfPath const &rprimId, SdfPath const &shaderId) { _surfaceShaderBindings[rprimId] = shaderId; @@ -422,12 +431,21 @@ class Hd_UnitTestDelegate : public HdSceneDelegate { } GlfTextureRefPtr texture; }; + struct _Camera { + VtDictionary params; + }; + struct _Light { + VtDictionary params; + }; + std::map _meshes; std::map _curves; std::map _points; std::map _instancers; std::map _surfaceShaders; std::map _textures; + std::map _cameras; + std::map _lights; TfHashSet _hiddenRprims; typedef std::map SdfPathMap; diff --git a/pxr/imaging/lib/hdx/drawTargetTask.cpp b/pxr/imaging/lib/hdx/drawTargetTask.cpp index 629c80a539..7715905ba9 100644 --- a/pxr/imaging/lib/hdx/drawTargetTask.cpp +++ b/pxr/imaging/lib/hdx/drawTargetTask.cpp @@ -30,9 +30,11 @@ #include "pxr/imaging/hdx/tokens.h" #include "pxr/imaging/hdx/debugCodes.h" +#include "pxr/imaging/hd/camera.h" #include "pxr/imaging/hd/drawTarget.h" #include "pxr/imaging/hd/drawTargetRenderPass.h" #include "pxr/imaging/hd/renderPassState.h" +#include "pxr/imaging/hd/simpleLightingShader.h" #include "pxr/imaging/glf/drawTarget.h" @@ -127,9 +129,14 @@ HdxDrawTargetTask::_Sync(HdTaskContext* ctx) pass->SetDrawTarget(drawTarget->GetGlfDrawTarget()); pass->SetRenderPassState(drawTarget->GetRenderPassState()); + HdRenderPassStateSharedPtr renderPassState(new HdRenderPassState()); + HdSimpleLightingShaderSharedPtr simpleLightingShader(new HdSimpleLightingShader()); + _renderPasses.emplace_back( RenderPassInfo { std::move(pass), + renderPassState, + simpleLightingShader, drawTarget, drawTarget->GetVersion() }); @@ -157,16 +164,48 @@ HdxDrawTargetTask::_Sync(HdTaskContext* ctx) } } + ///---------------------- + static const GfMatrix4d yflip = GfMatrix4d().SetScale( + GfVec3d(1.0, -1.0, 1.0)); + + // lighting context + GlfSimpleLightingContextRefPtr lightingContext; + _GetTaskContextData(ctx, HdTokens->lightingContext, &lightingContext); + size_t numRenderPasses = _renderPasses.size(); for (size_t renderPassIdx = 0; renderPassIdx < numRenderPasses; ++renderPassIdx) { - HdDrawTargetRenderPass *renderPass = _renderPasses[renderPassIdx].pass.get(); - HdRenderPassStateSharedPtr renderPassState = renderPass->GetRenderPassState(); + RenderPassInfo &renderPassInfo = _renderPasses[renderPassIdx]; + HdDrawTargetRenderPass *renderPass = renderPassInfo.pass.get(); + HdRenderPassStateSharedPtr &renderPassState = renderPassInfo.renderPassState; + HdDrawTargetSharedPtr drawTarget = renderPassInfo.target.lock(); + + const SdfPath &cameraId = drawTarget->GetRenderPassState()->GetCamera(); + + // XXX: Need to detect when camera changes and only update if + // needed + HdCameraSharedPtr camera + = GetDelegate()->GetRenderIndex().GetCamera(cameraId); + + if (!camera) { + // Render pass should not have been added to task list. + TF_CODING_ERROR("Invalid camera for render pass: %s", + cameraId.GetText()); + return; + } + + VtValue viewMatrixVt = camera->Get(HdShaderTokens->worldToViewMatrix); + VtValue projMatrixVt = camera->Get(HdShaderTokens->projectionMatrix); + GfMatrix4d viewMatrix = viewMatrixVt.Get(); + const GfMatrix4d &projMatrix = projMatrixVt.Get(); + GfMatrix4d projectionMatrix = projMatrix * yflip; + + GfVec2i const &resolution = drawTarget->GetGlfDrawTarget()->GetSize(); + GfVec4d viewport(0, 0, resolution[0], resolution[1]); // Update Raster States - // XXX: Share raster state between render passes? renderPassState->SetOverrideColor(_overrideColor); renderPassState->SetWireframeColor(_wireframeColor); renderPassState->SetLightingEnabled(_enableLighting); @@ -175,7 +214,30 @@ HdxDrawTargetTask::_Sync(HdTaskContext* ctx) renderPassState->SetDrawingRange(_drawingRange); renderPassState->SetCullStyle(_cullStyle); - renderPass->Sync(ctx); + HdSimpleLightingShaderSharedPtr &simpleLightingShader + = _renderPasses[renderPassIdx].simpleLightingShader; + GlfSimpleLightingContextRefPtr const& simpleLightingContext = + simpleLightingShader->GetLightingContext(); + + renderPassState->SetLightingShader(simpleLightingShader); + + renderPassState->SetCamera(viewMatrix, projectionMatrix, viewport); + simpleLightingContext->SetCamera(viewMatrix, projectionMatrix); + + if (lightingContext) { + simpleLightingContext->SetUseLighting( + lightingContext->GetUseLighting()); + simpleLightingContext->SetLights(lightingContext->GetLights()); + simpleLightingContext->SetMaterial(lightingContext->GetMaterial()); + simpleLightingContext->SetSceneAmbient( + lightingContext->GetSceneAmbient()); + simpleLightingContext->SetShadows(lightingContext->GetShadows()); + simpleLightingContext->SetUseColorMaterialDiffuse( + lightingContext->GetUseColorMaterialDiffuse()); + } + + renderPassState->Sync(); + renderPass->Sync(); } } @@ -233,8 +295,11 @@ HdxDrawTargetTask::_Execute(HdTaskContext* ctx) renderPassIdx < numRenderPasses; ++renderPassIdx) { - HdDrawTargetRenderPass *renderPass = _renderPasses[renderPassIdx].pass.get(); - renderPass->Execute(ctx); + HdDrawTargetRenderPass *renderPass = + _renderPasses[renderPassIdx].pass.get(); + HdRenderPassStateSharedPtr renderPassState = + _renderPasses[renderPassIdx].renderPassState; + renderPass->Execute(renderPassState); } if (oldAlphaToCoverage) { diff --git a/pxr/imaging/lib/hdx/drawTargetTask.h b/pxr/imaging/lib/hdx/drawTargetTask.h index 78bc001c7b..084050f59e 100644 --- a/pxr/imaging/lib/hdx/drawTargetTask.h +++ b/pxr/imaging/lib/hdx/drawTargetTask.h @@ -27,6 +27,7 @@ #include "pxr/imaging/hdx/version.h" #include "pxr/imaging/hd/task.h" #include "pxr/imaging/hd/drawTargetRenderPass.h" +#include "pxr/imaging/hd/simpleLightingShader.h" #include "pxr/base/gf/vec2f.h" #include "pxr/base/gf/vec4f.h" @@ -55,6 +56,8 @@ class HdxDrawTargetTask : public HdSceneTask { struct RenderPassInfo { HdDrawTargetRenderPassUniquePtr pass; + HdRenderPassStateSharedPtr renderPassState; + HdSimpleLightingShaderSharedPtr simpleLightingShader; HdDrawTargetWeakPtr target; unsigned int version; }; diff --git a/pxr/usd/bin/usdcat/usdcat.py b/pxr/usd/bin/usdcat/usdcat.py index 5ff83293b4..aaa9f464ff 100644 --- a/pxr/usd/bin/usdcat/usdcat.py +++ b/pxr/usd/bin/usdcat/usdcat.py @@ -25,7 +25,7 @@ import argparse, sys, signal, os, platform def _Err(msg): - sys.stderr.write(msg + '\n'); + sys.stderr.write(msg + '\n') def GetUsdData(filePath): from pxr import Sdf diff --git a/pxr/usd/lib/ar/defaultResolver.cpp b/pxr/usd/lib/ar/defaultResolver.cpp index fce0fbbbdc..db28be1bc9 100644 --- a/pxr/usd/lib/ar/defaultResolver.cpp +++ b/pxr/usd/lib/ar/defaultResolver.cpp @@ -34,33 +34,18 @@ #include "pxr/base/tf/stringUtils.h" #include "pxr/base/vt/value.h" -#if MAYA_TBB_HANG_WORKAROUND_HACK -#include -#include -#else #include -#endif // MAYA_TBB_HANG_WORKAROUND_HACK #include static const char* _FileRelativePathPrefix = ARCH_REL_PATH_IDENT; -#if MAYA_TBB_HANG_WORKAROUND_HACK -struct Ar_DefaultResolver::_Cache -{ - using _PathToResolvedPathMap = - std::unordered_map; - _PathToResolvedPathMap _pathToResolvedPathMap; - tbb::spin_mutex _mutex; -}; -#else struct Ar_DefaultResolver::_Cache { using _PathToResolvedPathMap = tbb::concurrent_hash_map; _PathToResolvedPathMap _pathToResolvedPathMap; }; -#endif // MAYA_TBB_HANG_WORKAROUND_HACK Ar_DefaultResolver::Ar_DefaultResolver() { @@ -209,18 +194,6 @@ Ar_DefaultResolver::ResolveWithAssetInfo( return path; } -#if MAYA_TBB_HANG_WORKAROUND_HACK - if (_CachePtr currentCache = _GetCurrentCache()) { - tbb::spin_mutex::scoped_lock lock(currentCache->_mutex); - std::pair<_Cache::_PathToResolvedPathMap::iterator, bool> accessor = - currentCache->_pathToResolvedPathMap.insert( - std::make_pair(path, std::string())); - if (accessor.second) { - accessor.first->second = _ResolveNoCache(path); - } - return accessor.first->second; - } -#else if (_CachePtr currentCache = _GetCurrentCache()) { _Cache::_PathToResolvedPathMap::accessor accessor; if (currentCache->_pathToResolvedPathMap.insert( @@ -229,7 +202,6 @@ Ar_DefaultResolver::ResolveWithAssetInfo( } return accessor->second; } -#endif // MAYA_TBB_HANG_WORKAROUND_HACK return _ResolveNoCache(path); } diff --git a/pxr/usd/lib/pcp/cache.cpp b/pxr/usd/lib/pcp/cache.cpp index 30df90aa5a..fc98b98436 100644 --- a/pxr/usd/lib/pcp/cache.cpp +++ b/pxr/usd/lib/pcp/cache.cpp @@ -1319,9 +1319,11 @@ _AddRelocateEditsForLayerStack( layerStack->GetPathsToPrimsWithRelocates(); TF_FOR_ALL(pathIt, relocatePrimPaths) { TF_FOR_ALL(layerIt, layerStack->GetLayers()) { - // XXX: The prim should always be valid, but might not be due to - // bug 101300 const SdfPrimSpecHandle prim = (*layerIt)->GetPrimAtPath(*pathIt); + // The relocate we discovered in the layerStack at this path + // doesn't necessarily mean there is a spec with a relocate + // in every layer. Skip layers that don't have a spec with + // a relocate. if (not prim or not prim->HasRelocates()) { continue; } @@ -2468,13 +2470,15 @@ PcpCache::_GetPrimIndex(const SdfPath& path) const return NULL; } -template +template struct Pcp_ParallelIndexer { typedef Pcp_ParallelIndexer This; + template Pcp_ParallelIndexer(PcpCache *cache, - Predicate pred, + ChildrenPredicate childrenPred, + PayloadPredicate payloadPred, const PcpLayerStackPtr &layerStack, PcpPrimIndexInputs baseInputs, PcpErrorVector *allErrors, @@ -2483,7 +2487,7 @@ struct Pcp_ParallelIndexer const char *mallocTag2) : _cache(cache) , _allErrors(allErrors) - , _predicate(pred) + , _childrenPredicate(childrenPred) , _layerStack(layerStack) , _baseInputs(baseInputs) , _resolver(ArGetResolver()) @@ -2491,13 +2495,21 @@ struct Pcp_ParallelIndexer , _parentCache(parentCache) , _mallocTag1(mallocTag1) , _mallocTag2(mallocTag2) - {} + { + // Set the payload predicate in the base inputs, as well as the + // includedPayloadsMutex. + _baseInputs + .IncludedPayloadsMutex(&_includedPayloadsMutex) + .IncludePayloadPredicate(payloadPred) + ; + } ~Pcp_ParallelIndexer() { // Tear down async. WorkSwapDestroyAsync(_toCompute); WorkMoveDestroyAsync(_finishedOutputs); WorkSwapDestroyAsync(_consumerScratch); + WorkSwapDestroyAsync(_consumerScratchPayloads); // We need to tear down the _results synchronously because doing so may // drop layers, and that's something that clients rely on, but we can @@ -2506,7 +2518,7 @@ struct Pcp_ParallelIndexer [](PcpPrimIndexOutputs &out) { PcpPrimIndexOutputs().swap(out); }); - } + } // Run the added work and wait for it to complete. void RunAndWait() { @@ -2568,7 +2580,7 @@ struct Pcp_ParallelIndexer // Invoke the client's predicate to see if we should do children. bool didChildren = false; - if (_predicate(*index)) { + if (_childrenPredicate(*index)) { // Compute the children paths and add new tasks for them. TfTokenVector names; PcpTokenSet prohibitedNames; @@ -2609,18 +2621,54 @@ struct Pcp_ParallelIndexer _allErrors->insert(_allErrors->end(), outputs->allErrors.begin(), outputs->allErrors.end()); - + + SdfPath const &primIndexPath = outputs->primIndex.GetPath(); + // Add dependencies. - _cache->_AddIndexDependencies( - outputs->primIndex.GetPath(), outputs); + _cache->_AddIndexDependencies(primIndexPath, outputs); // Store index off to the side so we can publish several at once, // ideally. We have to make a copy to move into the _cache itself, // since sibling caches in other tasks will still require that their // parent be valid. _consumerScratch.push_back(outputs->primIndex); + + // Store included payload path to the side to publish several at + // once, as well. + if (outputs->includedDiscoveredPayload) + _consumerScratchPayloads.push_back(primIndexPath); } - + + // This size threshold is arbitrary but helps ensure that even with + // writer starvation we'll avoid growing our working spaces too large. + static const size_t PendingSizeThreshold = 20000; + + if (not _consumerScratchPayloads.empty()) { + // Publish to _includedPayloads if possible. If we're told to + // flush, or if we're over a threshold number of pending results, + // then take the write lock and publish. Otherwise only attempt to + // take the write lock, and if we fail to do so then we do nothing, + // since we're guaranteed to run again. This helps minimize + // contention and maximize throughput. + tbb::spin_rw_mutex::scoped_lock lock; + + bool locked = flush || + _consumerScratch.size() >= PendingSizeThreshold; + if (locked) { + lock.acquire(_includedPayloadsMutex, /*write=*/true); + } else { + locked = lock.try_acquire( + _includedPayloadsMutex, /*write=*/true); + } + if (locked) { + for (auto const &path: _consumerScratchPayloads) { + _cache->_includedPayloads.insert(path); + } + lock.release(); + _consumerScratchPayloads.clear(); + } + } + // Ok, publish the set of indexes. if (not _consumerScratch.empty()) { // If we're told to flush, or if we're over a threshold number of @@ -2628,38 +2676,39 @@ struct Pcp_ParallelIndexer // only attempt to take the write lock, and if we fail to do so then // we do nothing, since we're guaranteed to run again. This helps // minimize contention and maximize throughput. - - // This size threshold is arbitrary but helps ensure that even with - // writer starvation we'll never grow our working space too huge. - static const size_t PendingSizeThreshold = 20000; - tbb::spin_rw_mutex::scoped_lock lock; - if (flush or _consumerScratch.size() >= PendingSizeThreshold) { + + bool locked = flush || + _consumerScratch.size() >= PendingSizeThreshold; + if (locked) { lock.acquire(_primIndexCacheMutex, /*write=*/true); } else { - if (not lock.try_acquire(_primIndexCacheMutex, /*write=*/true)) - return; + locked = lock.try_acquire(_primIndexCacheMutex, /*write=*/true); } - for (auto &index: _consumerScratch) { - // Save the prim index in the cache. - const SdfPath &path = index.GetPath(); - _cache->_primIndexCache[path].Swap(index); + if (locked) { + for (auto &index: _consumerScratch) { + // Save the prim index in the cache. + const SdfPath &path = index.GetPath(); + _cache->_primIndexCache[path].Swap(index); + } + lock.release(); + _consumerScratch.clear(); } - lock.release(); - _consumerScratch.clear(); } } PcpCache *_cache; PcpErrorVector *_allErrors; - Predicate _predicate; + ChildrenPredicate _childrenPredicate; vector > _toCompute; const PcpLayerStackPtr &_layerStack; PcpPrimIndexInputs _baseInputs; tbb::concurrent_vector _results; tbb::spin_rw_mutex _primIndexCacheMutex; + tbb::spin_rw_mutex _includedPayloadsMutex; tbb::concurrent_queue _finishedOutputs; vector _consumerScratch; + vector _consumerScratchPayloads; ArResolver& _resolver; WorkDispatcher _dispatcher; WorkSingularTask _consumer; @@ -2672,7 +2721,8 @@ void PcpCache::_ComputePrimIndexesInParallel( const SdfPathVector &roots, PcpErrorVector *allErrors, - _UntypedPredicate pred, + _UntypedIndexingChildrenPredicate childrenPred, + _UntypedIndexingPayloadPredicate payloadPred, const char *mallocTag1, const char *mallocTag2) { @@ -2685,22 +2735,22 @@ PcpCache::_ComputePrimIndexesInParallel( TF_PY_ALLOW_THREADS_IN_SCOPE(); ArResolverScopedCache parentCache; - TfAutoMallocTag2 tag(mallocTag1, mallocTag2); + TfAutoMallocTag2 tag(mallocTag1, mallocTag2); - typedef Pcp_ParallelIndexer<_UntypedPredicate> Indexer; + using Indexer = Pcp_ParallelIndexer<_UntypedIndexingChildrenPredicate>; if (not _layerStack) ComputeLayerStack(GetLayerStackIdentifier(), allErrors); // General strategy: Compute indexes recursively starting from roots, in - // parallel. When we've computed an index, ask the predicate if we should - // continue to compute its children indexes. If so, we add all the children - // as new tasks for threads to pick up. + // parallel. When we've computed an index, ask the children predicate if we + // should continue to compute its children indexes. If so, we add all the + // children as new tasks for threads to pick up. // // Once all the indexes are computed, add them to the cache and add their // dependencies to the dependencies structures. - Indexer indexer(this, pred, _layerStack, + Indexer indexer(this, childrenPred, payloadPred, _layerStack, GetPrimIndexInputs().USD(_usd), allErrors, &parentCache, mallocTag1, mallocTag2); diff --git a/pxr/usd/lib/pcp/cache.h b/pxr/usd/lib/pcp/cache.h index bb0e83ac2d..35fe82b2d9 100644 --- a/pxr/usd/lib/pcp/cache.h +++ b/pxr/usd/lib/pcp/cache.h @@ -261,57 +261,73 @@ class PcpCache ComputePrimIndex(const SdfPath &primPath, PcpErrorVector *allErrors); /// Compute PcpPrimIndexes in the subtree rooted at path in parallel, - /// subject to the supplied predicate \p pred. This is similar to - /// ComputePrimIndex(), except it will compute an entire subtree of indexes - /// in parallel, so it can be much more efficient. This function invokes - /// \p pred concurrently, so it must be safe to do so. When a PcpPrimIndex - /// is finished being computed, this function invokes \p pred, passing it - /// the PcpPrimIndex. If \p pred returns true, this function will continue - /// to the children and compute their indexes. If \p pred returns false, - /// prim index computation ceases for that subtree. - template + /// recursing to children based on the supplied \p childrenPred. Also + /// include payloads not already in this cache's included payloads (see + /// GetIncludedPayloads()) according to \p payloadPred. + /// + /// This is similar to ComputePrimIndex(), except it computes an entire + /// subtree of indexes in parallel so it can be much more efficient. This + /// function invokes both \p childrenPred and \p payloadPred concurrently, + /// so it must be safe to do so. When a PcpPrimIndex computation completes + /// invoke \p childrenPred, passing it the PcpPrimIndex. If \p childrenPred + /// returns true, continue indexing children prim indexes. Conversely if + /// \p childrenPred returns false, stop indexing in that subtree. If + /// payloads discovered during indexing do not already appear in this + /// cache's set of included payloads, invoke \p payloadPred, passing it the + /// path for the prim with the payload. If \p payloadPred returns true, + /// include its payload and add it to the cache's set of included payloads + /// upon completion. + template void ComputePrimIndexesInParallel(const SdfPath &path, PcpErrorVector *allErrors, - const Predicate &pred) { - ComputePrimIndexesInParallel(SdfPathVector(1, path), allErrors, pred, + const ChildrenPredicate &childrenPred, + const PayloadPredicate &payloadPred) { + ComputePrimIndexesInParallel(SdfPathVector(1, path), allErrors, + childrenPred, payloadPred, "Pcp", "ComputePrimIndexesInParallel"); } /// \overload /// XXX Do not add new callers of this method. It is needed as a workaround /// for bug #132031, which we hope to tackle soon (as of 6/2016) - template + template void ComputePrimIndexesInParallel(const SdfPath &path, PcpErrorVector *allErrors, - const Predicate &pred, + const ChildrenPredicate &childrenPred, + const PayloadPredicate &payloadPred, const char *mallocTag1, const char *mallocTag2) { - ComputePrimIndexesInParallel(SdfPathVector(1, path), allErrors, pred. + ComputePrimIndexesInParallel(SdfPathVector(1, path), allErrors, + childrenPred, payloadPred, mallocTag1, mallocTag2); } /// Vectorized form of ComputePrimIndexesInParallel(). Equivalent to /// invoking that method for each path in \p paths, but more efficient. - template + template void ComputePrimIndexesInParallel(const SdfPathVector &paths, PcpErrorVector *allErrors, - const Predicate &pred) { - _UntypedPredicate p(&pred); - _ComputePrimIndexesInParallel(paths, allErrors, p, + const ChildrenPredicate &childrenPred, + const PayloadPredicate &payloadPred) { + _UntypedIndexingChildrenPredicate cp(&childrenPred); + _UntypedIndexingPayloadPredicate pp(&payloadPred); + _ComputePrimIndexesInParallel(paths, allErrors, cp, pp, "Pcp", "ComputePrimIndexesInParallel"); } /// \overload /// XXX Do not add new callers of this method. It is needed as a workaround /// for bug #132031, which we hope to tackle soon (as of 6/2016) - template + template void ComputePrimIndexesInParallel(const SdfPathVector &paths, PcpErrorVector *allErrors, - const Predicate &pred, + const ChildrenPredicate &childrenPred, + const PayloadPredicate &payloadPred, const char *mallocTag1, const char *mallocTag2) { - _UntypedPredicate p(&pred); - _ComputePrimIndexesInParallel(paths, allErrors, p, + _UntypedIndexingChildrenPredicate cp(&childrenPred); + _UntypedIndexingPayloadPredicate pp(&payloadPred); + _ComputePrimIndexesInParallel(paths, allErrors, cp, pp, mallocTag1, mallocTag2); } @@ -622,12 +638,12 @@ class PcpCache friend class PcpChanges; friend class Pcp_Statistics; - template + template friend struct Pcp_ParallelIndexer; struct _PathDebugInfo; - // Helper struct to type-erase a predicate for the duration of + // Helper struct to type-erase a children predicate for the duration of // ComputePrimIndexesInParallel. // // This lets us achieve two goals. First, clients may pass any arbitrary @@ -640,9 +656,9 @@ class PcpCache // typecast and predicate invocation, and pass that function pointer into // the implementation. There is no heap allocation, no predicate copy, no // argument marshalling, etc. - struct _UntypedPredicate { + struct _UntypedIndexingChildrenPredicate { template - explicit _UntypedPredicate(const Pred *pred) + explicit _UntypedIndexingChildrenPredicate(const Pred *pred) : pred(pred), invoke(_Invoke) {} inline bool operator()(const PcpPrimIndex &index) const { @@ -657,13 +673,34 @@ class PcpCache bool (*invoke)(const void *, const PcpPrimIndex &); }; + // See doc for _UntypedIndexingChildrenPredicate above. This does the same + // for the payload inclusion predicate. + struct _UntypedIndexingPayloadPredicate { + template + explicit _UntypedIndexingPayloadPredicate(const Pred *pred) + : pred(pred), invoke(_Invoke) {} + + inline bool operator()(const SdfPath &path) const { + return invoke(pred, path); + } + private: + template + static bool _Invoke(const void *pred, const SdfPath &path) { + return (*static_cast(pred))(path); + } + const void *pred; + bool (*invoke)(const void *, const SdfPath &); + }; + // Parallel indexing implementation. - PCP_API - void _ComputePrimIndexesInParallel(const SdfPathVector &paths, - PcpErrorVector *allErrors, - _UntypedPredicate pred, - const char *mallocTag1, - const char *mallocTag2); + PCP_API + void _ComputePrimIndexesInParallel( + const SdfPathVector &paths, + PcpErrorVector *allErrors, + _UntypedIndexingChildrenPredicate childrenPred, + _UntypedIndexingPayloadPredicate payloadPred, + const char *mallocTag1, + const char *mallocTag2); // Helper to add a computed prim index to dependency structures. PCP_API diff --git a/pxr/usd/lib/pcp/changes.cpp b/pxr/usd/lib/pcp/changes.cpp index 2a92ee4295..1d479c641d 100644 --- a/pxr/usd/lib/pcp/changes.cpp +++ b/pxr/usd/lib/pcp/changes.cpp @@ -721,31 +721,65 @@ PcpChanges::DidChange(const std::vector& caches, // (layer,path). If there aren't any and we want to fallback to our // parent then find all paths in the cache that use the parent. In // either case mark the found paths as having a significant change. - if (not pathsWithSignificantChanges.empty()) { - BOOST_FOREACH(const SdfPath& path, pathsWithSignificantChanges) { - // Compute the closest ancestor that must have dependencies. - SdfPath fallbackPath = findAncestor(path); - - BOOST_FOREACH(PcpCache* cache, caches) { - _DidChangeDependents( - _ChangeTypeSignificant, cache, layer, - path, fallbackPath, debugSummary); - } + BOOST_FOREACH(const SdfPath& path, pathsWithSignificantChanges) { + // Compute the closest ancestor that must have dependencies. + SdfPath fallbackPath = findAncestor(path); + + BOOST_FOREACH(PcpCache* cache, caches) { + _DidChangeDependents( + _ChangeTypeSignificant, cache, layer, + path, fallbackPath, debugSummary); } } // For every path we've found that has a significant change in // a specific cache, use the same logic as above to mark those paths // as having a significant change, but only in the associated cache. - if (not pathsWithSignificantChangesByCache.empty()) { - BOOST_FOREACH(const CacheAndLayerPathPair& p, - pathsWithSignificantChangesByCache) { - // Compute the closest ancestor that must have dependencies. - SdfPath fallbackPath = findAncestor(p.second); + BOOST_FOREACH(const CacheAndLayerPathPair& p, + pathsWithSignificantChangesByCache) { + // Compute the closest ancestor that must have dependencies. + SdfPath fallbackPath = findAncestor(p.second); + + _DidChangeDependents( + _ChangeTypeSignificant, p.first, layer, + p.second, fallbackPath, debugSummary); + } - _DidChangeDependents( - _ChangeTypeSignificant, p.first, layer, - p.second, fallbackPath, debugSummary); + // For every path we've found that has a significant change, + // check layer stacks that have discovered relocations that + // could be affected by that change. + if (not pathsWithSignificantChanges.empty()) { + // If this scope turns out to be expensive, we should look + // at switching PcpLayerStack's _relocatesPrimPaths from + // a std::vector to a path set. _AddRelocateEditsForLayerStack + // also does a traversal and might see a similar benefit. + TRACE_SCOPE("PcpChanges::DidChange -- Checking layer stack " + "relocations against significant prim resyncs"); + + for(const CacheLayerStacks &i: cacheLayerStacks) { + if (i.first->_usd) { + // No relocations in usd mode + continue; + } + for(const PcpLayerStackPtr &layerStack: i.second) { + const SdfPathVector& reloPaths = + layerStack->GetPathsToPrimsWithRelocates(); + if (reloPaths.empty()) { + continue; + } + for(const SdfPath &changedPath: + pathsWithSignificantChanges) { + for(const SdfPath &reloPath: reloPaths) { + if (reloPath.HasPrefix(changedPath)) { + layerStackChangesMap[layerStack] + |= LayerStackRelocatesChange; + goto doneWithLayerStack; + } + } + } + doneWithLayerStack: + ; + } } } @@ -755,33 +789,31 @@ PcpChanges::DidChange(const std::vector& caches, // there aren't any then find all paths in the cache that use the // parent. In either case mark the found paths as needing their // property spec stacks blown. - if (not pathsWithSpecChanges.empty()) { - BOOST_FOREACH(const PathChangeValue& value, pathsWithSpecChanges) { - const SdfPath& path = value.first; - PathChangeBitmask changes = value.second; - - int changeType = 0; - if (changes & PathChangeTargets) { - changeType |= _ChangeTypeTargets; - } - if (changes & PathChangeConnections) { - changeType |= _ChangeTypeConnections; - } + BOOST_FOREACH(const PathChangeValue& value, pathsWithSpecChanges) { + const SdfPath& path = value.first; + PathChangeBitmask changes = value.second; - // If the changes for this path include something other than - // target changes, they must be spec changes. - if (changes & ~(PathChangeTargets | PathChangeConnections)) { - changeType |= _ChangeTypeSpecs; - } + int changeType = 0; + if (changes & PathChangeTargets) { + changeType |= _ChangeTypeTargets; + } + if (changes & PathChangeConnections) { + changeType |= _ChangeTypeConnections; + } - // Compute the closest ancestor that must have dependencies. - SdfPath fallbackPath = findAncestor(path); + // If the changes for this path include something other than + // target changes, they must be spec changes. + if (changes & ~(PathChangeTargets | PathChangeConnections)) { + changeType |= _ChangeTypeSpecs; + } - BOOST_FOREACH(PcpCache* cache, caches) { - _DidChangeDependents( - changeType, cache, layer, - path, fallbackPath, debugSummary); - } + // Compute the closest ancestor that must have dependencies. + SdfPath fallbackPath = findAncestor(path); + + BOOST_FOREACH(PcpCache* cache, caches) { + _DidChangeDependents( + changeType, cache, layer, + path, fallbackPath, debugSummary); } } diff --git a/pxr/usd/lib/pcp/mapExpression.cpp b/pxr/usd/lib/pcp/mapExpression.cpp index 2b5ec22d46..02e7268ab5 100644 --- a/pxr/usd/lib/pcp/mapExpression.cpp +++ b/pxr/usd/lib/pcp/mapExpression.cpp @@ -27,12 +27,7 @@ #include "pxr/base/tracelite/trace.h" -#if MAYA_TBB_HANG_WORKAROUND_HACK -#include -#include -#else #include -#endif // MAYA_TBB_HANG_WORKAROUND_HACK class Pcp_VariableImpl; @@ -175,24 +170,10 @@ struct _KeyHashEq { inline bool equal(const Key &l, const Key &r) const { return l == r; } inline size_t hash(const Key &k) const { return k.GetHash(); } - -#if MAYA_TBB_HANG_WORKAROUND_HACK - inline size_t operator()(const Key &k) const { return hash(k); } -#endif // MAYA_TBB_HANG_WORKAROUND_HACK }; } // anon -#if MAYA_TBB_HANG_WORKAROUND_HACK -struct PcpMapExpression::_Node::_NodeMap -{ - typedef PcpMapExpression::_Node::Key Key; - typedef std::unordered_map< - Key, PcpMapExpression::_Node *, _KeyHashEq > MapType; - MapType map; - tbb::spin_mutex mutex; -}; -#else struct PcpMapExpression::_Node::_NodeMap { typedef PcpMapExpression::_Node::Key Key; @@ -201,7 +182,6 @@ struct PcpMapExpression::_Node::_NodeMap typedef MapType::accessor accessor; MapType map; }; -#endif // MAYA_TBB_HANG_WORKAROUND_HACK TfStaticData PcpMapExpression::_Node::_nodeRegistry; @@ -254,25 +234,6 @@ PcpMapExpression::_Node::New( _Op op_, if (key.op != _OpVariable) { // Check for existing instance to re-use -#if MAYA_TBB_HANG_WORKAROUND_HACK - tbb::spin_mutex::scoped_lock lock(_nodeRegistry->mutex); - - std::pair<_NodeMap::MapType::iterator, bool> accessor = - _nodeRegistry->map.insert(std::make_pair(key, nullptr)); - if (accessor.second or - accessor.first->second->_refCount.fetch_and_increment() == 0) { - // Either there was no node in the table, or there was but it had - // begun dying (another client dropped its refcount to 0). We have - // to create a new node in the table. When the client that is - // killing the other node it looks for itself in the table, it will - // either not find itself or will find a different node and so won't - // remove it. - _NodeRefPtr newNode(new _Node(key)); - accessor.first->second = newNode.get(); - return newNode; - } - return _NodeRefPtr(accessor.first->second, /*add_ref =*/ false); -#else _NodeMap::accessor accessor; if (_nodeRegistry->map.insert(accessor, key) or accessor->second->_refCount.fetch_and_increment() == 0) { @@ -287,7 +248,6 @@ PcpMapExpression::_Node::New( _Op op_, return newNode; } return _NodeRefPtr(accessor->second, /*add_ref =*/ false); -#endif // MAYA_TBB_HANG_WORKAROUND_HACK } return _NodeRefPtr(new _Node(key)); } @@ -319,22 +279,12 @@ PcpMapExpression::_Node::~_Node() } if (key.op != _OpVariable) { -#if MAYA_TBB_HANG_WORKAROUND_HACK - tbb::spin_mutex::scoped_lock lock(_nodeRegistry->mutex); - // Remove from node map if present. - _NodeMap::MapType::iterator accessor = _nodeRegistry->map.find(key); - if (accessor != _nodeRegistry->map.end() and - accessor->second == this) { - _nodeRegistry->map.erase(accessor); - } -#else // Remove from node map if present. _NodeMap::accessor accessor; if (_nodeRegistry->map.find(accessor, key) and accessor->second == this) { _nodeRegistry->map.erase(accessor); } -#endif // MAYA_TBB_HANG_WORKAROUND_HACK } } diff --git a/pxr/usd/lib/pcp/primIndex.cpp b/pxr/usd/lib/pcp/primIndex.cpp index b5b60b6c37..b3a754b13d 100644 --- a/pxr/usd/lib/pcp/primIndex.cpp +++ b/pxr/usd/lib/pcp/primIndex.cpp @@ -3394,13 +3394,33 @@ _EvalNodePayload( // Mark that this prim index contains a payload. // However, only process the payload if it's been requested. index->GetGraph()->SetHasPayload(true); + const PcpPrimIndexInputs::PayloadSet* includedPayloads = indexer->inputs.includedPayloads; - if (not includedPayloads or - includedPayloads->count(node.GetRootNode().GetPath()) == 0) { + + // If includedPayloads is nullptr, we never include payloads. Otherwise if + // it does not have this path, we invoke the predicate. If the predicate + // returns true we set the output bit includedDiscoveredPayload and we + // compose it. + if (!includedPayloads) { PCP_GRAPH_MSG(node, "Payload was not included, skipping"); return; } + SdfPath const &path = node.GetRootNode().GetPath(); + tbb::spin_rw_mutex::scoped_lock lock; + auto *mutex = indexer->inputs.includedPayloadsMutex; + if (mutex) { lock.acquire(*mutex, /*write=*/false); } + bool inIncludeSet = includedPayloads->count(path); + if (mutex) { lock.release(); } + if (!inIncludeSet) { + auto const &pred = indexer->inputs.includePayloadPredicate; + if (pred and pred(path)) { + indexer->outputs->includedDiscoveredPayload = true; + } else { + PCP_GRAPH_MSG(node, "Payload was not included, skipping"); + return; + } + } // Verify the payload prim path. if (not payload.GetPrimPath().IsEmpty() and diff --git a/pxr/usd/lib/pcp/primIndex.h b/pxr/usd/lib/pcp/primIndex.h index 8ce2361fd3..3531ead7cc 100644 --- a/pxr/usd/lib/pcp/primIndex.h +++ b/pxr/usd/lib/pcp/primIndex.h @@ -37,6 +37,8 @@ #include "pxr/base/tf/hashset.h" #include #include +#include +#include #include SDF_DECLARE_HANDLES(SdfLayer); @@ -305,6 +307,10 @@ class PcpPrimIndexOutputs /// List of all errors encountered during indexing. PcpErrorVector allErrors; + + /// True if this prim index has a payload that we included during indexing + /// that wasn't previously in the cache's payload include set. + bool includedDiscoveredPayload = false; /// Swap content with \p r. inline void swap(PcpPrimIndexOutputs &r) { @@ -316,6 +322,7 @@ class PcpPrimIndexOutputs spookyDependencySites.swap(r.spookyDependencySites); spookyDependencyNodes.swap(r.spookyDependencyNodes); allErrors.swap(r.allErrors); + std::swap(includedDiscoveredPayload, r.includedDiscoveredPayload); } }; @@ -329,13 +336,14 @@ inline void swap(PcpPrimIndexOutputs &l, PcpPrimIndexOutputs &r) { l.swap(r); } class PcpPrimIndexInputs { public: PcpPrimIndexInputs() - : cache(NULL) - , variantFallbacks(NULL) - , includedPayloads(NULL) - , parentIndex(NULL) + : cache(nullptr) + , variantFallbacks(nullptr) + , includedPayloads(nullptr) + , includedPayloadsMutex(nullptr) + , parentIndex(nullptr) + , payloadDecorator(nullptr) , cull(true) , usd(false) - , payloadDecorator(NULL) { } /// Returns true if prim index computations using this parameters object @@ -363,6 +371,18 @@ class PcpPrimIndexInputs { PcpPrimIndexInputs& IncludedPayloads(const PayloadSet* payloadSet) { includedPayloads = payloadSet; return *this; } + /// Optional mutex for accessing includedPayloads. + PcpPrimIndexInputs &IncludedPayloadsMutex(tbb::spin_rw_mutex *mutex) + { includedPayloadsMutex = mutex; return *this; } + + /// Optional predicate evaluated when a not-yet-included payload is + /// discovered while indexing. If the predicate returns true, indexing + /// includes the payload and sets the includedDiscoveredPayload bit in the + /// outputs. + PcpPrimIndexInputs &IncludePayloadPredicate( + std::function predicate) + { includePayloadPredicate = predicate; return *this; } + /// Whether subtrees that contribute no opinions should be culled /// from the index. PcpPrimIndexInputs& Cull(bool doCulling = true) @@ -383,11 +403,13 @@ class PcpPrimIndexInputs { PcpCache* cache; const PcpVariantFallbackMap* variantFallbacks; const PayloadSet* includedPayloads; + tbb::spin_rw_mutex *includedPayloadsMutex; + std::function includePayloadPredicate; const PcpPrimIndex *parentIndex; - bool cull; - bool usd; std::string targetSchema; PcpPayloadDecorator* payloadDecorator; + bool cull; + bool usd; }; /// Compute an index for the given path. \p errors will contain any errors diff --git a/pxr/usd/lib/pcp/primIndex_Graph.cpp b/pxr/usd/lib/pcp/primIndex_Graph.cpp index eeee8ed1a4..62eaf8f067 100644 --- a/pxr/usd/lib/pcp/primIndex_Graph.cpp +++ b/pxr/usd/lib/pcp/primIndex_Graph.cpp @@ -593,8 +593,8 @@ PcpPrimIndex_Graph::_InsertChildInStrengthOrder( void PcpPrimIndex_Graph::_DetachSharedNodePool() { - TRACE_FUNCTION(); if (not _data.unique()) { + TRACE_FUNCTION(); _data.reset(new _SharedData(*_data)); // XXX: This probably causes more finalization than necessary. Only diff --git a/pxr/usd/lib/pcp/statistics.cpp b/pxr/usd/lib/pcp/statistics.cpp index 70285ffd98..eb2e6ef874 100644 --- a/pxr/usd/lib/pcp/statistics.cpp +++ b/pxr/usd/lib/pcp/statistics.cpp @@ -24,6 +24,7 @@ #include "pxr/usd/pcp/statistics.h" #include "pxr/usd/pcp/cache.h" +#include "pxr/usd/pcp/layerStackRegistry.h" #include "pxr/usd/pcp/primIndex.h" #include "pxr/usd/pcp/primIndex_Graph.h" @@ -65,6 +66,7 @@ struct Pcp_CacheStats Pcp_GraphStats sharedAllGraphStats; Pcp_GraphStats sharedCulledGraphStats; std::map mapFunctionSizeDistribution; + std::map layerStackRelocationsSizeDistribution; }; class Pcp_Statistics @@ -154,6 +156,13 @@ class Pcp_Statistics size_t size = i->GetSourceToTargetMap().size(); stats->mapFunctionSizeDistribution[size] += 1; } + + // PcpLayerStack _relocatesPrimPaths size distribution + for(const PcpLayerStackPtr &layerStack: + cache->_layerStackCache->GetAllLayerStacks()) { + size_t size = layerStack->GetPathsToPrimsWithRelocates().size(); + stats->layerStackRelocationsSizeDistribution[size] += 1; + } } // Shamelessly stolen from Csd/Scene_PrimCachePopulation.cpp. @@ -309,6 +318,12 @@ class Pcp_Statistics printf("%zu %zu\n", i->first, i->second); } + out << "PcpLayerStack pathsWithRelocates size histogram: " << endl; + out << "SIZE COUNT" << endl; + TF_FOR_ALL(i, stats.layerStackRelocationsSizeDistribution) { + printf("%zu %zu\n", i->first, i->second); + } + // Assert sizes of structs we want to keep a close eye on. #if defined(ARCH_COMPILER_HAS_STATIC_ASSERT) BOOST_STATIC_ASSERT(sizeof(PcpMapFunction) == 8); diff --git a/pxr/usd/lib/pcp/wrapLayerStack.cpp b/pxr/usd/lib/pcp/wrapLayerStack.cpp index dce389bc49..c56730bb3a 100644 --- a/pxr/usd/lib/pcp/wrapLayerStack.cpp +++ b/pxr/usd/lib/pcp/wrapLayerStack.cpp @@ -72,29 +72,27 @@ void wrapLayerStack() .add_property("layers", make_function(&_GetLayerStackLayers, return_value_policy())) - .add_property("layerOffsets", make_function(&_GetLayerOffsets, return_value_policy())) - .add_property("layerTree", make_function(&PcpLayerStack::GetLayerTree, return_value_policy())) - .add_property("resolvedAssetPaths", make_function(&_GetResolvedAssetPaths, return_value_policy())) - .add_property("relocatesSourceToTarget", make_function(&PcpLayerStack::GetRelocatesSourceToTarget, return_value_policy())) - .add_property("relocatesTargetToSource", make_function(&PcpLayerStack::GetRelocatesTargetToSource, return_value_policy())) .add_property("localErrors", make_function(&PcpLayerStack::GetLocalErrors, return_value_policy())) + .add_property("pathsToPrimsWithRelocates", + make_function(&PcpLayerStack::GetPathsToPrimsWithRelocates, + return_value_policy())) // TODO: repr, eq, etc. ; } diff --git a/pxr/usd/lib/sdf/layer.cpp b/pxr/usd/lib/sdf/layer.cpp index 9e739f7500..ea3bbc666d 100644 --- a/pxr/usd/lib/sdf/layer.cpp +++ b/pxr/usd/lib/sdf/layer.cpp @@ -66,9 +66,10 @@ #include #include +#include +#include #include #include -#include using boost::bind; using std::map; @@ -88,6 +89,11 @@ typedef set _MutedLayers; static TfStaticData<_MutedLayers> _mutedLayers; // Global mutex protecting _mutedLayers. static TfStaticData _mutedLayersMutex; +// This is a global revision number that tracks changes to _mutedLayers. Since +// we seldom mute and unmute layers, this lets layers cache their muteness and +// do quick validity checks without taking a lock and looking themselves up in +// _mutedLayers. +static std::atomic_size_t _mutedLayersRevision { 1 }; // A registry for loaded layers. static TfStaticData _layerRegistry; @@ -107,6 +113,8 @@ SdfLayer::SdfLayer( _lastDirtyState(false), _assetInfo(new Sdf_AssetInfo), _assetModificationTime(0), + _mutedLayersRevisionCache(0), + _isMutedCache(false), _permissionToEdit(true), _permissionToSave(true) { @@ -1696,8 +1704,6 @@ SdfLayer::GetRelationshipAtPath(const SdfPath &path) bool SdfLayer::PermissionToEdit() const { - TRACE_FUNCTION(); - return _permissionToEdit and not IsMuted(); } @@ -2228,6 +2234,8 @@ SdfLayer::GetMutedLayers() void SdfLayer::SetMuted(bool muted) { + // XXX Racy... + if (muted == IsMuted()) { return; } @@ -2242,8 +2250,25 @@ SdfLayer::SetMuted(bool muted) bool SdfLayer::IsMuted() const -{ - return IsMuted(_GetMutedPath()); +{ + // Read the current muted revision number. If it's up-to-date we return our + // cache. It's possible that this is racy, but the whole thing is racy + // regardless. Even with a pure locking implementation, say we found this + // layer in the muted set -- by the time we return to the caller with + // 'true', some other thread may have removed this layer from the muted set. + + size_t curRev = _mutedLayersRevision; + if (ARCH_UNLIKELY(_mutedLayersRevisionCache != curRev)) { + string mutedPath = _GetMutedPath(); + std::lock_guard lock(*_mutedLayersMutex); + // Read again, since this is guaranteed to give us the current value + // because we have the lock. _mutedLayersRevision only changes with the + // lock held. + _mutedLayersRevisionCache = _mutedLayersRevision; + _isMutedCache = _mutedLayers->count(mutedPath); + } + + return _isMutedCache; } /*static*/ @@ -2260,7 +2285,9 @@ SdfLayer::AddToMutedLayers(const string &path) { bool didChange = false; { + // Racy... std::lock_guard lock(*_mutedLayersMutex); + ++_mutedLayersRevision; didChange = _mutedLayers->insert(path).second; } if (didChange) { @@ -2277,7 +2304,9 @@ SdfLayer::RemoveFromMutedLayers(const string &path) { bool didChange = false; { + // Racy... std::lock_guard lock(*_mutedLayersMutex); + ++_mutedLayersRevision; didChange = _mutedLayers->erase(path); } if (didChange) { @@ -2803,40 +2832,38 @@ void SdfLayer::SetField(const SdfAbstractDataSpecId& id, const TfToken& fieldName, const VtValue& value) { - if (not PermissionToEdit()) { + if (value.IsEmpty()) + return EraseField(id, fieldName); + + if (ARCH_UNLIKELY(not PermissionToEdit())) { TF_CODING_ERROR("Cannot set %s on <%s>. Layer @%s@ is not editable.", fieldName.GetText(), id.GetString().c_str(), GetIdentifier().c_str()); return; } - if (value.IsEmpty()) { - EraseField(id, fieldName); - } else { - VtValue oldValue = GetField(id, fieldName); - if (value != oldValue) - _PrimSetField(id, fieldName, value, &oldValue); - } + VtValue oldValue = GetField(id, fieldName); + if (value != oldValue) + _PrimSetField(id, fieldName, value, &oldValue); } void SdfLayer::SetField(const SdfAbstractDataSpecId& id, const TfToken& fieldName, const SdfAbstractDataConstValue& value) { - if (not PermissionToEdit()) { + if (value.IsEqual(VtValue())) + return EraseField(id, fieldName); + + if (ARCH_UNLIKELY(not PermissionToEdit())) { TF_CODING_ERROR("Cannot set %s on <%s>. Layer @%s@ is not editable.", fieldName.GetText(), id.GetString().c_str(), GetIdentifier().c_str()); return; } - - if (value.IsEqual(VtValue())) { - EraseField(id, fieldName); - } else { - VtValue oldValue = GetField(id, fieldName); - if (not value.IsEqual(oldValue)) - _PrimSetField(id, fieldName, value, &oldValue); - } + + VtValue oldValue = GetField(id, fieldName); + if (not value.IsEqual(oldValue)) + _PrimSetField(id, fieldName, value, &oldValue); } void @@ -2884,7 +2911,7 @@ SdfLayer::SetFieldDictValueByKey(const SdfAbstractDataSpecId& id, void SdfLayer::EraseField(const SdfAbstractDataSpecId& id, const TfToken& fieldName) { - if (not PermissionToEdit()) { + if (ARCH_UNLIKELY(not PermissionToEdit())) { TF_CODING_ERROR("Cannot erase %s on <%s>. Layer @%s@ is not editable.", fieldName.GetText(), id.GetString().c_str(), GetIdentifier().c_str()); diff --git a/pxr/usd/lib/sdf/layer.h b/pxr/usd/lib/sdf/layer.h index bfc905ee20..f8e93d54a0 100644 --- a/pxr/usd/lib/sdf/layer.h +++ b/pxr/usd/lib/sdf/layer.h @@ -1624,6 +1624,13 @@ class SdfLayer : public SdfLayerBase // Modification timestamp of the backing file asset when last read. mutable double _assetModificationTime; + // Mutable revision number for cache invalidation. + mutable size_t _mutedLayersRevisionCache; + + // Cache of whether or not this layer is muted. Only valid if + // _mutedLayersRevisionCache is up-to-date with the global revision number. + mutable bool _isMutedCache; + // Layer permission bits. bool _permissionToEdit; bool _permissionToSave; diff --git a/pxr/usd/lib/sdf/pathNode.cpp b/pxr/usd/lib/sdf/pathNode.cpp index 99aeb2b0ae..76bd0f6ba3 100644 --- a/pxr/usd/lib/sdf/pathNode.cpp +++ b/pxr/usd/lib/sdf/pathNode.cpp @@ -41,11 +41,6 @@ #include #include -#if MAYA_TBB_HANG_WORKAROUND_HACK -#include -#include -#endif // MAYA_TBB_HANG_WORKAROUND_HACK - using std::string; using std::vector; @@ -82,16 +77,6 @@ struct _ParentAnd { const Sdf_PathNode *parent; T value; }; // Allow void for 'expression' path case, which has no additional data. template <> struct _ParentAnd { const Sdf_PathNode *parent; }; -#if MAYA_TBB_HANG_WORKAROUND_HACK -template -bool operator==(_ParentAnd const &l, _ParentAnd const &r) { - return l.parent == r.parent && l.value == r.value; -} -bool operator==(_ParentAnd const &l, _ParentAnd const &r) { - return l.parent == r.parent; -} -#endif // MAYA_TBB_HANG_WORKAROUND_HACK - template inline _ParentAnd _MakeParentAnd(const Sdf_PathNode *parent, const T &value) { @@ -126,13 +111,7 @@ struct _HashParentAnd boost::hash_combine(h, t.value); return h; } - -#if MAYA_TBB_HANG_WORKAROUND_HACK - inline size_t operator()(const T &t) const { - return hash(t); - } -#endif // MAYA_TBB_HANG_WORKAROUND_HACK -}; + }; template <> struct _HashParentAnd<_ParentAnd > @@ -145,23 +124,13 @@ struct _HashParentAnd<_ParentAnd > inline size_t hash(const _ParentAnd &t) const { return hash_value(t.parent); } - -#if MAYA_TBB_HANG_WORKAROUND_HACK - inline size_t operator()(const _ParentAnd &t) const { - return hash(t); - } -#endif // MAYA_TBB_HANG_WORKAROUND_HACK }; template struct _Table { -#if MAYA_TBB_HANG_WORKAROUND_HACK - typedef std::unordered_map<_ParentAnd, const Sdf_PathNode *, - _HashParentAnd<_ParentAnd > > Type; -#else - typedef tbb::concurrent_hash_map<_ParentAnd, const Sdf_PathNode *, - _HashParentAnd<_ParentAnd > > Type; -#endif // MAYA_TBB_HANG_WORKAROUND_HACK + typedef tbb::concurrent_hash_map< + _ParentAnd, const Sdf_PathNode *, + _HashParentAnd<_ParentAnd > > Type; }; typedef _Table::Type _TokenTable; @@ -169,30 +138,12 @@ typedef _Table::Type _VarSelTable; typedef _Table::Type _PathTable; typedef _Table::Type _VoidTable; -#if MAYA_TBB_HANG_WORKAROUND_HACK -static tbb::spin_mutex &_GetTableLock() { - static tbb::spin_mutex mutex; - return mutex; -} -#endif // MAYA_TBB_HANG_WORKAROUND_HACK - template inline Sdf_PathNodeConstRefPtr _FindOrCreate(Table &table, const Sdf_PathNodeConstRefPtr &parent, const Arg &arg) { -#if MAYA_TBB_HANG_WORKAROUND_HACK - tbb::spin_mutex::scoped_lock lock(_GetTableLock()); - auto iresult = table.emplace(_MakeParentAnd(parent.get(), arg), nullptr); - if (iresult.second or - Access::GetRefCount(iresult.first->second).fetch_and_increment() == 0) { - Sdf_PathNodeConstRefPtr newNode = Access::New(parent, arg); - iresult.first->second = newNode.get(); - return newNode; - } - return Sdf_PathNodeConstRefPtr(iresult.first->second, /* add_ref = */ false); -#else // MAYA_TBB_HANG_WORKAROUND_HACK typename Table::accessor accessor; if (table.insert(accessor, _MakeParentAnd(parent.get(), arg)) or Access::GetRefCount(accessor->second).fetch_and_increment() == 0) { @@ -206,24 +157,12 @@ _FindOrCreate(Table &table, return newNode; } return Sdf_PathNodeConstRefPtr(accessor->second, /* add_ref = */ false); -#endif // MAYA_TBB_HANG_WORKAROUND_HACK } template inline Sdf_PathNodeConstRefPtr _FindOrCreate(Table &table, const Sdf_PathNodeConstRefPtr &parent) { -#if MAYA_TBB_HANG_WORKAROUND_HACK - tbb::spin_mutex::scoped_lock lock(_GetTableLock()); - auto iresult = table.emplace(_MakeParentAnd(parent.get()), nullptr); - if (iresult.second or - Access::GetRefCount(iresult.first->second).fetch_and_increment() == 0) { - Sdf_PathNodeConstRefPtr newNode = Access::New(parent); - iresult.first->second = newNode.get(); - return newNode; - } - return Sdf_PathNodeConstRefPtr(iresult.first->second, /* add_ref = */ false); -#else // MAYA_TBB_HANG_WORKAROUND_HACK typename Table::accessor accessor; if (table.insert(accessor, _MakeParentAnd(parent.get())) or Access::GetRefCount(accessor->second).fetch_and_increment() == 0) { @@ -237,7 +176,6 @@ _FindOrCreate(Table &table, const Sdf_PathNodeConstRefPtr &parent) return newNode; } return Sdf_PathNodeConstRefPtr(accessor->second, /* add_ref = */ false); -#endif // MAYA_TBB_HANG_WORKAROUND_HACK } template @@ -245,12 +183,6 @@ inline void _Remove(const Sdf_PathNode *pathNode, Table &table, const Sdf_PathNodeConstRefPtr &parent, const Arg &arg) { -#if MAYA_TBB_HANG_WORKAROUND_HACK - tbb::spin_mutex::scoped_lock lock(_GetTableLock()); - auto iter = table.find(_MakeParentAnd(parent.get(), arg)); - if (iter != table.end() and iter->second == pathNode) - table.erase(iter); -#else // MAYA_TBB_HANG_WORKAROUND_HACK // If there's an entry for this key that has pathNode, erase it. Even if // there's an entry present it may not be pathNode, since another node may // have been created since we decremented our refcount and started being @@ -260,7 +192,6 @@ _Remove(const Sdf_PathNode *pathNode, accessor->second == pathNode) { table.erase(accessor); } -#endif // MAYA_TBB_HANG_WORKAROUND_HACK } template @@ -268,12 +199,6 @@ inline void _Remove(const Sdf_PathNode *pathNode, Table &table, const Sdf_PathNodeConstRefPtr &parent) { -#if MAYA_TBB_HANG_WORKAROUND_HACK - tbb::spin_mutex::scoped_lock lock(_GetTableLock()); - auto iter = table.find(_MakeParentAnd(parent.get())); - if (iter != table.end() and iter->second == pathNode) - table.erase(iter); -#else // MAYA_TBB_HANG_WORKAROUND_HACK // If there's an entry for this key that has pathNode, erase it. Even if // there's an entry present it may not be pathNode, since another node may // have been created since we decremented our refcount and started being @@ -283,7 +208,6 @@ _Remove(const Sdf_PathNode *pathNode, accessor->second == pathNode) { table.erase(accessor); } -#endif // MAYA_TBB_HANG_WORKAROUND_HACK } } // anon diff --git a/pxr/usd/lib/usd/crateData.cpp b/pxr/usd/lib/usd/crateData.cpp index e0e13b199d..0610c7b4db 100644 --- a/pxr/usd/lib/usd/crateData.cpp +++ b/pxr/usd/lib/usd/crateData.cpp @@ -36,6 +36,8 @@ #include "pxr/base/work/utils.h" #include "pxr/base/work/loops.h" +#include "pxr/usd/sdf/schema.h" + #include #include @@ -150,14 +152,47 @@ class Usd_CrateDataImpl return false; } + inline bool _HasTargetSpec(SdfPath const &path) const { + // We don't store target specs to save space, since in Usd we don't have + // any fields that may be set on them. Their presence is determined by + // whether or not they appear in their owning relationship's Added or + // Explicit items. + SdfPath parentPath = path.GetParentPath(); + if (parentPath.IsPrimPropertyPath()) { + VtValue targetPaths; + if (Has(SdfAbstractDataSpecId(&parentPath), + SdfFieldKeys->TargetPaths, &targetPaths) and + targetPaths.IsHolding()) { + auto const &listOp = targetPaths.UncheckedGet(); + if (listOp.IsExplicit()) { + auto const &items = listOp.GetExplicitItems(); + return std::find( + items.begin(), items.end(), path) != items.end(); + } else { + auto const &items = listOp.GetAddedItems(); + return std::find( + items.begin(), items.end(), path) != items.end(); + } + } + } + return false; + } + inline bool HasSpec(const SdfAbstractDataSpecId &id) const { const SdfPath &path = id.GetFullSpecPath(); + if (ARCH_UNLIKELY(path.IsTargetPath())) { + return _HasTargetSpec(path); + } return _hashData ? _hashData->find(path) != _hashData->end() : _flatData.find(path) != _flatData.end(); } inline void EraseSpec(const SdfAbstractDataSpecId &id) { + if (ARCH_UNLIKELY(id.GetFullSpecPath().IsTargetPath())) { + // Do nothing, we do not store target specs. + return; + } if (_MaybeMoveToHashTable()) { _hashLastSet = nullptr; TF_VERIFY(_hashData->erase(id.GetFullSpecPath()), @@ -175,6 +210,11 @@ class Usd_CrateDataImpl inline void MoveSpec(const SdfAbstractDataSpecId& oldId, const SdfAbstractDataSpecId& newId) { + if (ARCH_UNLIKELY(oldId.GetFullSpecPath().IsTargetPath())) { + // Do nothing, we do not store target specs. + return; + } + SdfPath const &oldPath = oldId.GetFullSpecPath(); SdfPath const &newPath = newId.GetFullSpecPath(); @@ -211,8 +251,13 @@ class Usd_CrateDataImpl inline SdfSpecType GetSpecType(const SdfAbstractDataSpecId &id) const { SdfPath const &path = id.GetFullSpecPath(); - if (path == SdfPath::AbsoluteRootPath()) + if (path == SdfPath::AbsoluteRootPath()) { return SdfSpecTypePseudoRoot; + } + if (path.IsTargetPath()) { + return _HasTargetSpec(path) ? + SdfSpecTypeRelationshipTarget : SdfSpecTypeUnknown; + } if (_hashData) { auto i = _hashData->find(path); return i == _hashData->end() ? @@ -222,19 +267,18 @@ class Usd_CrateDataImpl if (i == _flatData.end()) return SdfSpecTypeUnknown; // Don't look up in the table if we can tell the type from the path. - if (path.IsPrimPath()) - return SdfSpecTypePrim; - // In Usd, target paths may only ever identify relationship targets, - // since Usd does not have support for attribute connections. - if (path.IsTargetPath()) - return SdfSpecTypeRelationshipTarget; - return _flatTypes[i - _flatData.begin()].type; + return path.IsPrimPath() ? SdfSpecTypePrim : + _flatTypes[i - _flatData.begin()].type; } inline void CreateSpec(const SdfAbstractDataSpecId &id, SdfSpecType specType) { if (not TF_VERIFY(specType != SdfSpecTypeUnknown)) return; + if (id.GetFullSpecPath().IsTargetPath()) { + // Do nothing, we do not store relationship target specs in usd. + return; + } if (_MaybeMoveToHashTable()) { // No need to blow the _hashLastSet cache here, since inserting into // the table won't invalidate existing references. @@ -255,6 +299,7 @@ class Usd_CrateDataImpl inline void _VisitSpecs(SdfAbstractData const &data, SdfAbstractDataSpecVisitor* visitor) const { + // XXX: Is it important to present relationship target specs here? if (_hashData) { for (auto const &p: *_hashData) { if (not visitor->VisitSpec( @@ -383,6 +428,12 @@ class Usd_CrateDataImpl Erase(id, fieldName); return; } + if (id.GetFullSpecPath().IsTargetPath()) { + TF_CODING_ERROR("Cannot set fields on relationship target specs: " + "<%s>:%s = %s", id.GetFullSpecPath().GetText(), + fieldName.GetText(), TfStringify(value).c_str()); + return; + } _hashData ? _SetHelper(*_hashData, id, _hashLastSet, fieldName, value) : _SetHelper(_flatData, id, _flatLastSet, fieldName, value); @@ -563,10 +614,16 @@ class Usd_CrateDataImpl vector fields; vector fieldSets; _crateFile->RemoveStructuralData(specs, fields, fieldSets); - - // Allocate all the spec data structures in the hashtable first, so we - // can populate fields in parallel without locking. - vector<_FlatSpecData *> specDataPtrs; + + // Remove any target specs, we do not store target specs in Usd, but old + // files could contain them. + specs.erase( + remove_if( + specs.begin(), specs.end(), + [this](CrateFile::Spec const &spec) { + return _crateFile->GetPath(spec.pathIndex).IsTargetPath(); + }), + specs.end()); // Sort by path fast-less-than, need same order that _Table will // store. @@ -591,6 +648,7 @@ class Usd_CrateDataImpl result_type operator()(CrateFile::Spec const &spec) const { result_type r; r.first = crateFile->GetPath(spec.pathIndex); + TF_AXIOM(!r.first.IsTargetPath()); return r; } CrateFile *crateFile; @@ -606,6 +664,10 @@ class Usd_CrateDataImpl _flatData); } + // Allocate all the spec data structures in the hashtable first, so we + // can populate fields in parallel without locking. + vector<_FlatSpecData *> specDataPtrs; + // Create all the specData entries and store pointers to them. dispatcher.Run([this, &specs, &specDataPtrs]() { // XXX Won't need first two tags when bug #132031 is addressed diff --git a/pxr/usd/lib/usd/crateFile.cpp b/pxr/usd/lib/usd/crateFile.cpp index 6bd8e13132..9743b123f6 100644 --- a/pxr/usd/lib/usd/crateFile.cpp +++ b/pxr/usd/lib/usd/crateFile.cpp @@ -1587,6 +1587,8 @@ CrateFile::_ReadTokens(Reader reader) p += strlen(p) + 1; } wd.Wait(); + + WorkSwapDestroyAsync(chars); } template diff --git a/pxr/usd/lib/usd/crateFile.h b/pxr/usd/lib/usd/crateFile.h index 9cac1b3ffb..b8d46f72cb 100644 --- a/pxr/usd/lib/usd/crateFile.h +++ b/pxr/usd/lib/usd/crateFile.h @@ -63,6 +63,9 @@ using std::unordered_map; using std::tuple; using std::vector; +// Forward declaration required here for certain MSVC versions. +struct _PathItemHeader; + // Tag indicating trivially copyable types, hack since gcc doesn't yet implement // is_trivially_copyable correctly. struct _BitwiseReadWrite {}; @@ -504,7 +507,7 @@ class CrateFile static _BootStrap _ReadBootStrap(ByteStream src, int64_t fileSize); template - _TableOfContents _ReadTOC(Reader src, struct _BootStrap const &b) const; + _TableOfContents _ReadTOC(Reader src, _BootStrap const &b) const; template void _ReadFieldSets(Reader src); template void _ReadFields(Reader src); @@ -515,7 +518,7 @@ class CrateFile template void _ReadPathsRecursively( Reader src, const SdfPath &parentPath, - const struct _PathItemHeader &h, + const _PathItemHeader &h, WorkArenaDispatcher &dispatcher); void _ReadRawBytes(int64_t start, int64_t size, char *buf) const; diff --git a/pxr/usd/lib/usd/prim.cpp b/pxr/usd/lib/usd/prim.cpp index 64b64f9241..dd5741ebc1 100644 --- a/pxr/usd/lib/usd/prim.cpp +++ b/pxr/usd/lib/usd/prim.cpp @@ -481,7 +481,7 @@ UsdPrim::HasAuthoredReferences() const bool UsdPrim::HasPayload() const { - return GetPrimIndex().HasPayload(); + return _Prim()->HasPayload(); } bool diff --git a/pxr/usd/lib/usd/primData.cpp b/pxr/usd/lib/usd/primData.cpp index d4e4798303..1cfe04bb1d 100644 --- a/pxr/usd/lib/usd/primData.cpp +++ b/pxr/usd/lib/usd/primData.cpp @@ -105,6 +105,10 @@ void Usd_PrimData::_ComposeAndCacheFlags(Usd_PrimDataConstPtr parent, bool isMasterPrim) { + // We do not have to clear _flags here since in the pseudo root or instance + // master case the values never change, and in the ordinary prim case we set + // every flag. + // Special-case the root (the only prim which has no parent) and // instancing masters. if (ARCH_UNLIKELY(not parent or isMasterPrim)) { @@ -112,10 +116,7 @@ Usd_PrimData::_ComposeAndCacheFlags(Usd_PrimDataConstPtr parent, _flags[Usd_PrimLoadedFlag] = true; _flags[Usd_PrimModelFlag] = true; _flags[Usd_PrimGroupFlag] = true; - _flags[Usd_PrimAbstractFlag] = false; _flags[Usd_PrimDefinedFlag] = true; - _flags[Usd_PrimClipsFlag] = false; - _flags[Usd_PrimInstanceFlag] = false; _flags[Usd_PrimMasterFlag] = isMasterPrim; } else { @@ -125,10 +126,14 @@ Usd_PrimData::_ComposeAndCacheFlags(Usd_PrimDataConstPtr parent, self.GetMetadata(SdfFieldKeys->Active, &active); _flags[Usd_PrimActiveFlag] = active; + // Cache whether or not this prim has a payload. + bool hasPayload = _primIndex->HasPayload(); + _flags[Usd_PrimHasPayloadFlag] = hasPayload; + // An active prim is loaded if it's loadable and in the load set, or // it's not loadable and its parent is loaded. - _flags[Usd_PrimLoadedFlag] = active and - (self.HasPayload() ? + _flags[Usd_PrimLoadedFlag] = active && + (hasPayload ? _stage->_GetPcpCache()->IsPayloadIncluded(_primIndex->GetPath()) : parent->IsLoaded()); @@ -136,20 +141,19 @@ Usd_PrimData::_ComposeAndCacheFlags(Usd_PrimDataConstPtr parent, // children (groups or otherwise). So if our parent is not a Model // Group, then this prim cannot be a model (or a model group). // Otherwise we look up the kind metadata and consult the kind registry. - _flags[Usd_PrimGroupFlag] = _flags[Usd_PrimModelFlag] = false; + bool isGroup = false, isModel = false; if (parent->IsGroup()) { static TfToken kindToken("kind"); TfToken kind; self.GetMetadata(kindToken, &kind); - // Use the kind registry to determine model/groupness. if (not kind.IsEmpty()) { - _flags[Usd_PrimGroupFlag] = - KindRegistry::IsA(kind, KindTokens->group); - _flags[Usd_PrimModelFlag] = _flags[Usd_PrimGroupFlag] or - KindRegistry::IsA(kind, KindTokens->model); + isGroup = KindRegistry::IsA(kind, KindTokens->group); + isModel = isGroup or KindRegistry::IsA(kind, KindTokens->model); } } + _flags[Usd_PrimGroupFlag] = isGroup; + _flags[Usd_PrimModelFlag] = isModel; // Get specifier. SdfSpecifier specifier = GetSpecifier(); @@ -158,12 +162,12 @@ Usd_PrimData::_ComposeAndCacheFlags(Usd_PrimDataConstPtr parent, _flags[Usd_PrimAbstractFlag] = parent->IsAbstract() or specifier == SdfSpecifierClass; - // This prim is defined if its parent is defined and its specifier is - // defining. - const bool specifierIsDefining = SdfIsDefiningSpecifier(specifier); - _flags[Usd_PrimDefinedFlag] = - parent->IsDefined() and specifierIsDefining; - _flags[Usd_PrimHasDefiningSpecifierFlag] = specifierIsDefining; + // Cache whether or not this prim has an authored defining specifier. + const bool isDefiningSpec = SdfIsDefiningSpecifier(specifier); + _flags[Usd_PrimHasDefiningSpecifierFlag] = isDefiningSpec; + + // This prim is defined if its parent is and its specifier is defining. + _flags[Usd_PrimDefinedFlag] = isDefiningSpec && parent->IsDefined(); // The presence of clips that may affect attributes on this prim // is computed and set in UsdStage. Default to false. diff --git a/pxr/usd/lib/usd/primData.h b/pxr/usd/lib/usd/primData.h index 19a5dfcd17..985f03e511 100644 --- a/pxr/usd/lib/usd/primData.h +++ b/pxr/usd/lib/usd/primData.h @@ -120,6 +120,9 @@ class Usd_PrimData return _flags[Usd_PrimHasDefiningSpecifierFlag]; } + /// Return true if this prim has one or more payload composition arcs. + bool HasPayload() const { return _flags[Usd_PrimHasPayloadFlag]; } + /// Return true if this prim is an instance of a shared master prim, /// false otherwise. bool IsInstance() const { return _flags[Usd_PrimInstanceFlag]; } @@ -299,10 +302,10 @@ class Usd_PrimData mutable std::atomic_int _refCount; friend void intrusive_ptr_add_ref(const Usd_PrimData *prim) { - ++prim->_refCount; + prim->_refCount.fetch_add(1, std::memory_order_relaxed); } friend void intrusive_ptr_release(const Usd_PrimData *prim) { - if (--prim->_refCount == 0) + if (prim->_refCount.fetch_sub(1, std::memory_order_release) == 1) delete prim; } diff --git a/pxr/usd/lib/usd/primFlags.h b/pxr/usd/lib/usd/primFlags.h index 38a7c28a24..b182330d9f 100644 --- a/pxr/usd/lib/usd/primFlags.h +++ b/pxr/usd/lib/usd/primFlags.h @@ -83,6 +83,7 @@ // Enum for cached flags on prims. enum Usd_PrimFlags { + // Flags for use with predicates. Usd_PrimActiveFlag, Usd_PrimLoadedFlag, Usd_PrimModelFlag, @@ -90,9 +91,12 @@ enum Usd_PrimFlags { Usd_PrimAbstractFlag, Usd_PrimDefinedFlag, Usd_PrimHasDefiningSpecifierFlag, + Usd_PrimInstanceFlag, + + // Flags for internal use. + Usd_PrimHasPayloadFlag, Usd_PrimClipsFlag, Usd_PrimDeadFlag, - Usd_PrimInstanceFlag, Usd_PrimMasterFlag, Usd_PrimNumFlags }; diff --git a/pxr/usd/lib/usd/stage.cpp b/pxr/usd/lib/usd/stage.cpp index feb151cff8..ae4a1fe6d9 100644 --- a/pxr/usd/lib/usd/stage.cpp +++ b/pxr/usd/lib/usd/stage.cpp @@ -346,7 +346,8 @@ _CreateAnonymousSessionLayer(const SdfLayerHandle &rootLayer) UsdStage::UsdStage(const SdfLayerRefPtr& rootLayer, const SdfLayerRefPtr& sessionLayer, - const ArResolverContext& pathResolverContext) + const ArResolverContext& pathResolverContext, + InitialLoadSet load) : _pseudoRoot(0) , _rootLayer(rootLayer) , _sessionLayer(sessionLayer) @@ -359,6 +360,7 @@ UsdStage::UsdStage(const SdfLayerRefPtr& rootLayer, , _instanceCache(new Usd_InstanceCache) , _interpolationType(UsdInterpolationTypeLinear) , _lastChangeSerialNumber(0) + , _initialLoadSet(load) , _isClosingStage(false) { if (not TF_VERIFY(_rootLayer)) @@ -503,7 +505,7 @@ UsdStage::_InstantiateStage(const SdfLayerRefPtr &rootLayer, TfDebug::IsEnabled(USD_STAGE_INSTANTIATION_TIME); if (usdInstantiationTimeDebugCodeActive) { - stopwatch = TfStopwatch(); + stopwatch = TfStopwatch(); stopwatch->Start(); } @@ -511,27 +513,20 @@ UsdStage::_InstantiateStage(const SdfLayerRefPtr &rootLayer, return TfNullPtr; UsdStageRefPtr stage = TfCreateRefPtr( - new UsdStage(rootLayer, sessionLayer, pathResolverContext)); + new UsdStage(rootLayer, sessionLayer, pathResolverContext, load)); ArResolverScopedCache resolverCache; - // Minimally populate the stage, do not request payloads. + // Populate the stage, request payloads according to InitialLoadSet load. stage->_ComposePrimIndexesInParallel( - SdfPathVector(1, SdfPath::AbsoluteRootPath()), "Instantiating stage"); + SdfPathVector(1, SdfPath::AbsoluteRootPath()), + load == LoadAll ? + _IncludeAllDiscoveredPayloads : _IncludeNoDiscoveredPayloads, + "Instantiating stage"); stage->_pseudoRoot = stage->_InstantiatePrim(SdfPath::AbsoluteRootPath()); stage->_ComposeSubtreeInParallel(stage->_pseudoRoot); stage->_RegisterPerLayerNotices(); - // Include all payloads, if desired. - if (load == LoadAll) { - // we will ignore the aggregation of loads/unloads - // because we won't be using them to send a notification - SdfPathSet include, exclude; - - include.insert(SdfPath::AbsoluteRootPath()); - stage->_LoadAndUnload(include, exclude, NULL, NULL); - } - // Publish this stage into all current writable caches. BOOST_FOREACH(UsdStageCache *cache, UsdStageCacheContext::_GetWritableCaches()) { @@ -2912,13 +2907,11 @@ UsdStage::_HandleLayersDidChange( otherChangedPaths.clear(); } - SdfPathVector otherChangedPathsVec(otherChangedPaths.begin(), - otherChangedPaths.end()); - - otherChangedPathsVec.erase( - remove_if(otherChangedPathsVec.begin(), otherChangedPathsVec.end(), - bind(&UsdStage::_IsObjectElidedFromStage, this, _1)), - otherChangedPathsVec.end()); + SdfPathVector otherChangedPathsVec; + otherChangedPathsVec.reserve(otherChangedPaths.size()); + remove_copy_if(otherChangedPaths.begin(), otherChangedPaths.end(), + back_inserter(otherChangedPathsVec), + bind(&UsdStage::_IsObjectElidedFromStage, this, _1)); // Now we want to remove all elements of otherChangedPathsVec that are // prefixed by elements in pathsToRecompose. @@ -3053,7 +3046,8 @@ void UsdStage::_Recompose(const PcpChanges &changes, Usd_InstanceChanges changes; _ComposePrimIndexesInParallel( - primPathsToRecompose, "Recomposing stage", &changes); + primPathsToRecompose, _IncludeNewPayloadsIfAncestorWasIncluded, + "Recomposing stage", &changes); // Determine what instance master prims on this stage need to // be recomposed due to instance prim index changes. @@ -3238,9 +3232,68 @@ UsdStage::_ComputeSubtreesToRecompose( } } +struct UsdStage::_IncludeNewlyDiscoveredPayloadsPredicate +{ + explicit _IncludeNewlyDiscoveredPayloadsPredicate(UsdStage const *stage) + : _stage(stage) {} + + bool operator()(SdfPath const &path) const { + // We want to include newly discovered payloads on existing prims or on + // new prims if their nearest loadable ancestor was loaded, or if there + // is no nearest loadable ancestor and the stage was initially populated + // with LoadAll. + + // First, check to see if this payload is new to us. This is safe to do + // concurrently without a lock since these are only ever reads. + + // The path we're given is a prim index path. Due to instancing, the + // path to the corresponding prim on the stage may differ (it may be a + // generated master path). + SdfPath stagePath = _stage->_GetPrimPathUsingPrimIndexAtPath(path); + if (stagePath.IsEmpty()) + stagePath = path; + + UsdPrim prim = _stage->GetPrimAtPath(stagePath); + bool isNewPayload = !prim or !prim.HasPayload(); + + if (not isNewPayload) + return false; + + // XXX: This does not quite work correctly with instancing. What we + // need to do is once we hit a master, continue searching ancestors of + // all instances that use it. If we find *any* nearest ancestor that's + // loadable, we should return true. + + // This is a new payload -- find the nearest ancestor with a payload. + // First walk up by path until we find an existing prim. + if (prim) { + prim = prim.GetParent(); + } + else { + for (SdfPath curPath = stagePath.GetParentPath(); !prim; + curPath = curPath.GetParentPath()) { + prim = _stage->GetPrimAtPath(curPath); + } + } + + UsdPrim root = _stage->GetPseudoRoot(); + for (; !prim.HasPayload() && prim != root; prim = prim.GetParent()) { + // continue + } + + // If we hit the root, then consult the initial population state. + // Otherwise load the payload if the ancestor is loaded. + return prim != root ? prim.IsLoaded() : + _stage->_initialLoadSet == LoadAll; + } + + UsdStage const *_stage; +}; + void UsdStage::_ComposePrimIndexesInParallel( const std::vector& primIndexPaths, + _IncludePayloadsRule includeRule, const std::string& context, Usd_InstanceChanges* instanceChanges) { @@ -3250,10 +3303,26 @@ UsdStage::_ComposePrimIndexesInParallel( // Ask Pcp to compute all the prim indexes in parallel, stopping at // prim indexes that won't be used by the stage. PcpErrorVector errs; - _cache->ComputePrimIndexesInParallel( - primIndexPaths, - &errs, _NameChildrenPred(_instanceCache.get()), - "Usd", _mallocTagID.c_str()); + + if (includeRule == _IncludeAllDiscoveredPayloads) { + _cache->ComputePrimIndexesInParallel( + primIndexPaths, &errs, _NameChildrenPred(_instanceCache.get()), + [](const SdfPath &) { return true; }, + "Usd", _mallocTagID); + } + else if (includeRule == _IncludeNoDiscoveredPayloads) { + _cache->ComputePrimIndexesInParallel( + primIndexPaths, &errs, _NameChildrenPred(_instanceCache.get()), + [](const SdfPath &) { return false; }, + "Usd", _mallocTagID); + } + else if (includeRule == _IncludeNewPayloadsIfAncestorWasIncluded) { + _cache->ComputePrimIndexesInParallel( + primIndexPaths, &errs, _NameChildrenPred(_instanceCache.get()), + _IncludeNewlyDiscoveredPayloadsPredicate(this), + "Usd", _mallocTagID); + } + if (not errs.empty()) { _ReportPcpErrors(errs, context); } @@ -3273,7 +3342,8 @@ UsdStage::_ComposePrimIndexesInParallel( // instance. Compose the new source prim indexes. if (not changes.changedMasterPrims.empty()) { _ComposePrimIndexesInParallel( - changes.changedMasterPrimIndexes, context, instanceChanges); + changes.changedMasterPrimIndexes, includeRule, + context, instanceChanges); } } diff --git a/pxr/usd/lib/usd/stage.h b/pxr/usd/lib/usd/stage.h index 34e0266822..4d8378bb4e 100644 --- a/pxr/usd/lib/usd/stage.h +++ b/pxr/usd/lib/usd/stage.h @@ -427,7 +427,7 @@ class UsdStage : public TfRefBase, public TfWeakBase { /// unload set were processed first followed by the load set. /// /// This is equivalent to calling UsdStage::Unload for each item in the - /// loadSet followed by UsdStage::Load for each item in the unloadSet, + /// unloadSet followed by UsdStage::Load for each item in the loadSet, /// however this method is more efficient as all operations are committed /// in a single batch. /// @@ -1106,13 +1106,22 @@ class UsdStage : public TfRefBase, public TfWeakBase { /// @} private: + struct _IncludeNewlyDiscoveredPayloadsPredicate; + + enum _IncludePayloadsRule { + _IncludeAllDiscoveredPayloads, + _IncludeNoDiscoveredPayloads, + _IncludeNewPayloadsIfAncestorWasIncluded + }; + // --------------------------------------------------------------------- // // Stage Construction & Initialization // --------------------------------------------------------------------- // UsdStage(const SdfLayerRefPtr& rootLayer, const SdfLayerRefPtr& sessionLayer, - const ArResolverContext& pathResolverContext); + const ArResolverContext& pathResolverContext, + InitialLoadSet load); // Common ref ptr initialization, called by public, static constructors. // @@ -1239,6 +1248,7 @@ class UsdStage : public TfRefBase, public TfWeakBase { // during composition. void _ComposePrimIndexesInParallel( const std::vector& primIndexPaths, + _IncludePayloadsRule includeRule, const std::string& context, Usd_InstanceChanges* instanceChanges = NULL); @@ -1651,6 +1661,9 @@ class UsdStage : public TfRefBase, public TfWeakBase { // for this stage - from all access points - to this tag. std::string _mallocTagID; + // The state used when instantiating the stage. + const InitialLoadSet _initialLoadSet; + bool _isClosingStage; friend class UsdAttribute; diff --git a/pxr/usd/lib/usd/variantSets.cpp b/pxr/usd/lib/usd/variantSets.cpp index 1da05a1868..d583609933 100644 --- a/pxr/usd/lib/usd/variantSets.cpp +++ b/pxr/usd/lib/usd/variantSets.cpp @@ -89,9 +89,19 @@ UsdVariantSet::HasAuthoredVariant(const std::string& variantName) const string UsdVariantSet::GetVariantSelection() const { - string result; - (void)HasAuthoredVariantSelection(&result); - return result; + // Scan the composed prim for variant arcs for this variant set and + // return the first selection found. This ensures that we reflect + // whatever composition process selected the variant, such as fallbacks. + TF_FOR_ALL(i, _prim.GetPrimIndex().GetNodeRange()) { + if (i->GetArcType() == PcpArcTypeVariant) { + std::pair vsel = + i->GetSite().path.GetVariantSelection(); + if (vsel.first == _variantSetName) { + return vsel.second; + } + } + } + return std::string(); } bool diff --git a/pxr/usd/lib/usdGeom/bboxCache.cpp b/pxr/usd/lib/usdGeom/bboxCache.cpp index fc5a390cc3..68cc9a0c59 100644 --- a/pxr/usd/lib/usdGeom/bboxCache.cpp +++ b/pxr/usd/lib/usdGeom/bboxCache.cpp @@ -36,6 +36,7 @@ #include "pxr/usd/usd/treeIterator.h" #include "pxr/base/tracelite/trace.h" +#include "pxr/base/tf/pyLock.h" #include "pxr/base/tf/token.h" #include @@ -773,6 +774,11 @@ UsdGeomBBoxCache::_Resolve( TRACE_FUNCTION(); // NOTE: Bounds are cached in local space, but computed in world space. + // Drop the GIL here if we have it before we spawn parallel tasks, since + // resolving properties on prims in worker threads may invoke plugin code + // that needs the GIL. + TF_PY_ALLOW_THREADS_IN_SCOPE(); + // If the bound is in the cache, return it. std::vector masterPrims; _Entry* entry = _FindOrCreateEntriesForPrim(prim, &masterPrims); diff --git a/pxr/usd/lib/usdGeom/metrics.h b/pxr/usd/lib/usdGeom/metrics.h index 9d540fef68..6a0eed3ba8 100644 --- a/pxr/usd/lib/usdGeom/metrics.h +++ b/pxr/usd/lib/usdGeom/metrics.h @@ -28,7 +28,7 @@ #include "pxr/base/tf/token.h" #include "pxr/usd/usd/common.h" -/// \file usd/metrics.h +/// \file usdGeom/metrics.h /// /// Schema and utilities for encoding various spatial and geometric metrics of /// a UsdStage and its contents. diff --git a/pxr/usd/lib/usdGeom/primvar.cpp b/pxr/usd/lib/usdGeom/primvar.cpp index f1efd914d8..1fef467f4f 100644 --- a/pxr/usd/lib/usdGeom/primvar.cpp +++ b/pxr/usd/lib/usdGeom/primvar.cpp @@ -219,6 +219,20 @@ UsdGeomPrimvar::SetIndices(const VtIntArray &indices, } +void +UsdGeomPrimvar::BlockIndices() const +{ + // Check if the typeName is array valued here and issue a warning + // if it's not. + SdfValueTypeName typeName = GetTypeName(); + if (not typeName.IsArray()) { + TF_CODING_ERROR("Setting indices on non-array valued primvar of type " + "'%s'.", typeName.GetAsToken().GetText()); + return; + } + _GetIndicesAttr(/*create*/ true).Block(); +} + bool UsdGeomPrimvar::GetIndices(VtIntArray *indices, UsdTimeCode time) const @@ -233,7 +247,9 @@ UsdGeomPrimvar::GetIndices(VtIntArray *indices, bool UsdGeomPrimvar::IsIndexed() const { - return _GetIndicesAttr(/*create*/ false); + // XXX update this to api that can directly see if an attribute is blocked. + VtIntArray dummy; + return _GetIndicesAttr(/*create*/ false).Get(&dummy); } bool diff --git a/pxr/usd/lib/usdGeom/primvar.h b/pxr/usd/lib/usdGeom/primvar.h index 114c29626c..33c1f19e55 100644 --- a/pxr/usd/lib/usdGeom/primvar.h +++ b/pxr/usd/lib/usdGeom/primvar.h @@ -114,6 +114,31 @@ /// ... /// \endcode /// +/// \subsection Usd_Handling_Indexed_Primvars Proper Client Handling of "Indexed" Primvars +/// +/// As discussed in greater detail in +/// \ref UsdGeomPrimvar_Indexed_primvars "Indexed Primvars", primvars can +/// optionally contain a (possibly time-varying) indexing attribute that +/// establishes a sharing topology for elements of the primvar. Consumers +/// can always chose to ignore the possibility of indexed data by exclusively +/// using the ComputeFlattened() API. If a client wishes to preserve indexing +/// in their processing of a primvar, we suggest a pattern like the following, +/// which accounts for the fact that a stronger layer can +/// \ref UsdAttribute::Block() "block" a primvar's indexing from a weaker +/// layer, via UsdGeomPrimvar::BlockIndices(): +/// \code +/// VtValue values; +/// VtIntArray indices; +/// +/// if (primvar.Get(&values, timeCode)){ +/// if (primvar.GetIndices(&indices, timeCode)){ +/// // primvar is indexed: validate/process values and indices together +/// } +/// else { +/// // primvar is not indexed: validate/process values as flat array +/// } +/// } +/// \endcode /// /// \subsection Usd_Primvar_As_Attribute UsdGeomPrimvar and UsdAttribute API /// @@ -347,7 +372,10 @@ class UsdGeomPrimvar /// \sa UsdAttribute::GetTypeName() SdfValueTypeName GetTypeName() const { return _attr.GetTypeName(); } - /// Get the attribute value of the Primvar at \p time + /// Get the attribute value of the Primvar at \p time . + /// + /// \sa Usd_Handling_Indexed_Primvars for proper handling of + /// \ref Usd_Handling_Indexed_Primvars "indexed primvars" template bool Get(T* value, UsdTimeCode time = UsdTimeCode::Default()) const { return _attr.Get(value, time); @@ -382,6 +410,7 @@ class UsdGeomPrimvar /// the unique elements. The final value of the primvar is computed using /// the indices array and the attribute value array. /// + /// See also \ref Usd_Handling_Indexed_Primvars /// Sets the indices value of the indexed primvar at \p time. /// @@ -401,6 +430,12 @@ class UsdGeomPrimvar bool GetIndices(VtIntArray *indices, UsdTimeCode time = UsdTimeCode::Default()) const; + /// Block the indices that were previously set. This effectively makes an + /// indexed primvar no longer indexed. This is useful when overriding an + /// existing primvar. + USDGEOM_API + void BlockIndices() const; + /// Returns true if the primvar is indexed, i.e., if it has an associated /// "indices" attribute. USDGEOM_API diff --git a/pxr/usd/lib/usdGeom/wrapPrimvar.cpp b/pxr/usd/lib/usdGeom/wrapPrimvar.cpp index 77bf4155b7..c7d92f3b57 100644 --- a/pxr/usd/lib/usdGeom/wrapPrimvar.cpp +++ b/pxr/usd/lib/usdGeom/wrapPrimvar.cpp @@ -116,6 +116,7 @@ void wrapUsdGeomPrimvar() .def("SetIndices", &Primvar::SetIndices, (arg("indices"), arg("time")=UsdTimeCode::Default())) + .def("BlockIndices", &Primvar::BlockIndices) .def("GetIndices", _GetIndices, (arg("time")=UsdTimeCode::Default())) .def("IsIndexed", &Primvar::IsIndexed) diff --git a/pxr/usd/lib/usdUI/overview.dox b/pxr/usd/lib/usdUI/overview.dox new file mode 100644 index 0000000000..70b9675411 --- /dev/null +++ b/pxr/usd/lib/usdUI/overview.dox @@ -0,0 +1,22 @@ +/*! +\page usdUI_page_front UsdUI: USD UI Schemas +\if ( PIXAR_MFB_BUILD ) +\mainpage UsdUI: USD UI Schemas +\publicLib +\endif + +\section usdUI_overview Overview + +This module provides schemas for encoding information on USD prims +for client graphical user interface tools to use in deciding how to +organize and present the prims in GUI layouts. This information does +\em not guide the 3D rendering of a data contained in ascene, rather it's +about how to visualize the nodes in the graph that comprises a UsdStage. + +The primary classes are: + +\li UsdUINodeGraphNodeAPI - encodes layout information for prims that +participate in an interconnected (via relationships) graph, as would +prims in a shading network. + +*/ diff --git a/pxr/usd/plugin/usdAbc/wrapAlembicTest.cpp b/pxr/usd/plugin/usdAbc/wrapAlembicTest.cpp index 1a60b5513f..a84abbf386 100644 --- a/pxr/usd/plugin/usdAbc/wrapAlembicTest.cpp +++ b/pxr/usd/plugin/usdAbc/wrapAlembicTest.cpp @@ -21,10 +21,10 @@ // KIND, either express or implied. See the Apache License for the specific // language governing permissions and limitations under the Apache License. // -#include "pxr/usd/usdAbc/alembicTest.h" - #include +#include "pxr/usd/usdAbc/alembicTest.h" + using namespace boost::python; void wrapUsdAbcAlembicTest() diff --git a/pxr/usdImaging/bin/usdview/CMakeLists.txt b/pxr/usdImaging/bin/usdview/CMakeLists.txt index 369d733395..195a208e99 100644 --- a/pxr/usdImaging/bin/usdview/CMakeLists.txt +++ b/pxr/usdImaging/bin/usdview/CMakeLists.txt @@ -1,3 +1,8 @@ +if (NOT TARGET usdviewq) + message(WARNING "Not building usdview because of missing dependency: usdviewq") + return() +endif() + pxr_python_bins( usdview ) diff --git a/pxr/usdImaging/lib/usdImaging/delegate.cpp b/pxr/usdImaging/lib/usdImaging/delegate.cpp index 006af50c39..d60f1df034 100644 --- a/pxr/usdImaging/lib/usdImaging/delegate.cpp +++ b/pxr/usdImaging/lib/usdImaging/delegate.cpp @@ -2932,6 +2932,90 @@ UsdImagingDelegate::GetSurfaceShaderTextures(SdfPath const &shaderId) HdTextureResource::ID UsdImagingDelegate::GetTextureResourceID(SdfPath const &textureId) { + if (textureId == SdfPath()) { + size_t hash = textureId.GetHash(); + // salt with renderindex to prevent hash collision in non-shared imaging + boost::hash_combine(hash, &GetRenderIndex()); + return HdTextureResource::ID(hash); + } + + SdfPath usdPath = GetPathForUsd(textureId); + + UsdObject object = _stage->GetPrimAtPath(usdPath.GetPrimPath()); + if (not object) { + size_t hash = textureId.GetHash(); + // salt with renderindex to prevent hash collision in non-shared imaging + boost::hash_combine(hash, &GetRenderIndex()); + return HdTextureResource::ID(hash); + } + + bool isPtex = false; + SdfAssetPath asset; + + if (usdPath.IsPropertyPath()) { + // Attribute-based texture. + UsdAttribute attr = object.As().GetAttribute( + usdPath.GetNameToken()); + if (not attr) { + size_t hash = textureId.GetHash(); + // salt with renderindex to prevent hash collision in non-shared imaging + boost::hash_combine(hash, &GetRenderIndex()); + return HdTextureResource::ID(hash); + } + if (not attr.Get(&asset, _time)) { + size_t hash = textureId.GetHash(); + // salt with renderindex to prevent hash collision in non-shared imaging + boost::hash_combine(hash, &GetRenderIndex()); + return HdTextureResource::ID(hash); + } + } else { + TfToken id; + UsdShadeShader shader(_stage->GetPrimAtPath(usdPath)); + + if (not shader){ + size_t hash = textureId.GetHash(); + // salt with renderindex to prevent hash collision in non-shared imaging + boost::hash_combine(hash, &GetRenderIndex()); + return HdTextureResource::ID(hash); + } + if (not UsdHydraTexture(shader).GetFilenameAttr().Get(&asset)) { + size_t hash = textureId.GetHash(); + // salt with renderindex to prevent hash collision in non-shared imaging + boost::hash_combine(hash, &GetRenderIndex()); + return HdTextureResource::ID(hash); + } + } + + TfToken filePath = TfToken(asset.GetResolvedPath()); + + // Fallback to the literal path if it couldn't be resolved. + if (filePath.IsEmpty()) + filePath = TfToken(asset.GetAssetPath()); + + isPtex = GlfPtexTexture::IsPtexTexture(filePath); + + if (not TfPathExists(filePath)) { + if (isPtex) { + TF_WARN("Unable to find Texture '%s' with path '%s'. Fallback" + "textures are not supported for ptex", + filePath.GetText(), usdPath.GetText()); + + HdTextureResource::ID hash = + HdTextureResource::ComputeFallbackPtexHash(); + // Don't salt default values + return hash; + } else { + TF_WARN("Unable to find Texture '%s' with path '%s'. A black" + "texture will be substituted in its place.", + filePath.GetText(), usdPath.GetText()); + + HdTextureResource::ID hash = + HdTextureResource::ComputeFallbackUVHash(); + // Don't salt default values + return hash; + } + } + size_t hash = textureId.GetHash(); // salt with renderindex to prevent hash collision in non-shared imaging boost::hash_combine(hash, &GetRenderIndex()); diff --git a/pxr/usdImaging/lib/usdImaging/engine.cpp b/pxr/usdImaging/lib/usdImaging/engine.cpp index 8358ef248f..2c34f41296 100644 --- a/pxr/usdImaging/lib/usdImaging/engine.cpp +++ b/pxr/usdImaging/lib/usdImaging/engine.cpp @@ -644,3 +644,11 @@ UsdImagingEngine::SetRenderGraphPlugin(TfType const &type) { return false; } + +/* virtual */ +VtDictionary +UsdImagingEngine::GetResourceAllocation() const +{ + return VtDictionary(); +} + diff --git a/pxr/usdImaging/lib/usdImaging/engine.h b/pxr/usdImaging/lib/usdImaging/engine.h index b9f42ac528..6a1c31d6de 100644 --- a/pxr/usdImaging/lib/usdImaging/engine.h +++ b/pxr/usdImaging/lib/usdImaging/engine.h @@ -35,6 +35,7 @@ #include "pxr/base/gf/matrix4d.h" #include "pxr/base/gf/vec4d.h" #include "pxr/base/gf/vec4i.h" +#include "pxr/base/vt/dictionary.h" #include #include @@ -317,6 +318,9 @@ class UsdImagingEngine : private boost::noncopyable { USDIMAGING_API virtual bool SetRenderGraphPlugin(TfType const &type); + /// Returns GPU resource allocation info + virtual VtDictionary GetResourceAllocation() const; + protected: // Intentionally putting these under protected so that subclasses can share the usage of draw targets. // Once refEngine goes away and we only have hdEngine, it may be best to move this to private diff --git a/pxr/usdImaging/lib/usdImaging/gl.cpp b/pxr/usdImaging/lib/usdImaging/gl.cpp index 9befcd1ced..e5f7b0f189 100644 --- a/pxr/usdImaging/lib/usdImaging/gl.cpp +++ b/pxr/usdImaging/lib/usdImaging/gl.cpp @@ -33,6 +33,7 @@ #include "pxr/base/tf/diagnostic.h" #include "pxr/imaging/glf/glContext.h" +#include "pxr/imaging/glf/textureRegistry.h" #include @@ -313,3 +314,26 @@ UsdImagingGL::TestIntersectionBatch( worldToLocalSpace, paths, params, pickResolution, pathTranslator, outHit); } + +/* virtual */ +VtDictionary +UsdImagingGL::GetResourceAllocation() const +{ + VtDictionary dict; + dict = _engine->GetResourceAllocation(); + + // append texture usage + size_t texMem = 0; + for (auto const &texInfo : + GlfTextureRegistry::GetInstance().GetTextureInfos()) { + VtDictionary::const_iterator it = texInfo.find("memoryUsed"); + if (it != texInfo.end()) { + VtValue mem = it->second; + if (mem.IsHolding()) { + texMem += mem.Get(); + } + } + } + dict["textureMemoryUsed"] = texMem; + return dict; +} diff --git a/pxr/usdImaging/lib/usdImaging/gl.h b/pxr/usdImaging/lib/usdImaging/gl.h index 1a7c8bfcca..3de871ee94 100644 --- a/pxr/usdImaging/lib/usdImaging/gl.h +++ b/pxr/usdImaging/lib/usdImaging/gl.h @@ -190,6 +190,8 @@ class UsdImagingGL : public UsdImagingEngine { std::function< SdfPath(const SdfPath&) > pathTranslator, HitBatch *outHit); + virtual VtDictionary GetResourceAllocation() const; + private: UsdImagingEngineSharedPtr _engine; }; diff --git a/pxr/usdImaging/lib/usdImaging/hdEngine.cpp b/pxr/usdImaging/lib/usdImaging/hdEngine.cpp index e46ece46a6..6204853778 100644 --- a/pxr/usdImaging/lib/usdImaging/hdEngine.cpp +++ b/pxr/usdImaging/lib/usdImaging/hdEngine.cpp @@ -30,6 +30,7 @@ #include "pxr/imaging/hd/version.h" #include "pxr/imaging/hd/tokens.h" #include "pxr/imaging/hd/renderContextCaps.h" +#include "pxr/imaging/hd/resourceRegistry.h" #include "pxr/imaging/hd/debugCodes.h" #include "pxr/imaging/hdx/intersector.h" @@ -765,3 +766,10 @@ UsdImagingHdEngine::SetRenderGraphPlugin(TfType const &type) return true; } + +/* virtual */ +VtDictionary +UsdImagingHdEngine::GetResourceAllocation() const +{ + return HdResourceRegistry::GetInstance().GetResourceAllocation(); +} diff --git a/pxr/usdImaging/lib/usdImaging/hdEngine.h b/pxr/usdImaging/lib/usdImaging/hdEngine.h index 59cbb280c6..fc3a5a2461 100644 --- a/pxr/usdImaging/lib/usdImaging/hdEngine.h +++ b/pxr/usdImaging/lib/usdImaging/hdEngine.h @@ -158,6 +158,8 @@ class UsdImagingHdEngine : public UsdImagingEngine std::function< SdfPath(const SdfPath&) > pathTranslator, HitBatch *outHit); + virtual VtDictionary GetResourceAllocation() const; + private: // Helper functions for preparing multiple engines for // batched drawing. diff --git a/pxr/usdImaging/lib/usdImaging/wrapGL.cpp b/pxr/usdImaging/lib/usdImaging/wrapGL.cpp index bc5a42155d..012e83f4ad 100644 --- a/pxr/usdImaging/lib/usdImaging/wrapGL.cpp +++ b/pxr/usdImaging/lib/usdImaging/wrapGL.cpp @@ -104,6 +104,7 @@ void wrapGL() .def("GetRenderGraphPlugins", &UsdImagingGL::GetRenderGraphPlugins, return_value_policy< TfPySequenceToTuple >()) .def("SetRenderGraphPlugin", &UsdImagingGL::SetRenderGraphPlugin) + .def("GetResourceAllocation", &UsdImagingGL::GetResourceAllocation) ; // Wrap the constants. diff --git a/pxr/usdImaging/lib/usdviewq/CMakeLists.txt b/pxr/usdImaging/lib/usdviewq/CMakeLists.txt index f1c1bb9671..a6cf13b2bd 100644 --- a/pxr/usdImaging/lib/usdviewq/CMakeLists.txt +++ b/pxr/usdImaging/lib/usdviewq/CMakeLists.txt @@ -6,6 +6,11 @@ if (NOT QT4_FOUND) return() endif() +if (NOT PYSIDE_FOUND) + message(WARNING "Not building ${PXR_PACKAGE} because of missing dependency: PySide") + return() +endif() + pxr_shared_library(usdviewq LIBRARIES tf diff --git a/pxr/usdImaging/lib/usdviewq/attributeValueEditor.py b/pxr/usdImaging/lib/usdviewq/attributeValueEditor.py index d76a9c9b7c..ab1df0b847 100644 --- a/pxr/usdImaging/lib/usdviewq/attributeValueEditor.py +++ b/pxr/usdImaging/lib/usdviewq/attributeValueEditor.py @@ -201,4 +201,4 @@ def _revert(self, all=False): def _revertAll(self): self._revert(True) - + diff --git a/pxr/usdImaging/lib/usdviewq/attributeViewContextMenu.py b/pxr/usdImaging/lib/usdviewq/attributeViewContextMenu.py index 575017c024..cf068791a2 100644 --- a/pxr/usdImaging/lib/usdviewq/attributeViewContextMenu.py +++ b/pxr/usdImaging/lib/usdviewq/attributeViewContextMenu.py @@ -21,9 +21,8 @@ # KIND, either express or implied. See the Apache License for the specific # language governing permissions and limitations under the Apache License. # -from PySide import QtGui, QtCore +from PySide import QtGui from usdviewContextMenuItem import UsdviewContextMenuItem -import os # # Specialized context menu for running commands in the attribute viewer. diff --git a/pxr/usdImaging/lib/usdviewq/common.py b/pxr/usdImaging/lib/usdviewq/common.py index d8221094f6..62bb8a4a24 100644 --- a/pxr/usdImaging/lib/usdviewq/common.py +++ b/pxr/usdImaging/lib/usdviewq/common.py @@ -61,7 +61,7 @@ AbstractPrimFont = NormalFont # Keys for destinguishing items in the attribute inspector -class AttributeStatus: +class AttributeStatus(object): DEFAULT, CLAMPED, KEYFRAME, FALLBACK, NOVALUE = range(5) def PrintWarning(title, description): @@ -121,7 +121,7 @@ def GetAttributeColor(attribute, frame, hasValue=None, hasAuthoredValue=None, # Gathers information about a layer used as a subLayer, including its # position in the layerStack hierarchy. -class SubLayerInfo: +class SubLayerInfo(object): def __init__(self, sublayer, offset, containingLayer, prefix): self.layer = sublayer self.offset = offset @@ -183,7 +183,7 @@ def PrettyFormatSize(sz): return "%db" % sz -class Timer: +class Timer(object): """Use as a context object with python's "with" statement, like so: with Timer() as t: doSomeStuff() @@ -204,7 +204,7 @@ def PrintTime(self, action): print "Time to %s: %2.3fs" % (action, self.interval) -class BusyContext: +class BusyContext(object): """When used as a context object with python's "with" statement, will set Qt's busy cursor upon entry and pop it on exit. """ @@ -384,4 +384,3 @@ def DumpMallocTags(stage, contextStr): print "Unable to accumulate memory usage since the Pxr MallocTag system was not initialized" - diff --git a/pxr/usdImaging/lib/usdviewq/customAttributes.py b/pxr/usdImaging/lib/usdviewq/customAttributes.py index 7abe47dc7a..af2d233d63 100644 --- a/pxr/usdImaging/lib/usdviewq/customAttributes.py +++ b/pxr/usdImaging/lib/usdviewq/customAttributes.py @@ -21,10 +21,6 @@ # KIND, either express or implied. See the Apache License for the specific # language governing permissions and limitations under the Apache License. # -from PySide import QtGui, QtCore -from pxr import Tf -from pxr import UsdGeom -from datetime import datetime # # Edit the following to alter the set of custom attributes. @@ -46,18 +42,18 @@ def _GetCustomAttributes(currentNode, bboxCache, xformCache): # class CustomAttribute: def __init__(self, currentNode): - self._currentNode = currentNode + self._currentNode = currentNode def IsVisible(self): - return True + return True # GetName function to match UsdAttribute API def GetName(self): - return "" + return "" # Get function to match UsdAttribute API def Get(self, frame): - return "" + return "" # convenience function to make this look more like a UsdAttribute def GetTypeName(self): @@ -74,16 +70,16 @@ def __init__(self, currentNode, bboxCache): self._bboxCache = bboxCache def GetName(self): - return "World Bounding Box" - + return "World Bounding Box" + def Get(self, frame): - try: + try: bbox = self._bboxCache.ComputeWorldBound(self._currentNode) except RuntimeError, err: - bbox = "Invalid: " + str(err) - - return bbox + bbox = "Invalid: " + str(err) + + return bbox # # Displays the Local to world xform of a node @@ -96,15 +92,15 @@ def __init__(self, currentNode, xformCache): self._xformCache = xformCache def GetName(self): - return "Local to World Xform" - + return "Local to World Xform" + def Get(self, frame): - try: - pwt = self._xformCache.GetLocalToWorldTransform(self._currentNode) - except RuntimeError, err: - pwt = "Invalid: " + str(err) - - return pwt + try: + pwt = self._xformCache.GetLocalToWorldTransform(self._currentNode) + except RuntimeError, err: + pwt = "Invalid: " + str(err) + + return pwt # # Displays a relationship on the node diff --git a/pxr/usdImaging/lib/usdviewq/headerContextMenu.py b/pxr/usdImaging/lib/usdviewq/headerContextMenu.py index 0aaaaaba30..381aa58bca 100644 --- a/pxr/usdImaging/lib/usdviewq/headerContextMenu.py +++ b/pxr/usdImaging/lib/usdviewq/headerContextMenu.py @@ -33,7 +33,7 @@ class HeaderContextMenu(QtGui.QMenu): def __init__(self, parent): QtGui.QMenu.__init__(self, parent) self._menuItems = _GetContextMenuItems(parent) - + for menuItem in self._menuItems: if menuItem.isValid(): # create menu actions diff --git a/pxr/usdImaging/lib/usdviewq/mainWindow.py b/pxr/usdImaging/lib/usdviewq/mainWindow.py index f68743b955..4a2c5c0fe3 100644 --- a/pxr/usdImaging/lib/usdviewq/mainWindow.py +++ b/pxr/usdImaging/lib/usdviewq/mainWindow.py @@ -32,9 +32,7 @@ from customAttributes import _GetCustomAttributes from nodeViewItem import NodeViewItem from pxr import Usd, UsdGeom, UsdUtils, UsdImaging -from pxr import Gf from pxr import Glf -from pxr import Pcp from pxr import Sdf from pxr import Tf from pxr import Plug @@ -44,7 +42,7 @@ from collections import deque from collections import OrderedDict from time import time, sleep -import re, sys, os, uuid, tempfile +import re, sys, os import prettyPrint import watchWindow @@ -52,9 +50,9 @@ import referenceEditor from settings import Settings -from common import FallbackTextColor, ClampedTextColor, KeyframeTextColor,\ - DefaultTextColor, HeaderColor, RedColor, BoldFont, \ - GetAttributeColor, Timer, BusyContext, DumpMallocTags +from common import (FallbackTextColor, ClampedTextColor, KeyframeTextColor, + DefaultTextColor, HeaderColor, RedColor, BoldFont, + GetAttributeColor, Timer, BusyContext, DumpMallocTags) # Upper HUD entries (declared in variables for abstraction) PRIM = "Prims" @@ -474,7 +472,7 @@ def __init__(self, parent, parserData): [str(a.text()) for a in self._ui.pickModeActionGroup.actions()]: print "Warning: Unknown pick mode '%s', falling back to '%s'" % ( - pickMode, + self._stageView.pickMode, str(self._ui.pickModeActionGroup.actions()[0].text())) self._ui.pickModeActionGroup.actions()[0].setChecked(True) @@ -1087,11 +1085,6 @@ def _openStage(self, usdFilePath): return None if self._mallocTags != 'none': - if self._mallocTags == 'stageAndImaging': - # we want as little python overhead showing up as possible, - # so pre-import what we'll use in a bit before initializing - from pxr import UsdImaging - from pxr import Tf Tf.MallocTag.Initialize() with Timer() as t: @@ -1270,7 +1263,7 @@ def _configureRenderGraphPlugins(self): action = self._ui.menuRenderGraph.addAction(name) action.setCheckable(True) action.pluginType = pluginType - self._ui.renderGraphActionGroup.addAction(action); + self._ui.renderGraphActionGroup.addAction(action) QtCore.QObject.connect( action, @@ -2838,7 +2831,7 @@ def _currentPathChanged(self): import re newPaths = self._ui.currentPathWidget.text() pathList = re.split(", ?", newPaths) - pathList = filter(lambda path: len(path) != 0, pathList) + pathList = filter(lambda path: len(path) != 0, pathList) itemList = [] for primPath in pathList: @@ -3093,7 +3086,7 @@ def _updateAttributeViewInternal(self): tableWidget.item(attributeCount,0).setSelected(True) tableWidget.setCurrentItem(tableWidget.item(attributeCount, 0)) - attributeCount += 1; + attributeCount += 1 tableWidget.resizeColumnToContents(0) diff --git a/pxr/usdImaging/lib/usdviewq/nodeContextMenu.py b/pxr/usdImaging/lib/usdviewq/nodeContextMenu.py index 25661d782d..b5e5c936c6 100644 --- a/pxr/usdImaging/lib/usdviewq/nodeContextMenu.py +++ b/pxr/usdImaging/lib/usdviewq/nodeContextMenu.py @@ -21,8 +21,8 @@ # KIND, either express or implied. See the Apache License for the specific # language governing permissions and limitations under the Apache License. # -from PySide import QtGui, QtCore -from nodeContextMenuItems import NodeContextMenuItem, _GetContextMenuItems +from PySide import QtGui +from nodeContextMenuItems import _GetContextMenuItems # # Specialized context menu for node selection. diff --git a/pxr/usdImaging/lib/usdviewq/nodeContextMenuItems.py b/pxr/usdImaging/lib/usdviewq/nodeContextMenuItems.py index 664ad5e743..bfb26d49ed 100644 --- a/pxr/usdImaging/lib/usdviewq/nodeContextMenuItems.py +++ b/pxr/usdImaging/lib/usdviewq/nodeContextMenuItems.py @@ -21,11 +21,8 @@ # KIND, either express or implied. See the Apache License for the specific # language governing permissions and limitations under the Apache License. # -from PySide import QtGui, QtCore -from datetime import datetime -from nodeViewItem import NodeViewItem +from PySide import QtGui from usdviewContextMenuItem import UsdviewContextMenuItem -from pxr import Tf import os import sys @@ -94,7 +91,7 @@ class JumpToEnclosingModelItem(NodeContextMenuItem): def IsEnabled(self): from common import GetEnclosingModelPrim - + for p in self._currentNodes: if GetEnclosingModelPrim(p) is not None: return True @@ -102,7 +99,7 @@ def IsEnabled(self): def GetText(self): return "Jump to Enclosing Model" - + def RunCommand(self): self._mainWindow.jumpToEnclosingModelSelectedPrims() @@ -114,16 +111,16 @@ class JumpToBoundLookMenuItem(NodeContextMenuItem): def IsEnabled(self): from common import GetClosestBoundLook - + for p in self._currentNodes: look, bound = GetClosestBoundLook(p) if look is not None: return True - return False + return False def GetText(self): return "Jump to Bound Look" - + def RunCommand(self): self._mainWindow.jumpToBoundLookSelectedPrims() @@ -136,11 +133,11 @@ def IsEnabled(self): for p in self._currentNodes: if p.IsInstance(): return True - return False + return False def GetText(self): return "Jump to Master" - + def RunCommand(self): self._mainWindow.jumpToMasterSelectedPrims() @@ -169,7 +166,7 @@ def RunCommand(self): class ToggleVisibilityMenuItem(NodeContextMenuItem): def __init__(self, mainWindow, item): - NodeContextMenuItem.__init__(self, mainWindow, item) + NodeContextMenuItem.__init__(self, mainWindow, item) from pxr import UsdGeom self._imageable = False self._isVisible = False @@ -238,7 +235,7 @@ def RunCommand(self): class LoadOrUnloadMenuItem(NodeContextMenuItem): def __init__(self, mainWindow, item): - NodeContextMenuItem.__init__(self, mainWindow, item) + NodeContextMenuItem.__init__(self, mainWindow, item) from common import GetPrimsLoadability # Use the descendent-pruned selection set to avoid redundant # traversal of the stage to answer isLoaded... @@ -267,14 +264,14 @@ def GetText(self): if len(self._currentNodes) > 1: return "Copy Prim Paths" return "Copy Prim Path" - + def RunCommand(self): - pathlist = [str(p.GetPath()) for p in self._currentNodes] - pathStrings = '\n'.join(pathlist) + pathlist = [str(p.GetPath()) for p in self._currentNodes] + pathStrings = '\n'.join(pathlist) cb = QtGui.QApplication.clipboard() - cb.setText(pathStrings, QtGui.QClipboard.Selection ) - cb.setText(pathStrings, QtGui.QClipboard.Clipboard ) + cb.setText(pathStrings, QtGui.QClipboard.Selection ) + cb.setText(pathStrings, QtGui.QClipboard.Clipboard ) # # Copies the path of the first-selected prim's enclosing model @@ -283,25 +280,25 @@ def RunCommand(self): class CopyModelPathMenuItem(NodeContextMenuItem): def __init__(self, mainWindow, item): - NodeContextMenuItem.__init__(self, mainWindow, item) + NodeContextMenuItem.__init__(self, mainWindow, item) from common import GetEnclosingModelPrim - + self._modelPrim = GetEnclosingModelPrim(self._currentNodes[0]) if \ len(self._currentNodes) == 1 else None def IsEnabled(self): - return self._modelPrim + return self._modelPrim def GetText(self): name = ( "(%s)" % self._modelPrim.GetName() ) if self._modelPrim else "" return "Copy Enclosing Model %s Path" % name - + def RunCommand(self): modelPath = str(self._modelPrim.GetPath()) cb = QtGui.QApplication.clipboard() - cb.setText(modelPath, QtGui.QClipboard.Selection ) - cb.setText(modelPath, QtGui.QClipboard.Clipboard ) - + cb.setText(modelPath, QtGui.QClipboard.Selection ) + cb.setText(modelPath, QtGui.QClipboard.Clipboard ) + # @@ -315,32 +312,32 @@ def GetText(self): return "Isolate Copy of Prim..." def RunCommand(self): - inFile = self._currentNodes[0].GetScene().GetUsdFile() - - guessOutFile = os.getcwd() + "/" + self._currentNodes[0].GetName() + "_copy.usd" + inFile = self._currentNodes[0].GetScene().GetUsdFile() + + guessOutFile = os.getcwd() + "/" + self._currentNodes[0].GetName() + "_copy.usd" (outFile, _) = QtGui.QFileDialog.getSaveFileName(None, "Specify the Usd file to create", guessOutFile, 'Usd files (*.usd)') if (outFile.rsplit('.')[-1] != 'usd'): outFile += '.usd' - - if inFile == outFile: - sys.stderr.write( "Cannot isolate a copy to the source usd!\n" ) - return - sys.stdout.write( "Writing copy to new file '%s' ... " % outFile ) - sys.stdout.flush() - - os.system( 'usdcopy -inUsd ' + inFile + - ' -outUsd ' + outFile + ' ' + - ' -sourcePath ' + self._currentNodes[0].GetPath() + '; ' + - 'usdview ' + outFile + ' &') - - sys.stdout.write( "Done!\n" ) - + if inFile == outFile: + sys.stderr.write( "Cannot isolate a copy to the source usd!\n" ) + return + + sys.stdout.write( "Writing copy to new file '%s' ... " % outFile ) + sys.stdout.flush() + + os.system( 'usdcopy -inUsd ' + inFile + + ' -outUsd ' + outFile + ' ' + + ' -sourcePath ' + self._currentNodes[0].GetPath() + '; ' + + 'usdview ' + outFile + ' &') + + sys.stdout.write( "Done!\n" ) + def IsEnabled(self): - return len(self._currentNodes) == 1 and self._currentNodes[0].GetActive() + return len(self._currentNodes) == 1 and self._currentNodes[0].GetActive() # @@ -350,8 +347,8 @@ def IsEnabled(self): class IsolateAssetMenuItem(NodeContextMenuItem): def __init__(self, mainWindow, item): - NodeContextMenuItem.__init__(self, mainWindow, item) - + NodeContextMenuItem.__init__(self, mainWindow, item) + self._assetName = None if len(self._currentNodes) == 1: from pxr import Usd @@ -369,14 +366,13 @@ def __init__(self, mainWindow, item): self._filePath = layer.realPath def IsEnabled(self): - return self._assetName + return self._assetName def GetText(self): name = ( " '%s'" % self._assetName ) if self._assetName else "" return "usdview asset%s" % name - + def RunCommand(self): print "Spawning usdview %s" % self._filePath os.system("usdview %s &" % self._filePath) - diff --git a/pxr/usdImaging/lib/usdviewq/nodeViewItem.py b/pxr/usdImaging/lib/usdviewq/nodeViewItem.py index 9b1a686039..c9cc6a657c 100644 --- a/pxr/usdImaging/lib/usdviewq/nodeViewItem.py +++ b/pxr/usdImaging/lib/usdviewq/nodeViewItem.py @@ -176,8 +176,7 @@ def _nameData(self, role): elif self.isInstance: toolTip = 'Instanced ' + toolTip if self.hasArcs: - toolTip = toolTip + \ - "
Has composition arcs" + toolTip = toolTip + "
Has composition arcs" return toolTip else: return None diff --git a/pxr/usdImaging/lib/usdviewq/prettyPrint.py b/pxr/usdImaging/lib/usdviewq/prettyPrint.py index 33946d1635..570f121720 100644 --- a/pxr/usdImaging/lib/usdviewq/prettyPrint.py +++ b/pxr/usdImaging/lib/usdviewq/prettyPrint.py @@ -26,7 +26,6 @@ arrayAttributeView ''' from PySide import QtGui -from pxr import Gf # locale.setlocale(locale.LC_ALL, 'en_US') diff --git a/pxr/usdImaging/lib/usdviewq/pythonInterpreter.py b/pxr/usdImaging/lib/usdviewq/pythonInterpreter.py index db58395881..21f38285b6 100644 --- a/pxr/usdImaging/lib/usdviewq/pythonInterpreter.py +++ b/pxr/usdImaging/lib/usdviewq/pythonInterpreter.py @@ -637,6 +637,7 @@ class View(QtGui.QTextEdit): """ def __init__(self, parent=None): + QtGui.QTextEdit.__init__(self, parent) self.Parent = QtGui.QTextEdit self.Parent.__init__(self, parent) self.promptLength = 0 @@ -726,7 +727,7 @@ def mousePressEvent(self, e): def mouseDoubleClickEvent(self, e): self.Parent.mouseDoubleClickEvent(self, e) app = QtGui.QApplication.instance() - self.tripleClickTimer.start(app.doubleClickInterval(), self); + self.tripleClickTimer.start(app.doubleClickInterval(), self) # make a copy here, otherwise tripleClickPoint will always = globalPos self.tripleClickPoint = QtCore.QPoint(e.globalPos()) diff --git a/pxr/usdImaging/lib/usdviewq/scalarTypes.py b/pxr/usdImaging/lib/usdviewq/scalarTypes.py index 68da6804f0..9494ba22ea 100644 --- a/pxr/usdImaging/lib/usdviewq/scalarTypes.py +++ b/pxr/usdImaging/lib/usdviewq/scalarTypes.py @@ -22,10 +22,10 @@ # language governing permissions and limitations under the Apache License. # def GetScalarTypeFromAttr(attr): - ''' + ''' returns the (scalar, isArray) where isArray is True if it was an array type ''' - # Usd.Attribute and customAttributes.CustomAttribute have a + # Usd.Attribute and customAttributes.CustomAttribute have a # GetTypeName function, while Sdf.AttributeSpec has a typeName attr. if hasattr(attr, 'GetTypeName'): typeName = attr.GetTypeName() @@ -43,7 +43,6 @@ def ToString(v, typeName=None): This string is used in the watch window""" from pxr import Tf, Gf - import pprint if v is None: return 'None' @@ -62,7 +61,7 @@ def ToString(v, typeName=None): # Pretty-print a bounding box if isinstance(v, Gf.BBox3d): - prettyMatrix = ("%s\n%s\n%s\n%s" % (v.matrix[0], v.matrix[1], + prettyMatrix = ("%s\n%s\n%s\n%s" % (v.matrix[0], v.matrix[1], v.matrix[2], v.matrix[3])).replace("(","").replace(")","") result = "Endpts of box diagonal:\n%s\n%s\n\nTransform matrix:\n%s\n" \ % (v.box.GetCorner(0), v.box.GetCorner(7), prettyMatrix) @@ -93,22 +92,23 @@ def ToString(v, typeName=None): # Pretty-print a TfTimeStamp elif isinstance(v, Tf.TimeStamp): from datetime import datetime - dt = datetime.fromtimestamp( v.Get() ) - result = dt.isoformat(' ') + dt = datetime.fromtimestamp( v.Get() ) + result = dt.isoformat(' ') - # pretty print an int + # pretty print an int elif isinstance(v, int): result = "{:,d}".format(v) - # pretty print a float + # pretty print a float elif isinstance(v, float): result = "{:,.6f}".format(v) # print a string as-is elif isinstance(v, str): - result = v + result = v else: + import pprint result = pprint.pformat(v) return result diff --git a/pxr/usdImaging/lib/usdviewq/stageView.py b/pxr/usdImaging/lib/usdviewq/stageView.py index 2345f7cfbc..2f7f9752a4 100644 --- a/pxr/usdImaging/lib/usdviewq/stageView.py +++ b/pxr/usdImaging/lib/usdviewq/stageView.py @@ -25,13 +25,9 @@ Module that provides the StageView class. ''' -import logging -import math -from math import tan, sqrt, atan, degrees -from math import radians as rad +from math import tan, atan, radians as rad import os from time import time -import traceback from PySide import QtGui, QtCore, QtOpenGL @@ -67,8 +63,8 @@ class FreeCamera(QtCore.QObject): # is close to camera maxGoodZResolution = 5e4 - """FreeCamera can be either a Z up or Y up camera, based on 'zUp'""" def __init__(self, isZUp): + """FreeCamera can be either a Z up or Y up camera, based on 'zUp'""" super(FreeCamera, self).__init__() self._camera = Gf.Camera() @@ -304,7 +300,7 @@ def frameSelection(self, selBBox, frameFit): else: halfFov = self.fov*0.5 or 0.5 # don't divide by zero self.dist = ((self._selSize * frameFit * 0.5) - / math.atan(math.radians(halfFov))) + / atan(rad(halfFov))) def setClosestVisibleDistFromPoint(self, point): frustum = self._camera.frustum @@ -1004,11 +1000,11 @@ def _updateBboxGuides(self): # XXX Why aren't these @properties? def setDisplayGuides(self, enabled): self._displayGuides = enabled - self._updateBboxGuides(); + self._updateBboxGuides() def setDisplayRenderingGuides(self, enabled): self._displayRenderingGuides = enabled - self._updateBboxGuides(); + self._updateBboxGuides() def setDisplayCameraOracles(self, enabled): self._displayCameraOracles = enabled @@ -1052,7 +1048,7 @@ def setNodes(self, nodes, frame, resetCam=False, forceComputeBBox=False, if self._bbox.GetRange().IsEmpty(): self._selectionBBox = self._getDefaultBBox() else: - self._selectionBBox = self._bbox; + self._selectionBBox = self._bbox else: self._selectionBBox = self.getSelectionBBox() @@ -1130,6 +1126,7 @@ def setCameraPrim(self, cameraPrim): self._freeCamera = None self._cameraPrim = cameraPrim else: + from common import PrintWarning PrintWarning("Incorrect Prim Type", "Attempted to view the scene using the prim '%s', but " "the prim is not a UsdGeom.Camera." %(cameraPrim.GetName())) @@ -1306,7 +1303,7 @@ def paintGL(self): GL.glEnable(GL.GL_DEPTH_TEST) GL.glDepthFunc(GL.GL_LESS) - GL.glBlendFunc(GL.GL_SRC_ALPHA, GL.GL_ONE_MINUS_SRC_ALPHA); + GL.glBlendFunc(GL.GL_SRC_ALPHA, GL.GL_ONE_MINUS_SRC_ALPHA) GL.glEnable(GL.GL_BLEND) frustum = self.computeGfCamera().frustum @@ -1557,9 +1554,26 @@ def paintGL(self): self.fpsHUDKeys) # GPU stats (TimeElapsed is in nano seconds) if self.showHUD_GPUstats: - toPrint = { "GL prims" : self._glPrimitiveGeneratedQuery.GetResult(), - "GPU time" : "%.2f ms " % (self._glTimeElapsedQuery.GetResult() / 1000000.0) } - self.printDict(-10, self.height()-60, col, toPrint) + allocInfo = self._renderer.GetResourceAllocation() + gpuMemTotal = 0 + texMem = 0 + if "gpuMemoryUsed" in allocInfo: + gpuMemTotal = allocInfo["gpuMemoryUsed"] + if "textureMemoryUsed" in allocInfo: + texMem = allocInfo["textureMemoryUsed"] + gpuMemTotal += texMem + + from collections import OrderedDict + toPrint = OrderedDict() + toPrint["GL prims "] = self._glPrimitiveGeneratedQuery.GetResult() + toPrint["GPU time "] = "%.2f ms " % (self._glTimeElapsedQuery.GetResult() / 1000000.0) + toPrint["GPU mem "] = gpuMemTotal + toPrint[" primvar "] = allocInfo["primVar"] if "primVar" in allocInfo else "N/A" + toPrint[" topology"] = allocInfo["topology"] if "topology" in allocInfo else "N/A" + toPrint[" shader "] = allocInfo["drawingShader"] if "drawingShader" in allocInfo else "N/A" + toPrint[" texture "] = texMem + + self.printDict(-10, self.height()-30-(15*len(toPrint)), col, toPrint, toPrint.keys()) GL.glPopMatrix() @@ -1697,7 +1711,7 @@ def detachAndReClipFromCurrentCamera(self): FreeCamera. Then reset the near/far clipping planes based on distance to closest geometry.""" if not self._freeCamera: - self.switchToFreeCamera(); + self.switchToFreeCamera() else: self.computeAndSetClosestDistance() diff --git a/third_party/katana/lib/usdKatana/readCamera.cpp b/third_party/katana/lib/usdKatana/readCamera.cpp index efa56750c8..02cfa12ba0 100644 --- a/third_party/katana/lib/usdKatana/readCamera.cpp +++ b/third_party/katana/lib/usdKatana/readCamera.cpp @@ -130,6 +130,8 @@ PxrUsdKatanaReadCamera( const std::vector& motionSampleTimes = data.GetMotionSampleTimes(camera.GetFocalLengthAttr()); + const bool isMotionBackward = data.GetUsdInArgs()->IsMotionBackward(); + FnKat::DoubleBuilder fovBuilder(1); TF_FOR_ALL(iter, motionSampleTimes) { @@ -139,7 +141,8 @@ PxrUsdKatanaReadCamera( double fov = camera.GetCamera(time, camerasAreZup ).GetFieldOfView(GfCamera::FOVHorizontal); - fovBuilder.push_back(fov, fabs(relSampleTime)); + fovBuilder.push_back(fov, isMotionBackward ? + PxrUsdKatanaUtils::ReverseTimeSample(relSampleTime) : relSampleTime); if (not isVarying) { diff --git a/third_party/katana/lib/usdKatana/readConstraintTarget.cpp b/third_party/katana/lib/usdKatana/readConstraintTarget.cpp index 4d34bb6d51..aef6aa7345 100644 --- a/third_party/katana/lib/usdKatana/readConstraintTarget.cpp +++ b/third_party/katana/lib/usdKatana/readConstraintTarget.cpp @@ -99,6 +99,8 @@ _BuildMatrixAttr( const std::vector& motionSampleTimes = data.GetMotionSampleTimes(constraintAttr); + const bool isMotionBackward = data.GetUsdInArgs()->IsMotionBackward(); + FnKat::DoubleBuilder matBuilder(16); TF_FOR_ALL(iter, motionSampleTimes) { double relSampleTime = *iter; @@ -110,7 +112,10 @@ _BuildMatrixAttr( // Convert to vector. const double *matArray = mat.GetArray(); - std::vector &matVec = matBuilder.get(fabs(relSampleTime)); + + std::vector &matVec = matBuilder.get(isMotionBackward ? + PxrUsdKatanaUtils::ReverseTimeSample(relSampleTime) : relSampleTime); + matVec.resize(16); for (int i = 0; i < 16; ++i) { matVec[i] = matArray[i]; diff --git a/third_party/katana/lib/usdKatana/readGprim.cpp b/third_party/katana/lib/usdKatana/readGprim.cpp index aab921294a..f6ae944e3c 100644 --- a/third_party/katana/lib/usdKatana/readGprim.cpp +++ b/third_party/katana/lib/usdKatana/readGprim.cpp @@ -67,6 +67,8 @@ PxrUsdKatanaGeomGetPAttr( // Used to compare value sizes to identify varying topology. int arraySize = -1; + const bool isMotionBackward = data.GetUsdInArgs()->IsMotionBackward(); + FnKat::FloatBuilder attrBuilder(/* tupleSize = */ 3); TF_FOR_ALL(iter, motionSampleTimes) { @@ -85,7 +87,9 @@ PxrUsdKatanaGeomGetPAttr( break; } - std::vector &ptVec = attrBuilder.get(fabs(relSampleTime)); + std::vector &ptVec = attrBuilder.get(isMotionBackward ? + PxrUsdKatanaUtils::ReverseTimeSample(relSampleTime) : relSampleTime); + PxrUsdKatanaUtils::ConvertArrayToVector(ptArray, &ptVec); } @@ -257,6 +261,8 @@ PxrUsdKatanaGeomGetNormalAttr( const std::vector& motionSampleTimes = data.GetMotionSampleTimes(normalsAttr); + const bool isMotionBackward = data.GetUsdInArgs()->IsMotionBackward(); + FnKat::FloatBuilder attrBuilder(/* tupleSize = */ 3); TF_FOR_ALL(iter, motionSampleTimes) { @@ -267,7 +273,9 @@ PxrUsdKatanaGeomGetNormalAttr( VtVec3fArray normalsArray; normalsAttr.Get(&normalsArray, time); - std::vector &normalsVec = attrBuilder.get(fabs(relSampleTime)); + std::vector &normalsVec = attrBuilder.get(isMotionBackward ? + PxrUsdKatanaUtils::ReverseTimeSample(relSampleTime) : relSampleTime); + PxrUsdKatanaUtils::ConvertArrayToVector(normalsArray, &normalsVec); } diff --git a/third_party/katana/lib/usdKatana/readNurbsPatch.cpp b/third_party/katana/lib/usdKatana/readNurbsPatch.cpp index 454b703473..1947302cca 100644 --- a/third_party/katana/lib/usdKatana/readNurbsPatch.cpp +++ b/third_party/katana/lib/usdKatana/readNurbsPatch.cpp @@ -106,7 +106,8 @@ static FnKat::FloatAttribute _GetPwAttr( const UsdGeomNurbsPatch &nurbsPatch, double currentTime, - const std::vector& motionSampleTimes) + const std::vector& motionSampleTimes, + const bool isMotionBackward) { UsdAttribute weightsAttr = nurbsPatch.GetPointWeightsAttr(); UsdAttribute pointsAttr = nurbsPatch.GetPointsAttr(); @@ -143,7 +144,9 @@ _GetPwAttr( } // set the points data in katana at the give motion sample time - std::vector &ptVec = pwBuilder.get(fabs(relSampleTime)); + std::vector &ptVec = pwBuilder.get(isMotionBackward ? + PxrUsdKatanaUtils::ReverseTimeSample(relSampleTime) : relSampleTime); + ptVec.resize(ptArray.size() * 4); size_t count = 0; @@ -323,7 +326,8 @@ PxrUsdKatanaReadNurbsPatch( FnKat::GroupBuilder geometryBuilder; - geometryBuilder.set("point.Pw", _GetPwAttr(nurbsPatch, currentTime, motionSampleTimes)); + geometryBuilder.set("point.Pw", _GetPwAttr( + nurbsPatch, currentTime, motionSampleTimes, data.GetUsdInArgs()->IsMotionBackward())); geometryBuilder.set("u", _GetUAttr(nurbsPatch, currentTime)); geometryBuilder.set("v", _GetVAttr(nurbsPatch, currentTime)); geometryBuilder.set("uSize", _GetUSizeAttr(nurbsPatch, currentTime)); diff --git a/third_party/katana/lib/usdKatana/readPoints.cpp b/third_party/katana/lib/usdKatana/readPoints.cpp index b2a1a45b73..6918224db8 100644 --- a/third_party/katana/lib/usdKatana/readPoints.cpp +++ b/third_party/katana/lib/usdKatana/readPoints.cpp @@ -49,6 +49,24 @@ _GetVelocityAttr( return velocitiesBuilder.build(); } +static FnKat::Attribute +_GetNormalsAttr(const UsdGeomPoints& points, double currentTime) +{ + VtVec3fArray normals; + if (not points.GetNormalsAttr().Get(&normals, currentTime)) + { + return FnKat::Attribute(); + } + + // float attribute list with a width of 3 + FnKat::FloatBuilder normalsBuilder(3); + std::vector normalsVec; + PxrUsdKatanaUtils::ConvertArrayToVector(normals, &normalsVec); + normalsBuilder.set(normalsVec); + + return normalsBuilder.build(); +} + static FnKat::Attribute _GetWidthAttr(const UsdGeomPoints& points, double currentTime) { @@ -102,7 +120,7 @@ PxrUsdKatanaReadPoints( } // normals - FnKat::Attribute normalsAttr = PxrUsdKatanaGeomGetNormalAttr(points, data); + FnKat::Attribute normalsAttr = _GetNormalsAttr(points, currentTime); if (normalsAttr.isValid()) { geometryBuilder.set("point.N", normalsAttr); diff --git a/third_party/katana/lib/usdKatana/readXformable.cpp b/third_party/katana/lib/usdKatana/readXformable.cpp index 5161fbf221..ce58f308ee 100644 --- a/third_party/katana/lib/usdKatana/readXformable.cpp +++ b/third_party/katana/lib/usdKatana/readXformable.cpp @@ -25,6 +25,7 @@ #include "usdKatana/readPrim.h" #include "usdKatana/readXformable.h" #include "usdKatana/usdInPrivateData.h" +#include "usdKatana/utils.h" #include "pxr/usd/usdGeom/xform.h" @@ -58,6 +59,8 @@ PxrUsdKatanaReadXformable( FnKat::GroupBuilder gb; + const bool isMotionBackward = data.GetUsdInArgs()->IsMotionBackward(); + // For each xform op, construct a matrix containing the // transformation data for each time sample it has. // @@ -80,7 +83,9 @@ PxrUsdKatanaReadXformable( // Convert to vector. const double *matArray = mat.GetArray(); - std::vector &matVec = matBuilder.get(fabs(relSampleTime)); + std::vector &matVec = matBuilder.get(isMotionBackward ? + PxrUsdKatanaUtils::ReverseTimeSample(relSampleTime) : relSampleTime); + matVec.resize(16); for (int i = 0; i < 16; ++i) { diff --git a/third_party/katana/lib/usdKatana/usdInArgs.cpp b/third_party/katana/lib/usdKatana/usdInArgs.cpp index 89d4eaab5c..0e8010acfd 100644 --- a/third_party/katana/lib/usdKatana/usdInArgs.cpp +++ b/third_party/katana/lib/usdKatana/usdInArgs.cpp @@ -42,7 +42,8 @@ PxrUsdKatanaUsdInArgs::PxrUsdKatanaUsdInArgs( double shutterClose, const std::vector& motionSampleTimes, const StringListMap& extraAttributesOrNamespaces, - bool verbose) : + bool verbose, + const char * errorMessage) : _stage(stage), _rootLocation(rootLocation), _isolatePath(isolatePath), @@ -55,6 +56,13 @@ PxrUsdKatanaUsdInArgs::PxrUsdKatanaUsdInArgs( _extraAttributesOrNamespaces(extraAttributesOrNamespaces), _verbose(verbose) { + _isMotionBackward = _motionSampleTimes.size() > 1 and + _motionSampleTimes.front() > _motionSampleTimes.back(); + + if (errorMessage) + { + _errorMessage = errorMessage; + } } PxrUsdKatanaUsdInArgs::~PxrUsdKatanaUsdInArgs() diff --git a/third_party/katana/lib/usdKatana/usdInArgs.h b/third_party/katana/lib/usdKatana/usdInArgs.h index b5f2b905af..6d0a251fe8 100644 --- a/third_party/katana/lib/usdKatana/usdInArgs.h +++ b/third_party/katana/lib/usdKatana/usdInArgs.h @@ -58,7 +58,8 @@ class PxrUsdKatanaUsdInArgs : public TfRefBase double shutterClose, const std::vector& motionSampleTimes, const StringListMap& extraAttributesOrNamespaces, - bool verbose) { + bool verbose, + const char * errorMessage = 0) { return TfCreateRefPtr(new PxrUsdKatanaUsdInArgs( stage, rootLocation, @@ -70,7 +71,8 @@ class PxrUsdKatanaUsdInArgs : public TfRefBase shutterClose, motionSampleTimes, extraAttributesOrNamespaces, - verbose)); + verbose, + errorMessage)); } // bounds computation is kind of important, so we centralize it here. @@ -120,6 +122,15 @@ class PxrUsdKatanaUsdInArgs : public TfRefBase return _motionSampleTimes; } + /// \brief Return true if motion blur is backward. + /// + /// PxrUsdIn supports both forward and backward motion blur. Motion + /// blur is considered backward if multiple samples are requested + /// and the first specified sample is later than the last sample. + const bool IsMotionBackward() const { + return _isMotionBackward; + } + const StringListMap& GetExtraAttributesOrNamespaces() const { return _extraAttributesOrNamespaces; } @@ -133,6 +144,9 @@ class PxrUsdKatanaUsdInArgs : public TfRefBase return _bboxCaches.local(); } + const std::string & GetErrorMessage() { + return _errorMessage; + } private: USDKATANA_API PxrUsdKatanaUsdInArgs( @@ -146,7 +160,8 @@ class PxrUsdKatanaUsdInArgs : public TfRefBase double shutterClose, const std::vector& motionSampleTimes, const StringListMap& extraAttributesOrNamespaces, - bool verbose); + bool verbose, + const char * errorMessage = 0); USDKATANA_API ~PxrUsdKatanaUsdInArgs(); @@ -163,6 +178,7 @@ class PxrUsdKatanaUsdInArgs : public TfRefBase double _shutterOpen; double _shutterClose; std::vector _motionSampleTimes; + bool _isMotionBackward; // maps the root-level attribute name to the specified attributes or namespaces StringListMap _extraAttributesOrNamespaces; @@ -171,6 +187,8 @@ class PxrUsdKatanaUsdInArgs : public TfRefBase typedef tbb::enumerable_thread_specific< std::vector > _ThreadLocalBBoxCaches; _ThreadLocalBBoxCaches _bboxCaches; + + std::string _errorMessage; }; diff --git a/third_party/katana/lib/usdKatana/usdInPrivateData.cpp b/third_party/katana/lib/usdKatana/usdInPrivateData.cpp index c08f0f5d10..fc86011db8 100644 --- a/third_party/katana/lib/usdKatana/usdInPrivateData.cpp +++ b/third_party/katana/lib/usdKatana/usdInPrivateData.cpp @@ -75,13 +75,6 @@ PxrUsdKatanaUsdInPrivateData::PxrUsdKatanaUsdInPrivateData( } } -const std::vector -PxrUsdKatanaUsdInPrivateData::_GetNoMotion() -{ - static std::vector noMotion = {0.0}; - return noMotion; -} - const std::vector PxrUsdKatanaUsdInPrivateData::GetMotionSampleTimes(const UsdAttribute& attr) const { @@ -89,7 +82,8 @@ PxrUsdKatanaUsdInPrivateData::GetMotionSampleTimes(const UsdAttribute& attr) con if (attr and not PxrUsdKatanaUtils::IsAttributeVarying(attr, currentTime)) { - return _GetNoMotion(); + static std::vector noMotion = {0.0}; + return noMotion; } const std::vector motionSampleTimes = _usdInArgs->GetMotionSampleTimes(); @@ -107,15 +101,11 @@ PxrUsdKatanaUsdInPrivateData::GetMotionSampleTimes(const UsdAttribute& attr) con double shutterOpen = _usdInArgs->GetShutterOpen(); double shutterClose = _usdInArgs->GetShutterClose(); - double motionBegin = std::min( - motionSampleTimes.front(), motionSampleTimes.back()); - double shutterStartTime, shutterCloseTime; - // Calculate shutter start and close times based on whether - // we're to grab samples up to the current frame or from the - // current frame (typical motion specification is [0 -1]) - if (motionBegin < 0) + // Calculate shutter start and close times based on + // the direction of motion blur. + if (_usdInArgs->IsMotionBackward()) { shutterStartTime = currentTime - shutterClose; shutterCloseTime = currentTime - shutterOpen; @@ -134,17 +124,24 @@ PxrUsdKatanaUsdInPrivateData::GetMotionSampleTimes(const UsdAttribute& attr) con return motionSampleTimes; } - if (result.empty()) + bool foundSamplesInInterval = not result.empty(); + + double firstSample, lastSample; + + if (foundSamplesInInterval) { - return motionSampleTimes; + firstSample = result.front(); + lastSample = result.back(); + } + else + { + firstSample = shutterStartTime; + lastSample = shutterCloseTime; } - double firstSample = result.front(); - double lastSample = result.back(); - - // If the first sample is later than the shutter start time - // then attempt to get the previous sample in time. - if ((firstSample-shutterStartTime) > epsilon) + // If no samples were found or the first sample is later than the + // shutter start time then attempt to get the previous sample in time. + if (not foundSamplesInInterval or (firstSample-shutterStartTime) > epsilon) { double lower, upper; bool hasTimeSamples; @@ -161,9 +158,9 @@ PxrUsdKatanaUsdInPrivateData::GetMotionSampleTimes(const UsdAttribute& attr) con } } - // If the last sample is earlier than the shutter close time - // then attempt to get the next sample in time. - if ((shutterCloseTime-lastSample) > epsilon) + // If no samples were found or the last sample is earlier than the + // shutter close time then attempt to get the next sample in time. + if (not foundSamplesInInterval or (shutterCloseTime-lastSample) > epsilon) { double lower, upper; bool hasTimeSamples; diff --git a/third_party/katana/lib/usdKatana/usdInPrivateData.h b/third_party/katana/lib/usdKatana/usdInPrivateData.h index 6afc774bcb..37f5a99241 100644 --- a/third_party/katana/lib/usdKatana/usdInPrivateData.h +++ b/third_party/katana/lib/usdKatana/usdInPrivateData.h @@ -72,8 +72,6 @@ class PxrUsdKatanaUsdInPrivateData : public Foundry::Katana::GeolibPrivateData private: - static const std::vector _GetNoMotion(); - UsdPrim _prim; PxrUsdKatanaUsdInArgsRefPtr _usdInArgs; diff --git a/third_party/katana/lib/usdKatana/utils.cpp b/third_party/katana/lib/usdKatana/utils.cpp index ff2db18f32..e6880243d8 100644 --- a/third_party/katana/lib/usdKatana/utils.cpp +++ b/third_party/katana/lib/usdKatana/utils.cpp @@ -102,6 +102,14 @@ _ResolveAssetPath(const std::string &assetPath, bool asModel) return assetPath; } +double +PxrUsdKatanaUtils::ReverseTimeSample(double sample) +{ + // Only multiply when the sample is not 0 to avoid writing + // out a motion block containing -0. + return (sample == 0.0) ? sample : sample * -1; +} + void PxrUsdKatanaUtils::ConvertNumVertsToStartVerts( const std::vector &numVertsVec, std::vector *startVertsVec ) @@ -1235,6 +1243,7 @@ FnKat::DoubleAttribute PxrUsdKatanaUtils::ConvertBoundsToAttribute( const std::vector& bounds, const std::vector& motionSampleTimes, + const bool isMotionBackward, bool* hasInfiniteBounds) { FnKat::DoubleBuilder boundBuilder(6); @@ -1265,7 +1274,9 @@ PxrUsdKatanaUtils::ConvertBoundsToAttribute( *hasInfiniteBounds = true; } - std::vector &boundData = boundBuilder.get(fabs(relSampleTime)); + std::vector &boundData = boundBuilder.get( + isMotionBackward ? PxrUsdKatanaUtils::ReverseTimeSample(relSampleTime) : relSampleTime); + boundData.push_back( min[0] ); boundData.push_back( max[0] ); boundData.push_back( min[1] ); diff --git a/third_party/katana/lib/usdKatana/utils.h b/third_party/katana/lib/usdKatana/utils.h index 1892359abc..5db76810a6 100644 --- a/third_party/katana/lib/usdKatana/utils.h +++ b/third_party/katana/lib/usdKatana/utils.h @@ -44,6 +44,10 @@ namespace FnKat = Foundry::Katana; struct PxrUsdKatanaUtils { + /// Reverse a motion time sample. This is used for building + /// multi-sampled attributes when motion blur is backward. + static double ReverseTimeSample(double sample); + /// Convert Pixar-style numVerts to Katana-style startVerts. USDKATANA_API static void ConvertNumVertsToStartVerts( const std::vector &numVertsVec, @@ -163,6 +167,7 @@ struct PxrUsdKatanaUtils { static FnKat::DoubleAttribute ConvertBoundsToAttribute( const std::vector& bounds, const std::vector& motionSampleTimes, + bool isMotionBackward, bool* hasInfiniteBounds); /// \} diff --git a/third_party/katana/plugin/pxrUsdIn/pxrUsdIn.cpp b/third_party/katana/plugin/pxrUsdIn/pxrUsdIn.cpp index 68cfa75a22..2ae21d6947 100644 --- a/third_party/katana/plugin/pxrUsdIn/pxrUsdIn.cpp +++ b/third_party/katana/plugin/pxrUsdIn/pxrUsdIn.cpp @@ -109,6 +109,12 @@ class PxrUsdInOp : public FnKat::GeolibOp ERROR("Could not initialize PxrUsdIn usdInArgs."); return; } + + if (not usdInArgs->GetErrorMessage().empty()) + { + ERROR(usdInArgs->GetErrorMessage().c_str()); + return; + } if (interface.atRoot()) { interface.stopChildTraversal(); @@ -478,26 +484,80 @@ class PxrUsdInOp : public FnKat::GeolibOp return buffer.str(); } + + // utility to make it easier to exit earlier from InitUsdInArgs + struct ArgsBuilder + { + UsdStageRefPtr stage; + std::string rootLocation; + std::string isolatePath; + SdfPathSet variantSelections; + std::string ignoreLayerRegex; + double currentTime; + double shutterOpen; + double shutterClose; + std::vector motionSampleTimes; + PxrUsdKatanaUsdInArgs::StringListMap extraAttributesOrNamespaces; + bool verbose; + const char * errorMessage; + + + ArgsBuilder() + : currentTime(0.0) + , shutterOpen(0.0) + , shutterClose(0.0) + , verbose(false) + , errorMessage(0) + { + } + + PxrUsdKatanaUsdInArgsRefPtr build() + { + return PxrUsdKatanaUsdInArgs::New( + stage, + rootLocation, + isolatePath, + variantSelections, + ignoreLayerRegex, + currentTime, + shutterOpen, + shutterClose, + motionSampleTimes, + extraAttributesOrNamespaces, + verbose, + errorMessage); + } + + PxrUsdKatanaUsdInArgsRefPtr buildWithError(std::string errorStr) + { + errorMessage = errorStr.c_str(); + return build(); + } + + }; + + static PxrUsdKatanaUsdInArgsRefPtr InitUsdInArgs(const FnKat::GeolibCookInterface &interface, FnKat::GroupAttribute & additionalOpArgs) { + ArgsBuilder ab; + FnKat::StringAttribute usdFileAttr = interface.getOpArg("fileName"); if (not usdFileAttr.isValid()) { - FnLogInfo("Missing fileName attr."); - return TfNullPtr; + return ab.buildWithError("PxrUsdIn: USD fileName not specified."); } std::string fileName = usdFileAttr.getValue(); - std::string rootLocation = FnKat::StringAttribute( + ab.rootLocation = FnKat::StringAttribute( interface.getOpArg("location")).getValue( interface.getRootLocationPath(), false); std::string variants = FnKat::StringAttribute( interface.getOpArg("variants")).getValue("", false); - std::string sessionLocation = rootLocation; + std::string sessionLocation = ab.rootLocation; FnKat::StringAttribute sessionLocationAttr = interface.getOpArg("sessionLocation"); if (sessionLocationAttr.isValid()) { @@ -507,31 +567,32 @@ class PxrUsdInOp : public FnKat::GeolibOp variants += GetVariantStringFromSession( interface.getOpArg("session"), sessionLocation); - SdfPathSet variantSelections; + std::set selStrings = TfStringTokenizeToSet(variants); TF_FOR_ALL(selString, selStrings) { std::string errMsg; if (SdfPath::IsValidPathString(*selString, &errMsg)) { SdfPath varSelPath(*selString); if (varSelPath.IsPrimVariantSelectionPath()) { - variantSelections.insert( SdfPath(*selString) ); + ab.variantSelections.insert( SdfPath(*selString) ); continue; } - } - FnLogWarn(TfStringPrintf("Bad variant selection \"%s\"", - selString->c_str()).c_str()); - return TfNullPtr; + } + + return ab.buildWithError( + TfStringPrintf("PxrUsdIn: Bad variant selection \"%s\"", + selString->c_str()).c_str()); } - std::string ignoreLayerRegex = FnKat::StringAttribute( + ab.ignoreLayerRegex = FnKat::StringAttribute( interface.getOpArg("ignoreLayerRegex")).getValue("", false); - bool verbose = FnKat::IntAttribute( + ab.verbose = FnKat::IntAttribute( interface.getOpArg("verbose")).getValue(0, false); FnKat::GroupAttribute systemArgs(interface.getOpArg("system")); - double currentTime = + ab.currentTime = FnKat::FloatAttribute(systemArgs.getChildByName( "timeSlice.currentTime")).getValue(0, false); @@ -539,16 +600,14 @@ class PxrUsdInOp : public FnKat::GeolibOp FnKat::IntAttribute(systemArgs.getChildByName( "timeSlice.numSamples")).getValue(1, false); - double shutterOpen = + ab.shutterOpen = FnKat::FloatAttribute(systemArgs.getChildByName( "timeSlice.shutterOpen")).getValue(0, false); - double shutterClose = + ab.shutterClose = FnKat::FloatAttribute(systemArgs.getChildByName( "timeSlice.shutterClose")).getValue(0, false); - std::vector motionSampleTimes; - std::string motionSampleStr = FnKat::StringAttribute( interface.getOpArg("motionSampleTimes")).getValue("", false); @@ -557,7 +616,7 @@ class PxrUsdInOp : public FnKat::GeolibOp // if (numSamples < 2 or motionSampleStr.empty()) { - motionSampleTimes.push_back(0); + ab.motionSampleTimes.push_back(0); } else { @@ -566,20 +625,19 @@ class PxrUsdInOp : public FnKat::GeolibOp for (std::vector::iterator it = tokens.begin(); it != tokens.end(); ++it) { - motionSampleTimes.push_back(std::stod(*it)); + ab.motionSampleTimes.push_back(std::stod(*it)); } } - UsdStageRefPtr stage = + ab.stage = UsdKatanaCache::GetInstance().GetStage( fileName, - variantSelections, - ignoreLayerRegex, + ab.variantSelections, + ab.ignoreLayerRegex, true /* forcePopulate */); - if (not stage) { - FnLogInfo("No stage."); - return TfNullPtr; + if (not ab.stage) { + return ab.buildWithError("PxrUsdIn: USD Stage cannot be loaded."); } if (FnAttribute::StringAttribute( @@ -587,25 +645,26 @@ class PxrUsdInOp : public FnKat::GeolibOp ).getValue("expanded", false) == "as sources and instances") { additionalOpArgs = FnKat::GroupAttribute("masterMapping", - PxrUsdKatanaUtils::BuildInstanceMasterMapping(stage), true); + PxrUsdKatanaUtils::BuildInstanceMasterMapping(ab.stage), true); } - std::string isolatePath = FnKat::StringAttribute( + ab.isolatePath = FnKat::StringAttribute( interface.getOpArg("isolatePath")).getValue("", false); // if the specified isolatePath is not a valid prim, clear it out - if (not isolatePath.empty() and not stage->GetPrimAtPath(SdfPath(isolatePath))) + if (not ab.isolatePath.empty() and not ab.stage->GetPrimAtPath(SdfPath(ab.isolatePath))) { - FnLogWarn("Invalid isolatePath: " << isolatePath); - isolatePath = ""; + std::ostringstream errorBuffer; + errorBuffer << "PxrUsdIn: Invalid isolatePath: " << ab.isolatePath << "."; + return ab.buildWithError(errorBuffer.str()); } // get extra attributes or namespaces if they exist // - PxrUsdKatanaUsdInArgs::StringListMap extraAttributesOrNamespaces; + FnKat::StringAttribute extraAttributesOrNamespacesAttr = interface.getOpArg("extraAttributesOrNamespaces"); @@ -627,39 +686,28 @@ class PxrUsdInOp : public FnKat::GeolibOp } pystring::split(value, tokens, ":", 1); - extraAttributesOrNamespaces[tokens[0]].push_back(value); + ab.extraAttributesOrNamespaces[tokens[0]].push_back(value); } } // always include userProperties if not explicitly included. - if (extraAttributesOrNamespaces.find("userProperties") - == extraAttributesOrNamespaces.end()) + if (ab.extraAttributesOrNamespaces.find("userProperties") + == ab.extraAttributesOrNamespaces.end()) { - extraAttributesOrNamespaces["userProperties"].push_back( + ab.extraAttributesOrNamespaces["userProperties"].push_back( "userProperties"); } else { // if it is there, enforce that it includes only the top-level attr std::vector & userPropertiesNames = - extraAttributesOrNamespaces["userProperties"]; + ab.extraAttributesOrNamespaces["userProperties"]; userPropertiesNames.clear(); userPropertiesNames.push_back("userProperties"); } - - return PxrUsdKatanaUsdInArgs::New( - stage, - rootLocation, - isolatePath, - variantSelections, - ignoreLayerRegex, - currentTime, - shutterOpen, - shutterClose, - motionSampleTimes, - extraAttributesOrNamespaces, - verbose); + + return ab.build(); } private: @@ -694,9 +742,10 @@ class PxrUsdInOp : public FnKat::GeolibOp } std::vector bounds = usdInArgs->ComputeBounds(prim); const std::vector& motionSampleTimes = usdInArgs->GetMotionSampleTimes(); + bool hasInfiniteBounds = false; FnKat::DoubleAttribute boundsAttr = PxrUsdKatanaUtils::ConvertBoundsToAttribute( - bounds, motionSampleTimes, &hasInfiniteBounds); + bounds, motionSampleTimes, usdInArgs->IsMotionBackward(), &hasInfiniteBounds); // Report infinite bounds as a warning. if (hasInfiniteBounds) { @@ -742,6 +791,19 @@ class PxrUsdInBootstrapOp : public FnKat::GeolibOp FnKat::GroupAttribute additionalOpArgs; PxrUsdKatanaUsdInArgsRefPtr usdInArgs = PxrUsdInOp::InitUsdInArgs(interface, additionalOpArgs); + + if (not usdInArgs) { + ERROR("Could not initialize PxrUsdIn usdInArgs."); + return; + } + + if (not usdInArgs->GetErrorMessage().empty()) + { + ERROR(usdInArgs->GetErrorMessage().c_str()); + return; + } + + FnKat::GroupAttribute opArgs = FnKat::GroupBuilder() .update(interface.getOpArg()) diff --git a/third_party/katana/plugin/vmp_usd/usdVMP.cpp b/third_party/katana/plugin/vmp_usd/usdVMP.cpp index 19c9d0beb9..1842b92829 100644 --- a/third_party/katana/plugin/vmp_usd/usdVMP.cpp +++ b/third_party/katana/plugin/vmp_usd/usdVMP.cpp @@ -173,6 +173,20 @@ USDVMP::deepSetup(FnKat::ViewerModifierInput& input) // We are taking over all drawing for this location. input.overrideHostGeometry(); + + // store the view matrix + FnKat::DoubleAttribute mAttr = input.getDisplayMatrix(VIEW); + if (mAttr.isValid()) { + FnKat::DoubleConstVector vm = mAttr.getNearestSample(0.f); + _viewMatrix = + GfMatrix4d(GfRotation(GfVec3d(-1,0,0), 90), GfVec3d(0)) + * GfMatrix4d(vm[0], vm[1], vm[2], vm[3], + vm[4], vm[5], vm[6], vm[7], + vm[8], vm[9], vm[10], vm[11], + vm[12], vm[13], vm[14], vm[15]); + } else { + _viewMatrix = GfMatrix4d(1); + } } @@ -261,7 +275,17 @@ USDVMP::draw(FnKat::ViewerModifierInput& input) glGetIntegerv(GL_CURRENT_PROGRAM, &oldProgram); if (TF_VERIFY(_renderer)) { - _renderer->SetCameraStateFromOpenGL(); + // Copy camera from GL state, Katana does not provide it directly + GfMatrix4d modelViewMatrix, projectionMatrix; + GfVec4d viewport; + glGetDoublev(GL_MODELVIEW_MATRIX, modelViewMatrix.GetArray()); + glGetDoublev(GL_PROJECTION_MATRIX, projectionMatrix.GetArray()); + glGetDoublev(GL_VIEWPORT, &viewport[0]); + + _renderer->SetCameraState(_viewMatrix, projectionMatrix, viewport); + + GfMatrix4d modelMatrix = modelViewMatrix * (_viewMatrix.GetInverse()); + _renderer->SetRootTransform(modelMatrix); glPushAttrib(GL_LIGHTING_BIT | GL_ENABLE_BIT); @@ -272,7 +296,11 @@ USDVMP::draw(FnKat::ViewerModifierInput& input) glLightfv(GL_LIGHT0, GL_AMBIENT, params); } + glMatrixMode(GL_MODELVIEW); + glPushMatrix(); + glLoadMatrixd(_viewMatrix.GetArray()); _renderer->SetLightingStateFromOpenGL(); + glPopMatrix(); glPopAttrib(); diff --git a/third_party/katana/plugin/vmp_usd/usdVMP.h b/third_party/katana/plugin/vmp_usd/usdVMP.h index b75bfd42ce..2df9ead7bf 100644 --- a/third_party/katana/plugin/vmp_usd/usdVMP.h +++ b/third_party/katana/plugin/vmp_usd/usdVMP.h @@ -100,6 +100,8 @@ class USDVMP : public FnKat::ViewerModifier UsdImagingGLSharedPtr _renderer; UsdImagingGL::RenderParams _params; UsdPrim _prim; + + GfMatrix4d _viewMatrix; }; #endif diff --git a/third_party/maya/lib/pxrUsdMayaGL/CMakeLists.txt b/third_party/maya/lib/pxrUsdMayaGL/CMakeLists.txt index 5f47b03947..b8a6d5db8c 100644 --- a/third_party/maya/lib/pxrUsdMayaGL/CMakeLists.txt +++ b/third_party/maya/lib/pxrUsdMayaGL/CMakeLists.txt @@ -36,5 +36,6 @@ pxr_shared_library(${PXR_PACKAGE} batchRenderer proxyDrawOverride proxyShapeUI + softSelectHelper ) diff --git a/third_party/maya/lib/pxrUsdMayaGL/batchRenderer.cpp b/third_party/maya/lib/pxrUsdMayaGL/batchRenderer.cpp index 5d49c0ff74..16e255b9f5 100644 --- a/third_party/maya/lib/pxrUsdMayaGL/batchRenderer.cpp +++ b/third_party/maya/lib/pxrUsdMayaGL/batchRenderer.cpp @@ -172,6 +172,52 @@ UsdMayaGLBatchRenderer::ShapeRenderer::PrepareForQueue( } } + +// Helper function that converts the M3dView::DisplayStatus (viewport 1.0) +// into the MHWRender::DisplayStatus (viewport 2.0) +static inline +MHWRender::DisplayStatus +_ToMHWRenderDisplayStatus(const M3dView::DisplayStatus& displayStatus) +{ + // these enums are equivalent, but statically checking just in case. + static_assert(((int)M3dView::kActive == (int)MHWRender::kActive) + and ((int)M3dView::kLive == (int)MHWRender::kLive) + and ((int)M3dView::kDormant == (int)MHWRender::kDormant) + and ((int)M3dView::kInvisible == (int)MHWRender::kInvisible) + and ((int)M3dView::kHilite == (int)MHWRender::kHilite) + and ((int)M3dView::kTemplate == (int)MHWRender::kTemplate) + and ((int)M3dView::kActiveTemplate == (int)MHWRender::kActiveTemplate) + and ((int)M3dView::kActiveComponent == (int)MHWRender::kActiveComponent) + and ((int)M3dView::kLead == (int)MHWRender::kLead) + and ((int)M3dView::kIntermediateObject == (int)MHWRender::kIntermediateObject) + and ((int)M3dView::kActiveAffected == (int)MHWRender::kActiveAffected) + and ((int)M3dView::kNoStatus == (int)MHWRender::kNoStatus), + "M3dView::DisplayStatus == MHWRender::DisplayStatus"); + return MHWRender::DisplayStatus((int)displayStatus); +} + +static +bool +_GetWireframeColor( + const UsdMayaGLSoftSelectHelper& softSelectHelper, + const MDagPath& objPath, + const MHWRender::DisplayStatus& displayStatus, + MColor* mayaWireColor) +{ + // dormant objects may be included in soft selection. + if (displayStatus == MHWRender::kDormant) { + return softSelectHelper.GetFalloffColor(objPath, mayaWireColor); + } + else if ((displayStatus == MHWRender::kActive) or + (displayStatus == MHWRender::kLead) or + (displayStatus == MHWRender::kHilite)) { + *mayaWireColor = MHWRender::MGeometryUtilities::wireframeColor(objPath); + return true; + } + + return false; +} + UsdMayaGLBatchRenderer::RenderParams UsdMayaGLBatchRenderer::ShapeRenderer::GetRenderParams( const MDagPath& objPath, @@ -194,16 +240,15 @@ UsdMayaGLBatchRenderer::ShapeRenderer::GetRenderParams( // QueueShapeForDraw(...) will later break this single param set into // two, to perform a two-pass render. // - bool selected = - (displayStatus == M3dView::kActive) || - (displayStatus == M3dView::kLead) || - (displayStatus == M3dView::kHilite); - - if( selected ) + MColor mayaWireframeColor; + bool needsWire = _GetWireframeColor( + _batchRenderer->GetSoftSelectHelper(), + objPath, + _ToMHWRenderDisplayStatus(displayStatus), + &mayaWireframeColor); + + if( needsWire ) { - const MColor mayaWireframeColor = - MHWRender::MGeometryUtilities::wireframeColor(objPath); - // The legacy viewport does not support color management, // so we roll our own gamma correction via framebuffer effect. // But that means we need to pre-linearize the wireframe color @@ -227,7 +272,7 @@ UsdMayaGLBatchRenderer::ShapeRenderer::GetRenderParams( } case M3dView::kGouraudShaded: { - if( selected ) + if( needsWire ) params.drawRepr = HdTokens->refinedWireOnSurf; else params.drawRepr = HdTokens->refined; @@ -235,7 +280,7 @@ UsdMayaGLBatchRenderer::ShapeRenderer::GetRenderParams( } case M3dView::kFlatShaded: { - if( selected ) + if( needsWire ) params.drawRepr = HdTokens->wireOnSurf; else params.drawRepr = HdTokens->hull; @@ -274,15 +319,14 @@ UsdMayaGLBatchRenderer::ShapeRenderer::GetRenderParams( // QueueShapeForDraw(...) will later break this single param set into // two, to perform a two-pass render. // - bool selected = - (displayStatus == MHWRender::kActive) || - (displayStatus == MHWRender::kLead) || - (displayStatus == MHWRender::kHilite); + MColor mayaWireframeColor; + bool needsWire = _GetWireframeColor( + _batchRenderer->GetSoftSelectHelper(), + objPath, displayStatus, + &mayaWireframeColor); - if( selected ) + if( needsWire ) { - const MColor mayaWireframeColor = - MHWRender::MGeometryUtilities::wireframeColor(objPath); params.wireframeColor = GfVec4f( mayaWireframeColor.r, @@ -301,14 +345,14 @@ UsdMayaGLBatchRenderer::ShapeRenderer::GetRenderParams( if( flatShaded ) { - if( selected ) + if( needsWire ) params.drawRepr = HdTokens->wireOnSurf; else params.drawRepr = HdTokens->hull; } else if( displayStyle & MHWRender::MFrameContext::DisplayStyle::kGouraudShaded ) { - if( selected || (displayStyle & MHWRender::MFrameContext::DisplayStyle::kWireFrame) ) + if( needsWire || (displayStyle & MHWRender::MFrameContext::DisplayStyle::kWireFrame) ) params.drawRepr = HdTokens->refinedWireOnSurf; else params.drawRepr = HdTokens->refined; @@ -527,13 +571,25 @@ UsdMayaGLBatchRenderer::TaskDelegate::SetCameraState( } void -UsdMayaGLBatchRenderer::TaskDelegate::SetLightingStateFromOpenGL() +UsdMayaGLBatchRenderer::TaskDelegate::SetLightingStateFromOpenGL(const MMatrix& viewMatForLights) { // XXX: this is a dumb copy of UsdImaging::HdEngine // ideally we should directly suck the lightint parameter from // maya API and put them into HdLight. - _lightingContextForOpenGLState->SetStateFromOpenGL(); + // We only transform the light positions into view space if the view matrix + // is non-identity (the VP1.0 case). If the view matrix is identity (the + // VP2.0 case), the light positions have already been transformed, so don't + // doubly transform them. + if (viewMatForLights != MMatrix::identity) { + glMatrixMode(GL_MODELVIEW); + glPushMatrix(); + glLoadMatrixd(viewMatForLights.matrix[0]); + _lightingContextForOpenGLState->SetStateFromOpenGL(); + glPopMatrix(); + } else { + _lightingContextForOpenGLState->SetStateFromOpenGL(); + } // cache the GlfSimpleLight vector GlfSimpleLightVector const &lights @@ -698,6 +754,13 @@ UsdMayaGLBatchRenderer::GetShapeRenderer( return toReturn; } +const UsdMayaGLSoftSelectHelper& +UsdMayaGLBatchRenderer::GetSoftSelectHelper() +{ + _softSelectHelper.Populate(); + return _softSelectHelper; +} + UsdMayaGLBatchRenderer::UsdMayaGLBatchRenderer() : _renderIndex(new HdRenderIndex()) , _taskDelegate(new TaskDelegate(_renderIndex, SdfPath("/mayaTask"))) @@ -1040,7 +1103,7 @@ UsdMayaGLBatchRenderer::_RenderBatches( invisedPrimPaths ); _populateQueue.clear(); - + TF_DEBUG(PXRUSDMAYAGL_QUEUE_INFO).Msg( "^^^^^^^^^^^^ POPULATE STAGE FINISH ^^^^^^^^^^^^^ (%zu)\n",_populateQueue.size()); } @@ -1052,6 +1115,11 @@ UsdMayaGLBatchRenderer::_RenderBatches( // longer valid. _selectQueue.clear(); _selectResults.clear(); + + // We've already populated with all the selection info we need. We Reset + // and the first call to GetSoftSelectHelper in the next render pass will + // re-populate it. + _softSelectHelper.Reset(); GfMatrix4d modelViewMatrix(viewMat.matrix); GfMatrix4d projectionMatrix(projectionMat.matrix); @@ -1071,10 +1139,17 @@ UsdMayaGLBatchRenderer::_RenderBatches( glDisable(GL_BLEND); glEnable(GL_SAMPLE_ALPHA_TO_COVERAGE); - if( vp2Context ) + // With VP2.0, the utils method will take care of transforming the light + // positions from world space into view space when it loads them into GL. + // For VP1.0, we will need to transform the light positions ourselves. + MMatrix viewMatForLights; + if (vp2Context) { px_vp20Utils::setupLightingGL(*vp2Context); + } else { + viewMatForLights = viewMat; + } - _taskDelegate->SetLightingStateFromOpenGL(); + _taskDelegate->SetLightingStateFromOpenGL(viewMatForLights); // The legacy viewport does not support color management, // so we roll our own gamma correction by GL means (only in diff --git a/third_party/maya/lib/pxrUsdMayaGL/batchRenderer.h b/third_party/maya/lib/pxrUsdMayaGL/batchRenderer.h index d0244d40d2..e5568f1253 100644 --- a/third_party/maya/lib/pxrUsdMayaGL/batchRenderer.h +++ b/third_party/maya/lib/pxrUsdMayaGL/batchRenderer.h @@ -28,7 +28,8 @@ #ifndef PXRUSDMAYAGL_BATCHRENDERER_H #define PXRUSDMAYAGL_BATCHRENDERER_H -#include "pxrUsdMayaGL/api.h" +#include "pxrUsdMayaGL/softSelectHelper.h" + #include "pxr/base/arch/hash.h" #include "pxr/base/tf/debug.h" #include "pxr/usd/usd/stage.h" @@ -244,7 +245,7 @@ class USDMAYAGL_API UsdMayaGLBatchRenderer : private boost::noncopyable void SetCameraState(const GfMatrix4d& viewMatrix, const GfMatrix4d& projectionMatrix, const GfVec4d& viewport); - void SetLightingStateFromOpenGL(); + void SetLightingStateFromOpenGL(const MMatrix& viewMatForLights); HdTaskSharedPtrVector GetSetupTasks(); @@ -297,6 +298,10 @@ class USDMAYAGL_API UsdMayaGLBatchRenderer : private boost::noncopyable const SdfPathVector& excludePrimPaths, const MDagPath& objPath ); + /// \brief Gets UsdMayaGLSoftSelectHelper that this batchRenderer maintains. + /// This should only be used by ShapeRenderer::GetRenderParams + const UsdMayaGLSoftSelectHelper& GetSoftSelectHelper(); + /// \brief Construct a new, unique BatchRenderer. In almost all cases, /// this should not be used -- use \c GlobalBatchRenderer() instead. UsdMayaGLBatchRenderer(); @@ -395,6 +400,7 @@ class USDMAYAGL_API UsdMayaGLBatchRenderer : private boost::noncopyable HdRenderIndexSharedPtr _renderIndex; TaskDelegateSharedPtr _taskDelegate; HdxIntersectorSharedPtr _intersector; + UsdMayaGLSoftSelectHelper _softSelectHelper; /// \brief Sole global batch renderer used by default. static UsdMayaGLBatchRenderer _sGlobalRenderer; diff --git a/third_party/maya/lib/pxrUsdMayaGL/softSelectHelper.cpp b/third_party/maya/lib/pxrUsdMayaGL/softSelectHelper.cpp new file mode 100644 index 0000000000..9fb120742d --- /dev/null +++ b/third_party/maya/lib/pxrUsdMayaGL/softSelectHelper.cpp @@ -0,0 +1,138 @@ +// +// 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. +// + +#include "pxrUsdMayaGL/softSelectHelper.h" + +#include "pxr/base/tf/stl.h" + +#include +#include +#include +#include + +UsdMayaGLSoftSelectHelper::UsdMayaGLSoftSelectHelper() + : _populated(false) +{ +} + +#define _PXRUSDMAYA_SOFTSELECT_COLORRAMP 1 + +void +UsdMayaGLSoftSelectHelper::Reset() +{ + _populated = false; + _dagPathsToWeight.clear(); +} + +void +UsdMayaGLSoftSelectHelper::Populate() +{ + // only populate if we haven't already + if (_populated) { + return; + } + + _PopulateWeights(); + _PopulateSoftSelectColorRamp(); + + _populated = true; +} + +void +UsdMayaGLSoftSelectHelper::_PopulateWeights() +{ + // we don't want to fallback to the active selection if there is no sot + // select + bool defaultToActiveSelection = false; + MRichSelection softSelect; + MGlobal::getRichSelection(softSelect, defaultToActiveSelection); + MSelectionList selection; + softSelect.getSelection(selection); + + for (MItSelectionList iter( selection, MFn::kInvalid); !iter.isDone(); iter.next() ) { + MDagPath dagPath; + MObject component; + + iter.getDagPath(dagPath, component); + // component.isNull() indcates that we're selecting a whole object, as + // opposed to a component. + if (not component.isNull()) { + continue; + } + + float weight = 0.0f; + _dagPathsToWeight[dagPath] = weight; + } +} + +void +UsdMayaGLSoftSelectHelper::_PopulateSoftSelectColorRamp() +{ + // Since in we are not able to get the real distance/weight value, we don't + // yet store the full color ramp. We just get the first color which at + // least gives feedback over which things will be influenced. + bool success = false; + MString commandResult; + + // it's really unfortunate that we have to go through this instead of having + // direct access to this. + if (MGlobal::executeCommand("softSelect -query -softSelectColorCurve", + commandResult)) { + + // parse only the first tuple. + int interp; + float r, g, b; + float position; + if (sscanf(commandResult.asChar(), + "%f,%f,%f,%f,%d", &r, &g, &b, &position, &interp) == 5) { + _wireColor = MColor(r,g,b); + success = true; + } + } + + if (not success) { + _wireColor = MColor(0.f, 0.f, 1.f); + } +} + +bool +UsdMayaGLSoftSelectHelper::GetWeight( + const MDagPath& dagPath, + float* weight) const +{ + return TfMapLookup(_dagPathsToWeight, dagPath, weight); +} + +bool +UsdMayaGLSoftSelectHelper::GetFalloffColor( + const MDagPath& dagPath, + MColor* falloffColor) const +{ + float weight = 0.f; + if (GetWeight(dagPath, &weight)) { + *falloffColor = _wireColor; + return true; + } + return false; +} diff --git a/third_party/maya/lib/pxrUsdMayaGL/softSelectHelper.h b/third_party/maya/lib/pxrUsdMayaGL/softSelectHelper.h new file mode 100644 index 0000000000..ca65b92e31 --- /dev/null +++ b/third_party/maya/lib/pxrUsdMayaGL/softSelectHelper.h @@ -0,0 +1,93 @@ +// +// 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. +// +/// +/// \file softSelectHelper.h +/// + +#ifndef PXRUSDMAYAGL_SOFTSELECTHELPER_H +#define PXRUSDMAYAGL_SOFTSELECTHELPER_H + +#include "pxr/base/tf/hash.h" + +#include +#include +#include +#include + +#include + +/// \class UsdMayaGLSoftSelectHelper +/// \brief Helper class to store soft ("rich") selection state while +/// computing render params for a frame. +/// +/// When rendering, we want to be able to draw things that will be influenced by +/// soft selection with a different wireframe. Querying this maya state is too +/// expensive do in the middle of the render loop so this class lets us compute +/// it once at the beginning of a frame render, and then query it later. +/// +/// While this class doesn't have anything particular to rendering, it is only +/// used by the render and is therefore here. We can move this to usdMaya if +/// we'd like to use it outside of the rendering. +class UsdMayaGLSoftSelectHelper +{ +public: + UsdMayaGLSoftSelectHelper(); + + /// \brief Clears the saved soft selection state. + void Reset(); + + /// \brief Repopulates soft selection state + void Populate(); + + /// \brief Returns true if \p dagPath is in the softSelection. Also returns + /// the \p weight. + /// + /// NOTE: until MAYA-73448 (and MAYA-73513) is fixed, the \p weight value is + /// arbitrary. + bool GetWeight(const MDagPath& dagPath, float* weight) const; + + /// \brief Returns true if \p dagPath is in the softSelection. Also returns + /// the appropriate color based on the distance/weight and the current soft + /// select color curve. It will currently always return (0, 0, 1) at the + /// moment. + bool GetFalloffColor(const MDagPath& dagPath, MColor* falloffColor) const; + +private: + + void _PopulateWeights(); + void _PopulateSoftSelectColorRamp(); + + struct _MDagPathHash { + inline size_t operator()(const MDagPath& dagPath) const { + return TfHash()(std::string(dagPath.fullPathName().asChar())); + } + }; + typedef std::unordered_map _MDagPathsToWeights; + + _MDagPathsToWeights _dagPathsToWeight; + MColor _wireColor; + bool _populated; +}; + +#endif // PXRUSDMAYAGL_SOFTSELECTHELPER_H diff --git a/third_party/maya/lib/usdMaya/AEpxrUsdReferenceAssemblyTemplate.py b/third_party/maya/lib/usdMaya/AEpxrUsdReferenceAssemblyTemplate.py index 868092eb4c..9bc797d267 100644 --- a/third_party/maya/lib/usdMaya/AEpxrUsdReferenceAssemblyTemplate.py +++ b/third_party/maya/lib/usdMaya/AEpxrUsdReferenceAssemblyTemplate.py @@ -111,7 +111,7 @@ def variantSets_Replace(nodeAttr, new): if new == True: cmds.frameLayout(frameLayoutName, label='VariantSets', collapse=False) else: - cmds.setParent(frameLayoutName); + cmds.setParent(frameLayoutName) # Remove existing children of layout children = cmds.frameLayout(frameLayoutName, q=True, childArray=True) @@ -131,8 +131,8 @@ def variantSets_Replace(nodeAttr, new): for regVarSet in UsdUtils.GetRegisteredVariantSets()] if usdPrim: - variantSets = usdPrim.GetVariantSets(); - variantSetNames = variantSets.GetNames(); + variantSets = usdPrim.GetVariantSets() + variantSetNames = variantSets.GetNames() for variantSetName in variantSetNames: if regVarSetNames and (variantSetName not in regVarSetNames): diff --git a/third_party/maya/lib/usdMaya/MayaMeshWriter.cpp b/third_party/maya/lib/usdMaya/MayaMeshWriter.cpp index d84d0ce3e2..8817f91c08 100644 --- a/third_party/maya/lib/usdMaya/MayaMeshWriter.cpp +++ b/third_party/maya/lib/usdMaya/MayaMeshWriter.cpp @@ -25,6 +25,8 @@ #include "usdMaya/meshUtil.h" +#include "pxr/base/gf/vec3f.h" +#include "pxr/base/tf/staticTokens.h" #include "pxr/usd/usdGeom/mesh.h" #include "pxr/usd/usdGeom/pointBased.h" #include "pxr/usd/usdUtils/pipeline.h" @@ -33,6 +35,19 @@ #include #include +TF_DEFINE_PRIVATE_TOKENS(_tokens, + ((DisplayColorColorSetName, "displayColor")) + ((DisplayOpacityColorSetName, "displayOpacity")) +); + + +const GfVec3f MayaMeshWriter::_ShaderDefaultRGB = GfVec3f(0.5); +const float MayaMeshWriter::_ShaderDefaultAlpha = 0.0; + +const GfVec3f MayaMeshWriter::_ColorSetDefaultRGB = GfVec3f(1.0); +const float MayaMeshWriter::_ColorSetDefaultAlpha = 1.0; + + MayaMeshWriter::MayaMeshWriter( MDagPath & iDag, UsdStageRefPtr stage, @@ -41,7 +56,6 @@ MayaMeshWriter::MayaMeshWriter( { } - //virtual UsdPrim MayaMeshWriter::write(const UsdTimeCode &usdTime) { @@ -214,106 +228,153 @@ bool MayaMeshWriter::writeMeshAttrs(const UsdTimeCode &usdTime, UsdGeomMesh &pri if (getArgs().exportColorSets) { status = lMesh.getColorSetNames(colorSetNames); } - // shaderColor is used in our pipeline as displayColor. - // shaderColor is used to fill faces where the colorset is not assigned - MColorArray shaderColors; - MObjectArray shaderObjs; - + VtArray shadersRGBData; - TfToken shadersRGBInterp; VtArray shadersAlphaData; - TfToken shadersAlphaInterp; - - // If exportDisplayColor is set to true or we have color sets, - // gather color & opacity from the shader including per face - // assignment. Color set require this to initialize unauthored/unpainted faces - if (getArgs().exportDisplayColor or colorSetNames.length()>0) { - PxrUsdMayaUtil::GetLinearShaderColor(lMesh, numPolygons, - &shadersRGBData, &shadersRGBInterp, - &shadersAlphaData, &shadersAlphaInterp); + TfToken shadersInterpolation; + VtArray shadersAssignmentIndices; + + // If we're exporting displayColor or we have color sets, gather colors and + // opacities from the shaders assigned to the mesh and/or its faces. + // If we find a displayColor color set, the shader colors and opacities + // will be used to fill in unauthored/unpainted faces in the color set. + if (getArgs().exportDisplayColor or colorSetNames.length() > 0) { + PxrUsdMayaUtil::GetLinearShaderColor(lMesh, + &shadersRGBData, + &shadersAlphaData, + &shadersInterpolation, + &shadersAssignmentIndices); } - for (unsigned int i=0; i < colorSetNames.length(); i++) { + for (unsigned int i=0; i < colorSetNames.length(); ++i) { - bool isDisplayColor=false; + bool isDisplayColor = false; - if (colorSetNames[i]=="displayColor") { - if (not getArgs().exportDisplayColor) + if (colorSetNames[i] == _tokens->DisplayColorColorSetName.GetText()) { + if (not getArgs().exportDisplayColor) { continue; + } isDisplayColor=true; } - if (colorSetNames[i]=="displayOpacity") { - MGlobal::displayWarning("displayOpacity on mesh:" + lMesh.fullPathName() + - " is a reserved PrimVar name in USD. Skipping..."); + if (colorSetNames[i] == _tokens->DisplayOpacityColorSetName.GetText()) { + MGlobal::displayWarning("Mesh \"" + lMesh.fullPathName() + + "\" has a color set named \"" + + MString(_tokens->DisplayOpacityColorSetName.GetText()) + + "\" which is a reserved Primvar name in USD. Skipping..."); continue; } VtArray RGBData; - TfToken RGBInterp; - VtArray RGBAData; - TfToken RGBAInterp; VtArray AlphaData; - TfToken AlphaInterp; + TfToken interpolation; + VtArray assignmentIndices; + int unassignedValueIndex = -1; MFnMesh::MColorRepresentation colorSetRep; - bool clamped=false; - - // If displayColor uses shaderValues for non authored areas - // and allow RGB and Alpha to have different interpolation - // For all other colorSets the non authored values are set - // to (1,1,1,1) and RGB and Alpha will have the same interplation - // since they will be emitted as a Vec4f - if (not _GetMeshColorSetData( lMesh, colorSetNames[i], - isDisplayColor, - shadersRGBData, shadersAlphaData, - &RGBData, &RGBInterp, - &RGBAData, &RGBAInterp, - &AlphaData, &AlphaInterp, - &colorSetRep, &clamped)) { + bool clamped = false; + + if (not _GetMeshColorSetData(lMesh, + colorSetNames[i], + isDisplayColor, + shadersRGBData, + shadersAlphaData, + shadersAssignmentIndices, + &RGBData, + &AlphaData, + &interpolation, + &assignmentIndices, + &colorSetRep, + &clamped)) { MGlobal::displayWarning("Unable to retrieve colorSet data: " + - colorSetNames[i] + " on mesh: "+ lMesh.fullPathName() + ". Skipping..."); + colorSetNames[i] + " on mesh: " + lMesh.fullPathName() + + ". Skipping..."); continue; } + PxrUsdMayaUtil::AddUnassignedColorAndAlphaIfNeeded( + &RGBData, + &AlphaData, + &assignmentIndices, + &unassignedValueIndex, + _ColorSetDefaultRGB, + _ColorSetDefaultAlpha); + if (isDisplayColor) { // We tag the resulting displayColor/displayOpacity primvar as - // authored to make sure we reconstruct the colorset on import - // The RGB is also convererted From DisplayToLinear - - - _setDisplayPrimVar( primSchema, colorSetRep, - RGBData, RGBInterp, - AlphaData, AlphaInterp, - clamped, true); + // authored to make sure we reconstruct the color set on import. + _addDisplayPrimvars(primSchema, + colorSetRep, + RGBData, + AlphaData, + interpolation, + assignmentIndices, + unassignedValueIndex, + clamped, + true); } else { TfToken colorSetNameToken = TfToken( - PxrUsdMayaUtil::SanitizeColorSetName( - std::string(colorSetNames[i].asChar()))); + PxrUsdMayaUtil::SanitizeColorSetName( + std::string(colorSetNames[i].asChar()))); if (colorSetRep == MFnMesh::kAlpha) { - _createAlphaPrimVar(primSchema, colorSetNameToken, - AlphaData, AlphaInterp, clamped); + _createAlphaPrimVar(primSchema, + colorSetNameToken, + AlphaData, + interpolation, + assignmentIndices, + unassignedValueIndex, + clamped); } else if (colorSetRep == MFnMesh::kRGB) { - _createRGBPrimVar(primSchema, colorSetNameToken, - RGBData, RGBInterp, clamped); + _createRGBPrimVar(primSchema, + colorSetNameToken, + RGBData, + interpolation, + assignmentIndices, + unassignedValueIndex, + clamped); } else if (colorSetRep == MFnMesh::kRGBA) { - _createRGBAPrimVar(primSchema, colorSetNameToken, - RGBAData, RGBAInterp, clamped); + _createRGBAPrimVar(primSchema, + colorSetNameToken, + RGBData, + AlphaData, + interpolation, + assignmentIndices, + unassignedValueIndex, + clamped); } } } - // Set displayColor and displayOpacity only if they are NOT authored already - // Since this primvar will come from the shader and not a colorset, - // we are not adding the clamp attribute as custom data - // If a displayColor/displayOpacity is added, it's not considered authored - // we don't need to reconstruct this as a colorset since it orgininated - // from bound shader[s], so the authored flag is set to false - // Given that this RGB is for display, we do DisplayToLinear conversion + + // _addDisplayPrimvars() will only author displayColor and displayOpacity + // if no authored opinions exist, so the code below only has an effect if + // we did NOT find a displayColor color set above. if (getArgs().exportDisplayColor) { - _setDisplayPrimVar( primSchema, MFnMesh::kRGBA, - shadersRGBData, shadersRGBInterp, - shadersAlphaData, shadersAlphaInterp, - false, false); + // Using the shader default values (an alpha of zero, in particular) + // results in Gprims rendering the same way in usdview as they do in + // Maya (i.e. unassigned components are invisible). + int unassignedValueIndex = -1; + PxrUsdMayaUtil::AddUnassignedColorAndAlphaIfNeeded( + &shadersRGBData, + &shadersAlphaData, + &shadersAssignmentIndices, + &unassignedValueIndex, + _ShaderDefaultRGB, + _ShaderDefaultAlpha); + + // Since these colors come from the shaders and not a colorset, we are + // not adding the clamp attribute as custom data. We also don't need to + // reconstruct a color set from them on import since they originated + // from the bound shader(s), so the authored flag is set to false. + _addDisplayPrimvars(primSchema, + MFnMesh::kRGBA, + shadersRGBData, + shadersAlphaData, + shadersInterpolation, + shadersAssignmentIndices, + unassignedValueIndex, + false, + false); } + return true; } diff --git a/third_party/maya/lib/usdMaya/MayaMeshWriter.h b/third_party/maya/lib/usdMaya/MayaMeshWriter.h index f8515444a0..56c74e4399 100644 --- a/third_party/maya/lib/usdMaya/MayaMeshWriter.h +++ b/third_party/maya/lib/usdMaya/MayaMeshWriter.h @@ -21,18 +21,17 @@ // KIND, either express or implied. See the Apache License for the specific // language governing permissions and limitations under the Apache License. // -#ifndef _usdExport_MayaMeshWriter_h_ -#define _usdExport_MayaMeshWriter_h_ +#ifndef PXRUSDMAYA_MAYAMESHWRITER_H +#define PXRUSDMAYA_MAYAMESHWRITER_H #include "usdMaya/MayaTransformWriter.h" + #include class UsdGeomMesh; class UsdGeomGprim; -class MFnLambertShader; -class MFnMesh; class MString; -class MColorArray; + // Writes an MFnMesh as a poly mesh OR a subd mesh class MayaMeshWriter : public MayaTransformWriter @@ -57,18 +56,20 @@ class MayaMeshWriter : public MayaTransformWriter MStatus _GetMeshUVSetData( MFnMesh& m, MString uvSetName, VtArray *uvArray, TfToken *interpolation); - + bool _GetMeshColorSetData( - MFnMesh& m, + MFnMesh& mesh, MString colorSet, bool isDisplayColor, const VtArray& shadersRGBData, const VtArray& shadersAlphaData, - VtArray *RGBData, TfToken *RGBInterp, - VtArray *RGBAData, TfToken *RGBAInterp, - VtArray *AlphaData, TfToken *AlphaInterp, - MFnMesh::MColorRepresentation *colorSetRep, - bool *clamped); + const VtArray& shadersAssignmentIndices, + VtArray* colorSetRGBData, + VtArray* colorSetAlphaData, + TfToken* interpolation, + VtArray* colorSetAssignmentIndices, + MFnMesh::MColorRepresentation* colorSetRep, + bool* clamped); static MStatus _CompressUVs(const MFnMesh& m, @@ -83,25 +84,56 @@ class MayaMeshWriter : public MayaTransformWriter const MFloatArray& uArray, const MFloatArray& vArray, VtArray *uvArray); - bool _createAlphaPrimVar( UsdGeomGprim &primSchema, const TfToken name, - const VtArray& data, TfToken interpolation, - bool clamped); + bool _createAlphaPrimVar(UsdGeomGprim &primSchema, + const TfToken& name, + const VtArray& data, + const TfToken& interpolation, + const VtArray& assignmentIndices, + const int unassignedValueIndex, + bool clamped); - bool _createRGBPrimVar( UsdGeomGprim &primSchema, const TfToken name, - const VtArray& data, TfToken interpolation, + bool _createRGBPrimVar(UsdGeomGprim &primSchema, + const TfToken& name, + const VtArray& data, + const TfToken& interpolation, + const VtArray& assignmentIndices, + const int unassignedValueIndex, + bool clamped); + + bool _createRGBAPrimVar(UsdGeomGprim &primSchema, + const TfToken& name, + const VtArray& rgbData, + const VtArray& alphaData, + const TfToken& interpolation, + const VtArray& assignmentIndices, + const int unassignedValueIndex, bool clamped); - bool _createRGBAPrimVar( UsdGeomGprim &primSchema, const TfToken name, - const VtArray& RGBAData, TfToken RGBAInterp, - bool clamped); + /// Adds displayColor and displayOpacity primvars using the given color, + /// alpha, and assignment data if the \p primSchema does not already have + /// authored opinions for them. + bool _addDisplayPrimvars( + UsdGeomGprim &primSchema, + const MFnMesh::MColorRepresentation colorRep, + const VtArray& RGBData, + const VtArray& AlphaData, + const TfToken& interpolation, + const VtArray& assignmentIndices, + const int unassignedValueIndex, + const bool clamped, + const bool authored); + + /// Default values to use when collecting colors based on shader values + /// and an object or component has no assigned shader. + static const GfVec3f _ShaderDefaultRGB; + static const float _ShaderDefaultAlpha; - bool _setDisplayPrimVar( UsdGeomGprim &primSchema, - MFnMesh::MColorRepresentation colorRep, - VtArray RGBData, TfToken RGBInterp, - VtArray AlphaData, TfToken AlphaInterp, - bool clamped, bool authored); + /// Default values to use when collecting colors from a color set and a + /// component has no authored value. + static const GfVec3f _ColorSetDefaultRGB; + static const float _ColorSetDefaultAlpha; }; typedef shared_ptr < MayaMeshWriter > MayaMeshWriterPtr; -#endif // _usdExport_MayaMeshWriter_h_ +#endif // PXRUSDMAYA_MAYAMESHWRITER_H diff --git a/third_party/maya/lib/usdMaya/MayaMeshWriter_PrimVars.cpp b/third_party/maya/lib/usdMaya/MayaMeshWriter_PrimVars.cpp index 073536d5c4..f2c5ccf926 100644 --- a/third_party/maya/lib/usdMaya/MayaMeshWriter_PrimVars.cpp +++ b/third_party/maya/lib/usdMaya/MayaMeshWriter_PrimVars.cpp @@ -23,100 +23,186 @@ // #include "usdMaya/MayaMeshWriter.h" +#include "pxr/base/gf/gamma.h" #include "pxr/base/gf/math.h" #include "pxr/base/gf/transform.h" -#include "pxr/base/gf/gamma.h" - #include "pxr/usd/usdGeom/mesh.h" -#include +#include #include #include -#include -#include -#include -#include -#include #include -#include -#include #include -// This function tries to compress facevarying data to uniform, vertex or constant -// Loop over all elements and invalidate any of the 3 conditions -// Copy uniform and vertex values into a temporary array -// At the end resize to 1 or copy those temporary array into the resulting data -template -static void compressFVPrimvar(MFnMesh& m, VtArray *data, TfToken *interpolation) +#include + + +template +struct ValueHash +{ + std::size_t operator() (const T& value) const { + return hash_value(value); + } +}; + +template +struct ValuesEqual +{ + bool operator() (const T& a, const T& b) const { + return GfIsClose(a, b, 1e-9); + } +}; + +// This function condenses distinct indices that point to the same color values +// (the combination of RGB AND Alpha) to all point to the same index for that +// value. This will potentially shrink the data arrays. +static +void +_MergeEquivalentColorSetValues( + VtArray* colorSetRGBData, + VtArray* colorSetAlphaData, + VtArray* colorSetAssignmentIndices) { - std::vector valueOnVertex; - std::vector valueOnFace; - VtArray vertexValue; - VtArray faceValue; - - bool isConstant=true; - bool isUniform=true; - bool isVertex=true; - int numVertices = m.numVertices(); - int numPolygons = m.numPolygons(); - valueOnVertex.resize(numVertices, false); - valueOnFace.resize(numPolygons, false); - vertexValue.resize(numVertices); - faceValue.resize(numPolygons); - - MItMeshFaceVertex itFV( m.object() ); - int fvi=0; - for( itFV.reset(); !itFV.isDone(); itFV.next() ) { - int faceId=itFV.faceId(); - int vertId=itFV.vertId(); - // Validate if constant by checking against the first element - if (isConstant && fvi>0) { - if (not GfIsClose((*data)[0], (*data)[fvi], 1e-9)) { - isConstant=false; + if (not colorSetRGBData or not colorSetAlphaData or not colorSetAssignmentIndices) { + return; + } + + const size_t numValues = colorSetRGBData->size(); + if (numValues == 0) { + return; + } + + if (colorSetAlphaData->size() != numValues) { + TF_CODING_ERROR("Unequal sizes for color (%zu) and alpha (%zu)", + colorSetRGBData->size(), colorSetAlphaData->size()); + } + + // We maintain a map of values (color AND alpha together) to those values' + // indices in our unique value arrays (color and alpha separate). + std::unordered_map, ValuesEqual > valuesSet; + VtArray uniqueColors; + VtArray uniqueAlphas; + VtArray uniqueIndices; + + for (size_t i = 0; i < colorSetAssignmentIndices->size(); ++i) { + int index = (*colorSetAssignmentIndices)[i]; + + if (index < 0 or static_cast(index) >= numValues) { + // This is an unassigned or otherwise unknown index, so just keep it. + uniqueIndices.push_back(index); + continue; + } + + const GfVec3f color = (*colorSetRGBData)[index]; + const float alpha = (*colorSetAlphaData)[index]; + const GfVec4f value(color[0], color[1], color[2], alpha); + + int uniqueIndex = -1; + + auto inserted = valuesSet.insert( + std::pair(value, + uniqueColors.size())); + if (inserted.second) { + // This is a new value, so add it to the arrays. + uniqueColors.push_back(GfVec3f(value[0], value[1], value[2])); + uniqueAlphas.push_back(value[3]); + uniqueIndex = uniqueColors.size() - 1; + } else { + // This is an existing value, so re-use the original's index. + uniqueIndex = inserted.first->second; + } + + uniqueIndices.push_back(uniqueIndex); + } + + // If we reduced the number of values by merging, copy the results back. + if (uniqueColors.size() < numValues) { + (*colorSetRGBData) = uniqueColors; + (*colorSetAlphaData) = uniqueAlphas; + (*colorSetAssignmentIndices) = uniqueIndices; + } +} + +// This function tries to compress faceVarying primvar indices to uniform, +// vertex, or constant interpolation if possible. This will potentially shrink +// the indices array and will update the interpolation if any compression was +// possible. +static +void +_CompressFaceVaryingPrimvarIndices( + const MFnMesh& mesh, + TfToken *interpolation, + VtArray* assignmentIndices) +{ + if (not interpolation or + not assignmentIndices or + assignmentIndices->size() == 0) { + return; + } + + int numPolygons = mesh.numPolygons(); + VtArray uniformAssignments; + uniformAssignments.assign((size_t)numPolygons, -2); + + int numVertices = mesh.numVertices(); + VtArray vertexAssignments; + vertexAssignments.assign((size_t)numVertices, -2); + + // We assume that the data is constant/uniform/vertex until we can + // prove otherwise that two components have differing values. + bool isConstant = true; + bool isUniform = true; + bool isVertex = true; + + MItMeshFaceVertex itFV(mesh.object()); + unsigned int fvi = 0; + for (itFV.reset(); not itFV.isDone(); itFV.next(), ++fvi) { + int faceIndex = itFV.faceId(); + int vertexIndex = itFV.vertId(); + + int assignedIndex = (*assignmentIndices)[fvi]; + + if (isConstant) { + if (assignedIndex != (*assignmentIndices)[0]) { + isConstant = false; } } - // Validate if uniform by storing the first value on a given face - // and the if already stored, check if being a different value - // on the same face + if (isUniform) { - if (valueOnFace[faceId]) { - if (not GfIsClose(faceValue[faceId], - (*data)[fvi], 1e-9)) { - isUniform=false; - } - } else { - valueOnFace[faceId]=true; - faceValue[faceId]=(*data)[fvi]; + if (uniformAssignments[faceIndex] < -1) { + // No value for this face yet, so store one. + uniformAssignments[faceIndex] = assignedIndex; + } else if (assignedIndex != uniformAssignments[faceIndex]) { + isUniform = false; } } - // Validate if vertex by storing the first value on a given vertex - // and the if already stored, check if being a different value - // on the same vertex + if (isVertex) { - if (valueOnVertex[vertId]) { - if (not GfIsClose(vertexValue[vertId], - (*data)[fvi], 1e-9)) { - isVertex=false; - } - } else { - valueOnVertex[vertId]=true; - vertexValue[vertId]=(*data)[fvi]; + if (vertexAssignments[vertexIndex] < -1) { + // No value for this vertex yet, so store one. + vertexAssignments[vertexIndex] = assignedIndex; + } else if (assignedIndex != vertexAssignments[vertexIndex]) { + isVertex = false; } } - fvi++; + + if (not isConstant and not isUniform and not isVertex) { + // No compression will be possible, so stop trying. + break; + } } - + if (isConstant) { - data->resize(1); - *interpolation=UsdGeomTokens->constant; + assignmentIndices->resize(1); + *interpolation = UsdGeomTokens->constant; } else if (isUniform) { - *data=faceValue; - *interpolation=UsdGeomTokens->uniform; + *assignmentIndices = uniformAssignments; + *interpolation = UsdGeomTokens->uniform; } else if(isVertex) { - *data=vertexValue; - *interpolation=UsdGeomTokens->vertex; + *assignmentIndices = vertexAssignments; + *interpolation = UsdGeomTokens->vertex; } else { - *interpolation=UsdGeomTokens->faceVarying; + *interpolation = UsdGeomTokens->faceVarying; } } @@ -124,108 +210,188 @@ static inline GfVec3f _LinearColorFromColorSet( const MColor& mayaColor, - bool isDisplayColor) + bool shouldConvertToLinear) { // we assume all color sets except displayColor are in linear space. // if we got a color from colorSetData and we're a displayColor, we // need to convert it to linear. GfVec3f c(mayaColor[0], mayaColor[1], mayaColor[2]); - if (isDisplayColor) { + if (shouldConvertToLinear) { return GfConvertDisplayToLinear(c); } return c; } -// Collect values from the colorset -// If gathering for displayColor, set the unpainted values to -// the underlying shaders values, else set to 1,1,1,1 -// Values are gathered per "facevertex" but then the data -// is compressed to constant, uniform and vertex if possible -// RGB and Alpha data are compressed independently -// RGBA data is compressed as a single Vec4f array -// NOTE: We could only fill RGB and Alpha and then -// do a merge, compress and unmerge if RGBA is needed -// but for code simplicity we always fill the 3 arrays +/// Collect values from the color set named \p colorSet. +/// If \p isDisplayColor is true and this color set represents displayColor, +/// the unauthored/unpainted values in the color set will be filled in using +/// the shader values in \p shadersRGBData and \p shadersAlphaData if available. +/// Values are gathered per face vertex, but then the data is compressed to +/// vertex, uniform, or constant interpolation if possible. +/// Unauthored/unpainted values will be given the index -1. bool MayaMeshWriter::_GetMeshColorSetData( - MFnMesh& m, - MString colorSet, - bool isDisplayColor, - const VtArray& shadersRGBData, - const VtArray& shadersAlphaData, - VtArray *RGBData, TfToken *RGBInterp, - VtArray *RGBAData, TfToken *RGBAInterp, - VtArray *AlphaData, TfToken *AlphaInterp, - MFnMesh::MColorRepresentation *colorSetRep, - bool *clamped) + MFnMesh& mesh, + MString colorSet, + bool isDisplayColor, + const VtArray& shadersRGBData, + const VtArray& shadersAlphaData, + const VtArray& shadersAssignmentIndices, + VtArray* colorSetRGBData, + VtArray* colorSetAlphaData, + TfToken* interpolation, + VtArray* colorSetAssignmentIndices, + MFnMesh::MColorRepresentation* colorSetRep, + bool* clamped) { - // If there are no colors, return immediately as failure - if (m.numColors(colorSet)==0) { + // If there are no colors, return immediately as failure. + if (mesh.numColors(colorSet) == 0) { return false; } - - // Get ColorSet representation and clamping - *colorSetRep = m.getColorRepresentation(colorSet); - *clamped = m.isColorClamped(colorSet); - + MColorArray colorSetData; - const MColor unsetColor(-FLT_MAX,-FLT_MAX,-FLT_MAX,-FLT_MAX); - if (m.getFaceVertexColors (colorSetData, &colorSet, &unsetColor) - == MS::kFailure) { + const MColor unsetColor(-FLT_MAX, -FLT_MAX, -FLT_MAX, -FLT_MAX); + if (mesh.getFaceVertexColors(colorSetData, &colorSet, &unsetColor) + == MS::kFailure) { return false; } - // Resize the returning containers with FaceVertex amounts - RGBData->resize(colorSetData.length()); - AlphaData->resize(colorSetData.length()); - RGBAData->resize(colorSetData.length()); - - // Loop over every face vertex to populate colorArray - MItMeshFaceVertex itFV( m.object() ); - int fvi=0; - for( itFV.reset(); !itFV.isDone(); itFV.next() ) { - // Initialize RGBData and AlphaData to (1,1,1,1) and then - // if isDisplayColor from shader values (constant or uniform) - GfVec3f RGBValue=GfVec3f(1.0,1.0,1.0); - float AlphaValue=1; - - // NOTE, shadersRGBData is already linear - if (isDisplayColor && shadersRGBData.size() == static_cast(m.numPolygons())) { - RGBValue=shadersRGBData[itFV.faceId()]; - } else if (isDisplayColor && shadersRGBData.size()==1) { - RGBValue=shadersRGBData[0]; + if (colorSetData.length() == 0) { + return false; + } + + // Get the color set representation and clamping. + *colorSetRep = mesh.getColorRepresentation(colorSet); + *clamped = mesh.isColorClamped(colorSet); + + // We'll populate the assignment indices for every face vertex, but we'll + // only push values into the data if the face vertex has a value. All face + // vertices are initially unassigned/unauthored. + colorSetRGBData->clear(); + colorSetAlphaData->clear(); + colorSetAssignmentIndices->assign((size_t)colorSetData.length(), -1); + *interpolation = UsdGeomTokens->faceVarying; + + // Loop over every face vertex to populate the value arrays. + MItMeshFaceVertex itFV(mesh.object()); + unsigned int fvi = 0; + for (itFV.reset(); not itFV.isDone(); itFV.next(), ++fvi) { + // If this is a displayColor color set, we may need to fallback on the + // bound shader colors/alphas for this face in some cases. In + // particular, if the color set is alpha-only, we fallback on the + // shader values for the color. If the color set is RGB-only, we + // fallback on the shader values for alpha only. If there's no authored + // color for this face vertex, we use both the color AND alpha values + // from the shader. + bool useShaderColorFallback = false; + bool useShaderAlphaFallback = false; + if (isDisplayColor) { + if (colorSetData[fvi] == unsetColor) { + useShaderColorFallback = true; + useShaderAlphaFallback = true; + } else if (*colorSetRep == MFnMesh::kAlpha) { + // The color set does not provide color, so fallback on shaders. + useShaderColorFallback = true; + } else if (*colorSetRep == MFnMesh::kRGB) { + // The color set does not provide alpha, so fallback on shaders. + useShaderAlphaFallback = true; + } + } + + // If we're exporting displayColor and we use the value from the color + // set, we need to convert it to linear. + bool convertDisplayColorToLinear = isDisplayColor; + + // Shader values for the mesh could be constant + // (shadersAssignmentIndices is empty) or uniform. + int faceIndex = itFV.faceId(); + if (useShaderColorFallback) { + // There was no color value in the color set to use, so we use the + // shader color, or the default color if there is no shader color. + // This color will already be in linear space, so don't convert it + // again. + convertDisplayColorToLinear = false; + + int valueIndex = -1; + if (shadersAssignmentIndices.empty()) { + if (shadersRGBData.size() == 1) { + valueIndex = 0; + } + } else if (faceIndex >= 0 and + static_cast(faceIndex) < shadersAssignmentIndices.size()) { + + int tmpIndex = shadersAssignmentIndices[faceIndex]; + if (tmpIndex >= 0 and + static_cast(tmpIndex) < shadersRGBData.size()) { + valueIndex = tmpIndex; + } + } + if (valueIndex >= 0) { + colorSetData[fvi][0] = shadersRGBData[valueIndex][0]; + colorSetData[fvi][1] = shadersRGBData[valueIndex][1]; + colorSetData[fvi][2] = shadersRGBData[valueIndex][2]; + } else { + // No shader color to fallback on. Use the default shader color. + colorSetData[fvi][0] = _ShaderDefaultRGB[0]; + colorSetData[fvi][1] = _ShaderDefaultRGB[1]; + colorSetData[fvi][2] = _ShaderDefaultRGB[2]; + } } - if (isDisplayColor && shadersAlphaData.size() == static_cast(m.numPolygons())) { - AlphaValue=shadersAlphaData[itFV.faceId()]; - } else if (isDisplayColor && shadersAlphaData.size()==1) { - AlphaValue=shadersAlphaData[0]; + if (useShaderAlphaFallback) { + int valueIndex = -1; + if (shadersAssignmentIndices.empty()) { + if (shadersAlphaData.size() == 1) { + valueIndex = 0; + } + } else if (faceIndex >= 0 and + static_cast(faceIndex) < shadersAssignmentIndices.size()) { + int tmpIndex = shadersAssignmentIndices[faceIndex]; + if (tmpIndex >= 0 and + static_cast(tmpIndex) < shadersAlphaData.size()) { + valueIndex = tmpIndex; + } + } + if (valueIndex >= 0) { + colorSetData[fvi][3] = shadersAlphaData[valueIndex]; + } else { + // No shader alpha to fallback on. Use the default shader alpha. + colorSetData[fvi][3] = _ShaderDefaultAlpha; + } } - // Assign retrieved color set values - // unauthored color set values are ==unsetColor - // for those we use the previously initialized values - if (colorSetData[fvi]!=unsetColor) { - if ((*colorSetRep) == MFnMesh::kAlpha) { - AlphaValue=colorSetData[fvi][3]; - } else if ((*colorSetRep) == MFnMesh::kRGB) { - RGBValue=_LinearColorFromColorSet(colorSetData[fvi], isDisplayColor); - AlphaValue=1; - } else if ((*colorSetRep) == MFnMesh::kRGBA) { - RGBValue=_LinearColorFromColorSet(colorSetData[fvi], isDisplayColor); - AlphaValue=colorSetData[fvi][3]; + + // If we have a color/alpha value, add it to the data to be returned. + if (colorSetData[fvi] != unsetColor) { + GfVec3f rgbValue = _ColorSetDefaultRGB; + float alphaValue = _ColorSetDefaultAlpha; + + if (useShaderColorFallback or + (*colorSetRep == MFnMesh::kRGB) or + (*colorSetRep == MFnMesh::kRGBA)) { + rgbValue = _LinearColorFromColorSet(colorSetData[fvi], + convertDisplayColorToLinear); } + if (useShaderAlphaFallback or + (*colorSetRep == MFnMesh::kAlpha) or + (*colorSetRep == MFnMesh::kRGBA)) { + alphaValue = colorSetData[fvi][3]; + } + + colorSetRGBData->push_back(rgbValue); + colorSetAlphaData->push_back(alphaValue); + (*colorSetAssignmentIndices)[fvi] = colorSetRGBData->size() - 1; } - (*RGBData)[fvi]=RGBValue; - (*AlphaData)[fvi]=AlphaValue; - (*RGBAData)[fvi]=GfVec4f(RGBValue[0], RGBValue[1], - RGBValue[2], AlphaValue); - fvi++; - } - compressFVPrimvar(m, RGBData, RGBInterp); - compressFVPrimvar(m, AlphaData, AlphaInterp); - compressFVPrimvar(m, RGBAData, RGBAInterp); + } + + _MergeEquivalentColorSetValues(colorSetRGBData, + colorSetAlphaData, + colorSetAssignmentIndices); + _CompressFaceVaryingPrimvarIndices(mesh, + interpolation, + colorSetAssignmentIndices); + return true; } -// We assumed that primvars in USD are always unclamped so we add the +// We assumed that primvars in USD are always unclamped so we add the // clamped custom data ONLY when clamping is set to true in the colorset static void SetPVCustomData(UsdAttribute obj, bool clamped) { @@ -236,107 +402,189 @@ static void SetPVCustomData(UsdAttribute obj, bool clamped) bool MayaMeshWriter::_createAlphaPrimVar( - UsdGeomGprim &primSchema, const TfToken name, - const VtArray& data, TfToken interpolation, - bool clamped) + UsdGeomGprim &primSchema, + const TfToken& name, + const VtArray& data, + const TfToken& interpolation, + const VtArray& assignmentIndices, + const int unassignedValueIndex, + bool clamped) { - unsigned int numValues=data.size(); - if (numValues==0) return false; - TfToken interp=interpolation; - if (numValues==1 && interp==UsdGeomTokens->constant) { - interp=TfToken(); - } - UsdGeomPrimvar colorSet = primSchema.CreatePrimvar(name, - SdfValueTypeNames->FloatArray, - interp ); - colorSet.Set(data); - SetPVCustomData(colorSet.GetAttr(), clamped); + unsigned int numValues = data.size(); + if (numValues == 0) { + return false; + } + + TfToken interp = interpolation; + if (numValues == 1 and interp == UsdGeomTokens->constant) { + interp = TfToken(); + } + + UsdGeomPrimvar primVar = + primSchema.CreatePrimvar(name, + SdfValueTypeNames->FloatArray, + interp); + + primVar.Set(data); + + if (not assignmentIndices.empty()) { + primVar.SetIndices(assignmentIndices); + if (unassignedValueIndex != primVar.GetUnauthoredValuesIndex()) { + primVar.SetUnauthoredValuesIndex(unassignedValueIndex); + } + } + + SetPVCustomData(primVar.GetAttr(), clamped); + return true; } bool MayaMeshWriter::_createRGBPrimVar( - UsdGeomGprim &primSchema, const TfToken name, - const VtArray& data, TfToken interpolation, - bool clamped) + UsdGeomGprim &primSchema, + const TfToken& name, + const VtArray& data, + const TfToken& interpolation, + const VtArray& assignmentIndices, + const int unassignedValueIndex, + bool clamped) { - unsigned int numValues=data.size(); - if (numValues==0) return false; - TfToken interp=interpolation; - if (numValues==1 && interp==UsdGeomTokens->constant) { - interp=TfToken(); - } - UsdGeomPrimvar colorSet = primSchema.CreatePrimvar(name, - SdfValueTypeNames->Color3fArray, - interp ); - colorSet.Set(data); - SetPVCustomData(colorSet.GetAttr(), clamped); + unsigned int numValues = data.size(); + if (numValues == 0) { + return false; + } + + TfToken interp = interpolation; + if (numValues == 1 and interp == UsdGeomTokens->constant) { + interp = TfToken(); + } + + UsdGeomPrimvar primVar = + primSchema.CreatePrimvar(name, + SdfValueTypeNames->Color3fArray, + interp); + + primVar.Set(data); + + if (not assignmentIndices.empty()) { + primVar.SetIndices(assignmentIndices); + if (unassignedValueIndex != primVar.GetUnauthoredValuesIndex()) { + primVar.SetUnauthoredValuesIndex(unassignedValueIndex); + } + } + + SetPVCustomData(primVar.GetAttr(), clamped); + return true; } bool MayaMeshWriter::_createRGBAPrimVar( - UsdGeomGprim &primSchema, const TfToken name, - const VtArray& RGBAData, TfToken RGBAInterp, - bool clamped) + UsdGeomGprim &primSchema, + const TfToken& name, + const VtArray& rgbData, + const VtArray& alphaData, + const TfToken& interpolation, + const VtArray& assignmentIndices, + const int unassignedValueIndex, + bool clamped) { - unsigned int numValues=RGBAData.size(); - if (numValues==0) return false; - TfToken interp=RGBAInterp; - if (numValues==1 && interp==UsdGeomTokens->constant) { - interp=TfToken(); - } - UsdGeomPrimvar colorSet = primSchema.CreatePrimvar(name, - SdfValueTypeNames->Float4Array, - interp ); - colorSet.Set(RGBAData); - SetPVCustomData(colorSet.GetAttr(), clamped); + unsigned int numValues = rgbData.size(); + if (numValues == 0 or numValues != alphaData.size()) { + return false; + } + + TfToken interp = interpolation; + if (numValues == 1 and interp == UsdGeomTokens->constant) { + interp = TfToken(); + } + + UsdGeomPrimvar primVar = + primSchema.CreatePrimvar(name, + SdfValueTypeNames->Color4fArray, + interp); + + VtArray rgbaData(numValues); + for (size_t i = 0; i < rgbaData.size(); ++i) { + rgbaData[i] = GfVec4f(rgbData[i][0], rgbData[i][1], rgbData[i][2], + alphaData[i]); + } + + primVar.Set(rgbaData); + + if (not assignmentIndices.empty()) { + primVar.SetIndices(assignmentIndices); + if (unassignedValueIndex != primVar.GetUnauthoredValuesIndex()) { + primVar.SetUnauthoredValuesIndex(unassignedValueIndex); + } + } + + SetPVCustomData(primVar.GetAttr(), clamped); + return true; } -bool MayaMeshWriter::_setDisplayPrimVar( - UsdGeomGprim &primSchema, - MFnMesh::MColorRepresentation colorRep, - VtArray RGBData, TfToken RGBInterp, - VtArray AlphaData, TfToken AlphaInterp, - bool clamped, bool authored) +bool MayaMeshWriter::_addDisplayPrimvars( + UsdGeomGprim &primSchema, + const MFnMesh::MColorRepresentation colorRep, + const VtArray& RGBData, + const VtArray& AlphaData, + const TfToken& interpolation, + const VtArray& assignmentIndices, + const int unassignedValueIndex, + const bool clamped, + const bool authored) { - + // If we already have an authored value, don't try to write a new one. UsdAttribute colorAttr = primSchema.GetDisplayColorAttr(); if (not colorAttr.HasAuthoredValueOpinion() and not RGBData.empty()) { UsdGeomPrimvar displayColor = primSchema.GetDisplayColorPrimvar(); - if (RGBInterp != displayColor.GetInterpolation()) - displayColor.SetInterpolation(RGBInterp); + if (interpolation != displayColor.GetInterpolation()) { + displayColor.SetInterpolation(interpolation); + } displayColor.Set(RGBData); - bool authRGB=authored; - if (colorRep == MFnMesh::kAlpha) { authRGB=false; } + if (not assignmentIndices.empty()) { + displayColor.SetIndices(assignmentIndices); + if (unassignedValueIndex != displayColor.GetUnauthoredValuesIndex()) { + displayColor.SetUnauthoredValuesIndex(unassignedValueIndex); + } + } + bool authRGB = authored; + if (colorRep == MFnMesh::kAlpha) { + authRGB = false; + } if (authRGB) { colorAttr.SetCustomDataByKey(TfToken("Authored"), VtValue(authRGB)); SetPVCustomData(colorAttr, clamped); } } - - UsdAttribute alphaAttr = primSchema.GetDisplayOpacityAttr(); - // if we already have an authored value, don't try to write a new one. - if (not alphaAttr.HasAuthoredValueOpinion()) { - - if (not AlphaData.empty()) { - // we consider a single alpha value that is 1.0 to be the "default" - // value. We only want to write values that are not the "default". - bool hasDefaultAlpha = AlphaData.size() == 1 and GfIsClose(AlphaData[0], 1.0, 1e-9); - if (not hasDefaultAlpha) { - UsdGeomPrimvar displayOpacity = primSchema.GetDisplayOpacityPrimvar(); - if (AlphaInterp != displayOpacity.GetInterpolation()) - displayOpacity.SetInterpolation(AlphaInterp); - displayOpacity.Set(AlphaData); - bool authAlpha=authored; - if (colorRep == MFnMesh::kRGB) { authAlpha=false; } - if (authAlpha) { - alphaAttr.SetCustomDataByKey(TfToken("Authored"), VtValue(authAlpha)); - SetPVCustomData(alphaAttr, clamped); + UsdAttribute alphaAttr = primSchema.GetDisplayOpacityAttr(); + if (not alphaAttr.HasAuthoredValueOpinion() and not AlphaData.empty()) { + // we consider a single alpha value that is 1.0 to be the "default" + // value. We only want to write values that are not the "default". + bool hasDefaultAlpha = AlphaData.size() == 1 and GfIsClose(AlphaData[0], 1.0, 1e-9); + if (not hasDefaultAlpha) { + UsdGeomPrimvar displayOpacity = primSchema.GetDisplayOpacityPrimvar(); + if (interpolation != displayOpacity.GetInterpolation()) { + displayOpacity.SetInterpolation(interpolation); + } + displayOpacity.Set(AlphaData); + if (not assignmentIndices.empty()) { + displayOpacity.SetIndices(assignmentIndices); + if (unassignedValueIndex != displayOpacity.GetUnauthoredValuesIndex()) { + displayOpacity.SetUnauthoredValuesIndex(unassignedValueIndex); } } + bool authAlpha = authored; + if (colorRep == MFnMesh::kRGB) { + authAlpha = false; + } + if (authAlpha) { + alphaAttr.SetCustomDataByKey(TfToken("Authored"), VtValue(authAlpha)); + SetPVCustomData(alphaAttr, clamped); + } } } + return true; } diff --git a/third_party/maya/lib/usdMaya/MayaNurbsSurfaceWriter.cpp b/third_party/maya/lib/usdMaya/MayaNurbsSurfaceWriter.cpp index 0545375ec4..0433bd9943 100644 --- a/third_party/maya/lib/usdMaya/MayaNurbsSurfaceWriter.cpp +++ b/third_party/maya/lib/usdMaya/MayaNurbsSurfaceWriter.cpp @@ -89,24 +89,34 @@ bool MayaNurbsSurfaceWriter::writeNurbsSurfaceAttrs( // shader assignment possible. if (getArgs().exportDisplayColor) { VtArray RGBData; - TfToken RGBInterp; VtArray AlphaData; - TfToken AlphaInterp; - if (PxrUsdMayaUtil::GetLinearShaderColor(nurbs, 0, - &RGBData, &RGBInterp, - &AlphaData, &AlphaInterp)) { + TfToken interpolation; + VtArray assignmentIndices; + if (PxrUsdMayaUtil::GetLinearShaderColor(nurbs, + &RGBData, + &AlphaData, + &interpolation, + &assignmentIndices)) { if (RGBData.size()>0) { UsdGeomPrimvar dispColor = primSchema.GetDisplayColorPrimvar(); - if (RGBInterp != dispColor.GetInterpolation()) - dispColor.SetInterpolation(RGBInterp); + if (interpolation != dispColor.GetInterpolation()) { + dispColor.SetInterpolation(interpolation); + } dispColor.Set(RGBData); + if (not assignmentIndices.empty()) { + dispColor.SetIndices(assignmentIndices); + } } if (AlphaData.size() > 0 && GfIsClose(AlphaData[0], 1.0, 1e-9)==false) { UsdGeomPrimvar dispOpacity = primSchema.GetDisplayOpacityPrimvar(); - if (AlphaInterp != dispOpacity.GetInterpolation()) - dispOpacity.SetInterpolation(AlphaInterp); + if (interpolation != dispOpacity.GetInterpolation()) { + dispOpacity.SetInterpolation(interpolation); + } dispOpacity.Set(AlphaData); + if (not assignmentIndices.empty()) { + dispOpacity.SetIndices(assignmentIndices); + } } } } diff --git a/third_party/maya/lib/usdMaya/proxyShape.cpp b/third_party/maya/lib/usdMaya/proxyShape.cpp index b5969e3b11..c831e9ce33 100644 --- a/third_party/maya/lib/usdMaya/proxyShape.cpp +++ b/third_party/maya/lib/usdMaya/proxyShape.cpp @@ -310,6 +310,18 @@ UsdMayaProxyShape::initialize( retValue = addAttribute(psData->displayRenderGuides); CHECK_MSTATUS_AND_RETURN_IT(retValue); + psData->softSelectable = numericAttrFn.create( + "softSelectable", + "softSelectable", + MFnNumericData::kBoolean, + 0.0, + &retValue); + numericAttrFn.setKeyable(false); + numericAttrFn.setStorable(false); + numericAttrFn.setAffectsAppearance(true); + retValue = addAttribute(psData->softSelectable); + CHECK_MSTATUS_AND_RETURN_IT(retValue); + // // add attribute dependencies // @@ -907,3 +919,28 @@ UsdMayaProxyShape::~UsdMayaProxyShape() // } +MSelectionMask +UsdMayaProxyShape::getShapeSelectionMask() const +{ + if (_CanBeSoftSelected()) { + // to support soft selection (mode=Object), we need to add kSelectMeshes + // to our selection mask. + MSelectionMask::SelectionType selType = MSelectionMask::kSelectMeshes; + return MSelectionMask(selType); + } + return MPxSurfaceShape::getShapeSelectionMask(); +} + +bool +UsdMayaProxyShape::_CanBeSoftSelected() const +{ + UsdMayaProxyShape* nonConstThis = const_cast(this); + MDataBlock dataBlock = nonConstThis->forceCache(); + MStatus status; + MDataHandle softSelHandle = dataBlock.inputValue(_psData.softSelectable, &status); + if (not status) { + return false; + } + return softSelHandle.asBool(); + +} diff --git a/third_party/maya/lib/usdMaya/proxyShape.h b/third_party/maya/lib/usdMaya/proxyShape.h index ae83b4e5cc..424dae6825 100644 --- a/third_party/maya/lib/usdMaya/proxyShape.h +++ b/third_party/maya/lib/usdMaya/proxyShape.h @@ -73,6 +73,8 @@ class USDMAYA_API UsdMayaProxyShape : public MPxSurfaceShape, MObject displayGuides; MObject displayRenderGuides; + MObject softSelectable; + // this will not change once constructed. const MTypeId typeId; const MString typeName; @@ -95,12 +97,13 @@ class USDMAYA_API UsdMayaProxyShape : public MPxSurfaceShape, PluginStaticData* psData); // Virtual function overrides - virtual void postConstructor(); + virtual void postConstructor() override; virtual MStatus compute( const MPlug& plug, - MDataBlock& dataBlock); - virtual bool isBounded() const; - virtual MBoundingBox boundingBox() const; + MDataBlock& dataBlock) override; + virtual bool isBounded() const override; + virtual MBoundingBox boundingBox() const override; + virtual MSelectionMask getShapeSelectionMask() const override; // PxrUsdMayaUsdPrimProvider overrides: UsdPrim usdPrim() const override; @@ -166,6 +169,8 @@ class USDMAYA_API UsdMayaProxyShape : public MPxSurfaceShape, bool _GetDisplayRenderGuides( MDataBlock dataBlock ) const; bool _GetTint( MDataBlock dataBlock, GfVec4f *outTintColor ) const; + bool _CanBeSoftSelected() const; + std::map _boundingBoxCache; bool _useFastPlayback; diff --git a/third_party/maya/lib/usdMaya/referenceAssembly.cpp b/third_party/maya/lib/usdMaya/referenceAssembly.cpp index 211471ff7e..e5a669ec30 100644 --- a/third_party/maya/lib/usdMaya/referenceAssembly.cpp +++ b/third_party/maya/lib/usdMaya/referenceAssembly.cpp @@ -984,6 +984,8 @@ bool UsdMayaRepresentationProxyBase::activate() _OverrideProxyPlugs(shapeFn, dgMod); + dgMod.newPlugValueBool(shapeFn.findPlug(_psData.proxyShape.softSelectable, true), _proxyIsSoftSelectable); + dgMod.doIt(); _PushEditsToProxy(); diff --git a/third_party/maya/lib/usdMaya/referenceAssembly.h b/third_party/maya/lib/usdMaya/referenceAssembly.h index c1b74197fc..10d200e53d 100644 --- a/third_party/maya/lib/usdMaya/referenceAssembly.h +++ b/third_party/maya/lib/usdMaya/referenceAssembly.h @@ -257,8 +257,10 @@ class UsdMayaRepresentationBase : public MPxRepresentation class UsdMayaRepresentationProxyBase : public UsdMayaRepresentationBase { public: - UsdMayaRepresentationProxyBase(MPxAssembly *assembly, const MString &name) : - UsdMayaRepresentationBase(assembly, name) {}; + UsdMayaRepresentationProxyBase(MPxAssembly *assembly, const MString &name, + bool proxyIsSoftSelectable) : + UsdMayaRepresentationBase(assembly, name), + _proxyIsSoftSelectable(proxyIsSoftSelectable) {}; virtual bool activate(); virtual bool inactivate(); @@ -272,6 +274,7 @@ class UsdMayaRepresentationProxyBase : public UsdMayaRepresentationBase private: SdfLayerRefPtr _sessionSublayer; + bool _proxyIsSoftSelectable; }; // =========================================================== @@ -287,7 +290,11 @@ class UsdMayaRepresentationCollapsed : public UsdMayaRepresentationProxyBase // == Overrides for MPxRepresentation == UsdMayaRepresentationCollapsed(MPxAssembly *assembly, const MString &name) : - UsdMayaRepresentationProxyBase(assembly, name) {}; + + // We only support soft selection on "collapsed" proxies. While we may + // want to move proxies that are not root of the model, we suspect this + // is more likely to lead to undesired behavior. + UsdMayaRepresentationProxyBase(assembly, name, true) {}; virtual MString getType () const { return UsdMayaRepresentationCollapsed::_assemblyType; }; @@ -309,7 +316,7 @@ class UsdMayaRepresentationPlayback : public UsdMayaRepresentationProxyBase // == Overrides for MPxRepresentation == UsdMayaRepresentationPlayback(MPxAssembly *assembly, const MString &name) : - UsdMayaRepresentationProxyBase(assembly, name) {}; + UsdMayaRepresentationProxyBase(assembly, name, false) {}; virtual MString getType () const { return UsdMayaRepresentationPlayback::_assemblyType; }; diff --git a/third_party/maya/lib/usdMaya/util.cpp b/third_party/maya/lib/usdMaya/util.cpp index 0f6ab04560..b19ace60a4 100644 --- a/third_party/maya/lib/usdMaya/util.cpp +++ b/third_party/maya/lib/usdMaya/util.cpp @@ -24,20 +24,23 @@ #include "usdMaya/util.h" #include "pxr/base/gf/gamma.h" +#include "pxr/base/tf/hashmap.h" #include "pxr/usd/usdGeom/mesh.h" +#include +#include +#include #include +#include #include #include +#include +#include #include -#include -#include +#include #include #include -#include -#include -#include -#include + // return seconds per frame double PxrUsdMayaUtil::spf() @@ -435,47 +438,82 @@ std::string PxrUsdMayaUtil::SanitizeColorSetName(const std::string& name) return name.substr(namePos); } -// Get array (constant or per face) of attached shaders -// Pass numFaces==0 if retrieving shaders on a non polymesh -static bool +// Get array (constant or per component) of attached shaders +// Pass a non-zero value for numComponents when retrieving shaders on an object +// that supports per-component shader assignment (e.g. faces of a polymesh). +// In this case, shaderObjs will be the length of the number of shaders +// assigned to the object. assignmentIndices will be the length of +// numComponents, with values indexing into shaderObjs. +// When numComponents is zero, shaderObjs will be of length 1 and +// assignmentIndices will be empty. +static +bool _getAttachedMayaShaderObjects( - const MFnDagNode &node, const int numFaces, MObjectArray *shaderObjs) + const MFnDagNode &node, + const unsigned int numComponents, + MObjectArray *shaderObjs, + VtArray *assignmentIndices) { bool hasShader=false; MStatus status; - MObjectArray sgObjs; + + // This structure maps shader object names to their indices in the + // shaderObjs array. We use this to make sure that we add each unique + // shader to shaderObjs only once. + TfHashMap shaderPlugsMap; + + shaderObjs->clear(); + assignmentIndices->clear(); + + MObjectArray setObjs; MObjectArray compObjs; - node.getConnectedSetsAndMembers(0, sgObjs, compObjs, true); // Assuming that not using instancing - // If we have one shader connected we return a single shader - // If there are multiple shaders, we return an per face array of connected shaders - if (sgObjs.length()==1 or numFaces==0) { - shaderObjs->setLength(1); - } else if (sgObjs.length()>1) { - shaderObjs->setLength(numFaces); - } - for (unsigned int i=0; i < sgObjs.length(); ++i) { + node.getConnectedSetsAndMembers(0, setObjs, compObjs, true); // Assuming that not using instancing + + // If we have multiple components and either multiple sets or one set with + // only a subset of the object in it, we'll keep track of the assignments + // for all components in assignmentIndices. We initialize all of the + // assignments as unassigned using a value of -1. + if (numComponents > 1 and + (setObjs.length() > 1 or + (setObjs.length() == 1 and not compObjs[0].isNull()))) { + assignmentIndices->assign((size_t)numComponents, -1); + } + + for (unsigned int i=0; i < setObjs.length(); ++i) { // Get associated Set and Shading Group - MFnSet setFn( sgObjs[i], &status ); + MFnSet setFn(setObjs[i], &status); MPlug seSurfaceShaderPlg = setFn.findPlug("surfaceShader", &status); // Find connection shader->shadingGroup MPlugArray plgCons; seSurfaceShaderPlg.connectedTo(plgCons, true, false, &status); - MObject shaderObj; - if ( plgCons.length() > 0 ) { - hasShader = true; - shaderObj = plgCons[0].node(); - } - // If we have multiple shaders, we assign them per face - if (sgObjs.length()>1 and numFaces>0) { - MItMeshPolygon faceIt( node.dagPath(), compObjs[i] ); - for ( faceIt.reset() ; !faceIt.isDone() ; faceIt.next() ){ - (*shaderObjs)[faceIt.index()]=shaderObj; + if (plgCons.length() == 0) { + continue; + } + + hasShader = true; + MPlug shaderPlug = plgCons[0]; + MObject shaderObj = shaderPlug.node(); + + auto inserted = shaderPlugsMap.insert( + std::pair(shaderPlug.name().asChar(), + shaderObjs->length())); + if (inserted.second) { + shaderObjs->append(shaderObj); + } + + // If we are tracking per-component assignments, mark all components of + // this set as assigned to this shader. + if (not assignmentIndices->empty()) { + size_t shaderIndex = inserted.first->second; + + MItMeshPolygon faceIt(node.dagPath(), compObjs[i]); + for (faceIt.reset(); not faceIt.isDone(); faceIt.next()) { + (*assignmentIndices)[faceIt.index()] = shaderIndex; } - } else { - (*shaderObjs)[0]=shaderObj; } } + return hasShader; } @@ -546,99 +584,168 @@ _GetColorAndTransparencyFromDepNode( } static void -_getMayaShadersColor(const int numFaces, const MObjectArray &shaderObjs, - VtArray *RGBData, TfToken *RGBInterp, - VtArray *AlphaData, TfToken *AlphaInterp) +_getMayaShadersColor( + const MObjectArray &shaderObjs, + VtArray *RGBData, + VtArray *AlphaData) { MStatus status; - bool constantRGB=true; - bool constantAlpha=true; - if (RGBData) RGBData->resize(shaderObjs.length()); - if (AlphaData) AlphaData->resize(shaderObjs.length()); - for (unsigned int i=0; i < shaderObjs.length(); ++i) { + + if (shaderObjs.length() == 0) { + return; + } + + if (RGBData) { + RGBData->resize(shaderObjs.length()); + } + if (AlphaData) { + AlphaData->resize(shaderObjs.length()); + } + + for (unsigned int i = 0; i < shaderObjs.length(); ++i) { // Initialize RGB and Alpha to (1,1,1,1) if (RGBData) { (*RGBData)[i][0] = 1.0; (*RGBData)[i][1] = 1.0; (*RGBData)[i][2] = 1.0; } - if (AlphaData) { (*AlphaData)[i] = 1.0; } - if (!shaderObjs[i].isNull()) { - - // first, we assume the shader is a lambert and try that API. if - // not, we try our next best guess. - bool gotValues = _GetColorAndTransparencyFromLambert( - shaderObjs[i], - RGBData ? &(*RGBData)[i] : NULL, - AlphaData ? &(*AlphaData)[i] : NULL) - - or _GetColorAndTransparencyFromDepNode( - shaderObjs[i], - RGBData ? &(*RGBData)[i] : NULL, - AlphaData ? &(*AlphaData)[i] : NULL); - - if (gotValues) { - if (RGBData) { - for (int j = 0; j<3; j++) { - if (GfIsClose((*RGBData)[0][j], - (*RGBData)[i][j], 1e-9)==false) { - constantRGB=false; - } - } - } - if (AlphaData) { - if (GfIsClose((*AlphaData)[0], (*AlphaData)[i], 1e-9)==false) { - constantAlpha=false; - } - } - } - else { - MGlobal::displayError("Failed to get shaders colors at index: " + - MString(TfStringPrintf("%d", i).c_str()) + - ". Unable to retrieve ShaderBaseColor."); - } - } else { - MGlobal::displayError("Invalid Maya Shader Object at index: " + - MString(TfStringPrintf("%d", i).c_str()) + - ". Unable to retrieve ShaderBaseColor."); + if (AlphaData) { + (*AlphaData)[i] = 1.0; } - } - // If RGB or Alpha are constant, resize the array to 1 - if (RGBData) { - if (constantRGB) { - RGBData->resize(1); - *RGBInterp=UsdGeomTokens->constant; - } else if (RGBData->size() == static_cast(numFaces)) { - *RGBInterp=UsdGeomTokens->uniform; + + if (shaderObjs[i].isNull()) { + MGlobal::displayError("Invalid Maya Shader Object at index: " + + MString(TfStringPrintf("%d", i).c_str()) + + ". Unable to retrieve ShaderBaseColor."); + continue; } - } - if (AlphaData) { - if (constantAlpha) { - AlphaData->resize(1); - *AlphaInterp=UsdGeomTokens->constant; - } else if (AlphaData->size() == static_cast(numFaces)) { - *AlphaInterp=UsdGeomTokens->uniform; + + // first, we assume the shader is a lambert and try that API. if + // not, we try our next best guess. + bool gotValues = _GetColorAndTransparencyFromLambert( + shaderObjs[i], + RGBData ? &(*RGBData)[i] : NULL, + AlphaData ? &(*AlphaData)[i] : NULL) + + or _GetColorAndTransparencyFromDepNode( + shaderObjs[i], + RGBData ? &(*RGBData)[i] : NULL, + AlphaData ? &(*AlphaData)[i] : NULL); + + if (not gotValues) { + MGlobal::displayError("Failed to get shaders colors at index: " + + MString(TfStringPrintf("%d", i).c_str()) + + ". Unable to retrieve ShaderBaseColor."); } } } +static bool -PxrUsdMayaUtil::GetLinearShaderColor( +_GetLinearShaderColor( const MFnDagNode& node, - const int numFaces, - VtArray *RGBData, TfToken *RGBInterp, - VtArray *AlphaData, TfToken *AlphaInterp) + const unsigned int numComponents, + VtArray *RGBData, + VtArray *AlphaData, + TfToken *interpolation, + VtArray *assignmentIndices) { MObjectArray shaderObjs; - if (_getAttachedMayaShaderObjects(node, numFaces, &shaderObjs)) { - _getMayaShadersColor(numFaces, shaderObjs, - RGBData, RGBInterp, - AlphaData, AlphaInterp); + if (_getAttachedMayaShaderObjects(node, numComponents, &shaderObjs, assignmentIndices)) { + if (assignmentIndices and interpolation) { + if (assignmentIndices->empty()) { + *interpolation = UsdGeomTokens->constant; + } else { + *interpolation = UsdGeomTokens->uniform; + } + } + + _getMayaShadersColor(shaderObjs, RGBData, AlphaData); + return true; } + return false; } +bool +PxrUsdMayaUtil::GetLinearShaderColor( + const MFnDagNode& node, + VtArray *RGBData, + VtArray *AlphaData, + TfToken *interpolation, + VtArray *assignmentIndices) +{ + return _GetLinearShaderColor(node, + 0, + RGBData, + AlphaData, + interpolation, + assignmentIndices); +} + +bool +PxrUsdMayaUtil::GetLinearShaderColor( + const MFnMesh& mesh, + VtArray *RGBData, + VtArray *AlphaData, + TfToken *interpolation, + VtArray *assignmentIndices) +{ + unsigned int numComponents = mesh.numPolygons(); + return _GetLinearShaderColor(mesh, + numComponents, + RGBData, + AlphaData, + interpolation, + assignmentIndices); +} + +bool +PxrUsdMayaUtil::AddUnassignedColorAndAlphaIfNeeded( + VtArray* RGBData, + VtArray* AlphaData, + VtArray* assignmentIndices, + int* unassignedValueIndex, + const GfVec3f& defaultRGB, + const float defaultAlpha) +{ + if (not assignmentIndices or assignmentIndices->empty()) { + return false; + } + + if (RGBData and AlphaData and (RGBData->size() != AlphaData->size())) { + TF_CODING_ERROR("Unequal sizes for color (%zu) and opacity (%zu)", + RGBData->size(), AlphaData->size()); + } + + *unassignedValueIndex = -1; + + for (size_t i=0; i < assignmentIndices->size(); ++i) { + if ((*assignmentIndices)[i] >= 0) { + // This component has an assignment, so skip it. + continue; + } + + // We found an unassigned index. Add unassigned values to RGBData and + // AlphaData if we haven't already. + if (*unassignedValueIndex < 0) { + if (RGBData) { + RGBData->push_back(defaultRGB); + } + if (AlphaData) { + AlphaData->push_back(defaultAlpha); + } + *unassignedValueIndex = RGBData->size() - 1; + } + + // Assign the component the unassigned value index. + (*assignmentIndices)[i] = *unassignedValueIndex; + } + + return true; +} + MPlug PxrUsdMayaUtil::GetConnected(const MPlug& plug) { diff --git a/third_party/maya/lib/usdMaya/util.h b/third_party/maya/lib/usdMaya/util.h index e75cbf2a17..eef55e3d4b 100644 --- a/third_party/maya/lib/usdMaya/util.h +++ b/third_party/maya/lib/usdMaya/util.h @@ -29,16 +29,12 @@ #include "pxr/usd/usd/timeCode.h" #include -#include #include +#include +#include #include #include -#include -#include -#include -#include -class MFnDependencyNode; namespace PxrUsdMayaUtil { @@ -154,14 +150,52 @@ std::string SanitizeName(const std::string& name); // This to allow various pipeline to sanitize the colorset name for output std::string SanitizeColorSetName(const std::string& name); -// Get the basecolor from the bound shader. Returned colors will be in linear -// color space. +/// Get the base colors and opacities from the shader(s) bound to \p node. +/// Returned colors will be in linear color space. +/// +/// A single value for each of color and alpha will be returned, +/// interpolation will be constant, and assignmentIndices will be empty. +/// bool GetLinearShaderColor( const MFnDagNode& node, - const int numFaces, - VtArray *RGBData, TfToken *RGBInterp, - VtArray *AlphaData, TfToken *AlphaInterp); + VtArray *RGBData, + VtArray *AlphaData, + TfToken *interpolation, + VtArray *assignmentIndices); +/// Get the base colors and opacities from the shader(s) bound to \p mesh. +/// Returned colors will be in linear color space. +/// +/// If the entire mesh has a single shader assignment, a single value for each +/// of color and alpha will be returned, interpolation will be constant, and +/// assignmentIndices will be empty. +/// +/// Otherwise, a color and alpha value will be returned for each shader +/// assigned to any face of the mesh. \p assignmentIndices will be the length +/// of the number of faces with values indexing into the color and alpha arrays +/// representing per-face assignments. Faces with no assigned shader will have +/// a value of -1 in \p assignmentIndices. \p interpolation will be uniform. +/// +bool GetLinearShaderColor( + const MFnMesh& mesh, + VtArray *RGBData, + VtArray *AlphaData, + TfToken *interpolation, + VtArray *assignmentIndices); + +/// If any components in \p assignmentIndices are unassigned (-1), the given +/// default values will be added to RGBData and AlphaData and all of those +/// components will be assigned that index, which is returned in +/// \p unassignedValueIndex. +/// Returns true if unassigned values were added and indices were updated, or +/// false otherwise. +bool AddUnassignedColorAndAlphaIfNeeded( + VtArray* RGBData, + VtArray* AlphaData, + VtArray* assignmentIndices, + int* unassignedValueIndex, + const GfVec3f& defaultRGB, + const float defaultAlpha); MPlug GetConnected(const MPlug& plug); From 522e7f68e32997476aaff7f9f60cc74f4d9858a9 Mon Sep 17 00:00:00 2001 From: c64kernal Date: Tue, 30 Aug 2016 22:09:24 -0700 Subject: [PATCH 069/380] Add Hydra support for new Material schema. The usdShade Look schema is being replaced by Material and this change allows Hydra to support the new schema. It retains backwards compatibility for older assets. (Internal change: 1651209) --- pxr/usdImaging/lib/usdImaging/delegate.cpp | 17 +++++----- pxr/usdImaging/lib/usdImaging/delegate.h | 2 +- .../lib/usdImaging/gprimAdapter.cpp | 28 ++++++++-------- .../lib/usdImaging/inheritedCache.cpp | 33 ++++++++++--------- .../lib/usdImaging/inheritedCache.h | 30 +++++++++-------- pxr/usdImaging/lib/usdImaging/primAdapter.cpp | 4 +-- pxr/usdImaging/lib/usdImaging/refEngine.cpp | 2 +- 7 files changed, 60 insertions(+), 56 deletions(-) diff --git a/pxr/usdImaging/lib/usdImaging/delegate.cpp b/pxr/usdImaging/lib/usdImaging/delegate.cpp index d60f1df034..2fb3a5e04c 100644 --- a/pxr/usdImaging/lib/usdImaging/delegate.cpp +++ b/pxr/usdImaging/lib/usdImaging/delegate.cpp @@ -95,7 +95,7 @@ UsdImagingDelegate::UsdImagingDelegate() , _reprFallback() , _cullStyleFallback(HdCullStyleDontCare) , _xformCache(GetTime(), GetRootCompensation()) - , _lookBindingCache(GetTime(), GetRootCompensation()) + , _materialBindingCache(GetTime(), GetRootCompensation()) , _visCache(GetTime(), GetRootCompensation()) { // this constructor create a new render index. @@ -128,7 +128,7 @@ UsdImagingDelegate::UsdImagingDelegate( , _reprFallback() , _cullStyleFallback(HdCullStyleDontCare) , _xformCache(GetTime(), GetRootCompensation()) - , _lookBindingCache(GetTime(), GetRootCompensation()) + , _materialBindingCache(GetTime(), GetRootCompensation()) , _visCache(GetTime(), GetRootCompensation()) { HdChangeTracker &tracker = GetRenderIndex().GetChangeTracker(); @@ -915,13 +915,13 @@ UsdImagingDelegate::_SetStateForPopulation( } namespace { - struct _PopulateLookBindingCache { + struct _PopulateMaterialBindingCache { UsdPrim primToBind; - UsdImaging_LookBindingCache const* lookBindingCache; + UsdImaging_MaterialBindingCache const* materialBindingCache; void operator()() const { // Just calling GetValue will populate the cache for this prim and // potentially all ancestors. - lookBindingCache->GetValue(primToBind); + materialBindingCache->GetValue(primToBind); } }; }; @@ -990,7 +990,8 @@ UsdImagingDelegate::_Populate(UsdImagingIndexProxy* proxy) continue; } if (_AdapterSharedPtr adapter = _AdapterLookup(*treeIt)) { - _PopulateLookBindingCache wu = { *treeIt, &_lookBindingCache }; + _PopulateMaterialBindingCache wu = + { *treeIt, &_materialBindingCache }; bindingDispatcher.Run(wu); leafPaths.push_back(std::make_pair(*treeIt, adapter)); if (adapter->ShouldCullChildren(*treeIt)) { @@ -1105,7 +1106,7 @@ UsdImagingDelegate::_ProcessChangesForTimeUpdate(UsdTimeCode time) // Need to invalidate all caches if any stage objects have changed. This // invalidation is overly conservative, but correct. _xformCache.Clear(); - _lookBindingCache.Clear(); + _materialBindingCache.Clear(); _visCache.Clear(); } @@ -1892,7 +1893,7 @@ UsdImagingDelegate::_ComputeRootCompensation(SdfPath const & usdPath) _compensationPath = usdPath; _xformCache.SetRootPath(usdPath); - _lookBindingCache.SetRootPath(usdPath); + _materialBindingCache.SetRootPath(usdPath); _visCache.SetRootPath(usdPath); return true; diff --git a/pxr/usdImaging/lib/usdImaging/delegate.h b/pxr/usdImaging/lib/usdImaging/delegate.h index 79ecf314df..87fc97eb37 100644 --- a/pxr/usdImaging/lib/usdImaging/delegate.h +++ b/pxr/usdImaging/lib/usdImaging/delegate.h @@ -564,7 +564,7 @@ class UsdImagingDelegate : public HdSceneDelegate, public TfWeakBase { SdfPathVector _pathsToUpdate; UsdImaging_XformCache _xformCache; - UsdImaging_LookBindingCache _lookBindingCache; + UsdImaging_MaterialBindingCache _materialBindingCache; UsdImaging_VisCache _visCache; // Collection diff --git a/pxr/usdImaging/lib/usdImaging/gprimAdapter.cpp b/pxr/usdImaging/lib/usdImaging/gprimAdapter.cpp index cb6e685ae5..8e7450b975 100644 --- a/pxr/usdImaging/lib/usdImaging/gprimAdapter.cpp +++ b/pxr/usdImaging/lib/usdImaging/gprimAdapter.cpp @@ -32,7 +32,7 @@ #include "pxr/usd/usdGeom/gprim.h" -#include "pxr/usd/usdShade/look.h" +#include "pxr/usd/usdShade/material.h" #include "pxr/usd/usdShade/pShader.h" #include "pxr/usd/usdShade/shader.h" @@ -460,27 +460,27 @@ UsdImagingGprimAdapter::GetColorAndOpacity(UsdPrim const& prim, static TfToken displayColorToken("displayColor"); static TfToken displayOpacityToken("displayOpacity"); - UsdRelationship look = UsdShadeLook::GetBindingRel(prim); - SdfPathVector lookTargets; - if (look.GetForwardedTargets(&lookTargets)) { - if (not lookTargets.empty()) { - if (lookTargets.size() > 1) { - TF_WARN("<%s> has more than one look target; "\ + UsdRelationship mat = UsdShadeMaterial::GetBindingRel(prim); + SdfPathVector matTargets; + if (mat.GetForwardedTargets(&matTargets)) { + if (not matTargets.empty()) { + if (matTargets.size() > 1) { + TF_WARN("<%s> has more than one material target; "\ "using first one found: <%s>", prim.GetPath().GetText(), - lookTargets.front().GetText()); + matTargets.front().GetText()); } - UsdPrim lookPrim( - prim.GetStage()->GetPrimAtPath(lookTargets.front())); + UsdPrim matPrim( + prim.GetStage()->GetPrimAtPath(matTargets.front())); - if (lookPrim and - lookPrim.GetAttribute(displayColorToken).Get(&color, time)) { + if (matPrim and + matPrim.GetAttribute(displayColorToken).Get(&color, time)) { colorInterp = UsdGeomTokens->constant; result[0] = GfVec4f(color[0], color[1], color[2], opacity); } - if (lookPrim and - lookPrim.GetAttribute(displayOpacityToken).Get(&opacity, time)) { + if (matPrim and + matPrim.GetAttribute(displayOpacityToken).Get(&opacity, time)) { opacityInterp = UsdGeomTokens->constant; result[0][3] = opacity; } diff --git a/pxr/usdImaging/lib/usdImaging/inheritedCache.cpp b/pxr/usdImaging/lib/usdImaging/inheritedCache.cpp index 032b413ab1..1e3d7cb1a9 100644 --- a/pxr/usdImaging/lib/usdImaging/inheritedCache.cpp +++ b/pxr/usdImaging/lib/usdImaging/inheritedCache.cpp @@ -30,11 +30,11 @@ /*static*/ UsdPrim -UsdImaging_LookStrategy::GetTargetedShader(UsdPrim const& lookPrim, - UsdRelationship const& lookRel) +UsdImaging_MaterialStrategy::GetTargetedShader(UsdPrim const& materialPrim, + UsdRelationship const& materialRel) { SdfPathVector targets; - if (not lookRel.GetForwardedTargets(&targets)) + if (not materialRel.GetForwardedTargets(&targets)) return UsdPrim(); if (targets.size() != 1) { @@ -42,8 +42,8 @@ UsdImaging_LookStrategy::GetTargetedShader(UsdPrim const& lookPrim, // feature. TF_WARN("We expect only one target on relationship %s of prim <%s>, " "but got %zu.", - lookRel.GetName().GetText(), - lookPrim.GetPath().GetText(), + materialRel.GetName().GetText(), + materialPrim.GetPath().GetText(), targets.size()); return UsdPrim(); } @@ -53,25 +53,26 @@ UsdImaging_LookStrategy::GetTargetedShader(UsdPrim const& lookPrim, // feature. TF_WARN("We expect the target of the relationship %s of prim <%s> " "to be a prim, instead it is <%s>.", - lookRel.GetName().GetText(), - lookPrim.GetPath().GetText(), + materialRel.GetName().GetText(), + materialPrim.GetPath().GetText(), targets[0].GetText()); return UsdPrim(); } - return lookPrim.GetStage()->GetPrimAtPath(targets[0]); + return materialPrim.GetStage()->GetPrimAtPath(targets[0]); } /*static*/ SdfPath -UsdImaging_LookStrategy::GetBinding(UsdShadeLook const& look) +UsdImaging_MaterialStrategy::GetBinding(UsdShadeMaterial const& material) { - TF_DEBUG(USDIMAGING_SHADERS).Msg("\t Look: %s\n", look.GetPath().GetText()); - if (UsdRelationship lookRel = UsdHydraLookAPI(look).GetBxdfRel()) { + TF_DEBUG(USDIMAGING_SHADERS).Msg("\t Look: %s\n", + material.GetPath().GetText()); + if (UsdRelationship matRel = UsdHydraLookAPI(material).GetBxdfRel()) { TF_DEBUG(USDIMAGING_SHADERS).Msg("\t LookRel: %s\n", - lookRel.GetPath().GetText()); - UsdShadeShader shader(GetTargetedShader(look.GetPrim(), lookRel)); + matRel.GetPath().GetText()); + UsdShadeShader shader(GetTargetedShader(material.GetPrim(), matRel)); if (shader) { TF_DEBUG(USDIMAGING_SHADERS).Msg("\t UsdShade binding found: %s\n", shader.GetPath().GetText()); @@ -85,10 +86,10 @@ UsdImaging_LookStrategy::GetBinding(UsdShadeLook const& look) TfToken hdSurf("hydraLook:surface"), surfType("HydraPbsSurface"); - if (UsdRelationship lookRel = look.GetPrim().GetRelationship(hdSurf)) { + if (UsdRelationship matRel = material.GetPrim().GetRelationship(hdSurf)) { TF_DEBUG(USDIMAGING_SHADERS).Msg("\t LookRel: %s\n", - lookRel.GetPath().GetText()); - if (UsdPrim shader = GetTargetedShader(look.GetPrim(), lookRel)) { + matRel.GetPath().GetText()); + if (UsdPrim shader = GetTargetedShader(material.GetPrim(), matRel)) { if (TF_VERIFY(shader.GetTypeName() == surfType)) { TF_DEBUG(USDIMAGING_SHADERS).Msg( "\t Deprecated binding found: %s\n", diff --git a/pxr/usdImaging/lib/usdImaging/inheritedCache.h b/pxr/usdImaging/lib/usdImaging/inheritedCache.h index 569b121403..a106ef9794 100644 --- a/pxr/usdImaging/lib/usdImaging/inheritedCache.h +++ b/pxr/usdImaging/lib/usdImaging/inheritedCache.h @@ -512,37 +512,37 @@ struct UsdImaging_VisStrategy { }; // -------------------------------------------------------------------------- // -// LookBinding Cache +// MaterialBinding Cache // -------------------------------------------------------------------------- // -#include "pxr/usd/usdShade/look.h" +#include "pxr/usd/usdShade/material.h" -struct UsdImaging_LookStrategy; -typedef UsdImaging_InheritedCache - UsdImaging_LookBindingCache; +struct UsdImaging_MaterialStrategy; +typedef UsdImaging_InheritedCache + UsdImaging_MaterialBindingCache; -struct UsdImaging_LookStrategy { +struct UsdImaging_MaterialStrategy { typedef SdfPath value_type; // inherited path to bound shader - typedef UsdShadeLook query_type; + typedef UsdShadeMaterial query_type; static value_type MakeDefault() { return SdfPath(); } static query_type MakeQuery(UsdPrim prim) { - return UsdShadeLook::GetBoundLook(prim); + return UsdShadeMaterial::GetBoundMaterial(prim); } static - SdfPath GetBinding(UsdShadeLook const& look); + SdfPath GetBinding(UsdShadeMaterial const& material); static - UsdPrim GetTargetedShader(UsdPrim const& prim, - UsdRelationship const& lookRel); + UsdPrim GetTargetedShader(UsdPrim const& materialPrim, + UsdRelationship const& materialRel); static value_type - Inherit(UsdImaging_LookBindingCache const* owner, + Inherit(UsdImaging_MaterialBindingCache const* owner, UsdPrim prim, query_type const* query) { @@ -565,8 +565,10 @@ struct UsdImaging_LookStrategy { for (UsdPrim parent=prim;parent.GetParent();parent=parent.GetParent()) { TF_DEBUG(USDIMAGING_SHADERS).Msg("Looking for shader binding %s\n", parent.GetPath().GetText()); - if (UsdShadeLook look = UsdShadeLook::GetBoundLook(parent)) { - binding = GetBinding(look); + + UsdShadeMaterial mat = UsdShadeMaterial::GetBoundMaterial(parent); + if (mat) { + binding = GetBinding(mat); if (not binding.IsEmpty()) { break; } diff --git a/pxr/usdImaging/lib/usdImaging/primAdapter.cpp b/pxr/usdImaging/lib/usdImaging/primAdapter.cpp index bf3884c817..d37cfc172d 100644 --- a/pxr/usdImaging/lib/usdImaging/primAdapter.cpp +++ b/pxr/usdImaging/lib/usdImaging/primAdapter.cpp @@ -307,10 +307,10 @@ UsdImagingPrimAdapter::GetShaderBinding(UsdPrim const& prim) // samples. if (_IsEnabledBindingCache()) { - SdfPath binding = _delegate->_lookBindingCache.GetValue(prim); + SdfPath binding = _delegate->_materialBindingCache.GetValue(prim); return binding; } else { - return UsdImaging_LookStrategy::ComputeShaderPath(prim); + return UsdImaging_MaterialStrategy::ComputeShaderPath(prim); } } diff --git a/pxr/usdImaging/lib/usdImaging/refEngine.cpp b/pxr/usdImaging/lib/usdImaging/refEngine.cpp index db08eb1860..a2e2efcc8d 100644 --- a/pxr/usdImaging/lib/usdImaging/refEngine.cpp +++ b/pxr/usdImaging/lib/usdImaging/refEngine.cpp @@ -665,7 +665,7 @@ UsdImagingRefEngine::_ProcessGprimColor(const UsdGeomGprim *gprimSchema, // Get DoubleSided Attribute gprimSchema->GetDoubleSidedAttr().Get(doubleSided); - // Get interpolation and color using new UsdShadeLook + // Get interpolation and color using UsdShadeMaterial UsdImagingValueCache::PrimvarInfo primvar; VtValue colorAsVt = UsdImagingGprimAdapter::GetColorAndOpacity(prim, &primvar, _params.frame); From 8c82c4e2cbac6103ca144612e3a0647c21082603 Mon Sep 17 00:00:00 2001 From: Aaron Luk Date: Wed, 31 Aug 2016 14:46:11 +0200 Subject: [PATCH 070/380] Fix link to OpenEXR webpage. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 7a31cfecf3..63b1b9871a 100644 --- a/README.md +++ b/README.md @@ -45,7 +45,7 @@ Dependencies | [CMake](https://cmake.org/documentation/) | 2.8.8 (Linux/OS X), 3.1.1 (Windows) | | [Python](https://python.org) | 2.7.5 | | [Boost](https://boost.org) | 1.55 (Linux/OS X), 1.61.0 (Windows) | -| [OpenEXR](https://openexr.org) | 2.2.0 | +| [OpenEXR](http://www.openexr.com) | 2.2.0 | | [DoubleConversion](https://github.com/google/double-conversion) | 1.1.1 | | [Intel TBB](https://www.threadingbuildingblocks.org/) | 4.3.1 | | [OpenSubdiv](https://github.com/PixarAnimationStudios/OpenSubdiv) | 3.0.5 | From db0a56eca7c616f3022cd8e173f45c934db28e99 Mon Sep 17 00:00:00 2001 From: George ElKoura Date: Wed, 31 Aug 2016 21:59:09 -0700 Subject: [PATCH 071/380] Add more symbol visibility macros to hd API. --- pxr/imaging/lib/hd/drawTargetRenderPass.h | 2 ++ pxr/imaging/lib/hd/textureResource.h | 2 ++ 2 files changed, 4 insertions(+) diff --git a/pxr/imaging/lib/hd/drawTargetRenderPass.h b/pxr/imaging/lib/hd/drawTargetRenderPass.h index b9d0d9619f..743d900716 100644 --- a/pxr/imaging/lib/hd/drawTargetRenderPass.h +++ b/pxr/imaging/lib/hd/drawTargetRenderPass.h @@ -65,9 +65,11 @@ class HdDrawTargetRenderPass : boost::noncopyable { void SetRprimCollection(HdRprimCollection const& col); /// Execute render pass task + HDLIB_API void Sync(); /// Sync the render pass resources + HDLIB_API void Execute(HdRenderPassStateSharedPtr const &renderPassState); private: diff --git a/pxr/imaging/lib/hd/textureResource.h b/pxr/imaging/lib/hd/textureResource.h index c87ce6a9ad..6949301788 100644 --- a/pxr/imaging/lib/hd/textureResource.h +++ b/pxr/imaging/lib/hd/textureResource.h @@ -46,7 +46,9 @@ class HdTextureResource { /// Returns the hash value of the texture for \a sourceFile HDLIB_API static ID ComputeHash(TfToken const & sourceFile); + HDLIB_API static ID ComputeFallbackPtexHash(); + HDLIB_API static ID ComputeFallbackUVHash(); HDLIB_API From 054101e5f04746dc479786c6b361f5753cdbafa7 Mon Sep 17 00:00:00 2001 From: George ElKoura Date: Wed, 31 Aug 2016 22:00:27 -0700 Subject: [PATCH 072/380] Adding one more symbol visibility macro to GfFrustum. --- pxr/base/lib/gf/frustum.h | 1 + 1 file changed, 1 insertion(+) diff --git a/pxr/base/lib/gf/frustum.h b/pxr/base/lib/gf/frustum.h index 6b2ededd07..26462b8f01 100644 --- a/pxr/base/lib/gf/frustum.h +++ b/pxr/base/lib/gf/frustum.h @@ -439,6 +439,7 @@ class GfFrustum { /// \li Right top /// In particular, it gives the partial result of ComputeCorners when given /// near or far distance. + GF_API std::vector ComputeCornersAtDistance(double d) const; /// Returns a frustum that is a narrowed-down version of this frustum, From e739831d6fed5faf3e59c45bf9e0de5d3693f74a Mon Sep 17 00:00:00 2001 From: George ElKoura Date: Wed, 31 Aug 2016 22:01:56 -0700 Subject: [PATCH 073/380] Fix bad merge. --- pxr/base/lib/work/loops.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pxr/base/lib/work/loops.h b/pxr/base/lib/work/loops.h index 7edd5049a3..866535a47c 100644 --- a/pxr/base/lib/work/loops.h +++ b/pxr/base/lib/work/loops.h @@ -76,7 +76,7 @@ WorkParallelForN(size_t n, Fn &&callback) // Don't bother with parallel_for, if concurrency is limited to 1. if (WorkGetConcurrencyLimit() > 1) { - class Work_ParallelForN_TBB: boost::noncopyable + class Work_ParallelForN_TBB { public: Work_ParallelForN_TBB(Fn &fn) : _fn(fn) { } From 448afdc2d802ccb5c2d8f3e86e151721707b54c9 Mon Sep 17 00:00:00 2001 From: George ElKoura Date: Wed, 31 Aug 2016 22:07:33 -0700 Subject: [PATCH 074/380] Fix issue with MSVC finding proper overrides. --- pxr/usd/lib/usd/stage.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pxr/usd/lib/usd/stage.cpp b/pxr/usd/lib/usd/stage.cpp index ae4a1fe6d9..494a8d3e98 100644 --- a/pxr/usd/lib/usd/stage.cpp +++ b/pxr/usd/lib/usd/stage.cpp @@ -3308,19 +3308,19 @@ UsdStage::_ComposePrimIndexesInParallel( _cache->ComputePrimIndexesInParallel( primIndexPaths, &errs, _NameChildrenPred(_instanceCache.get()), [](const SdfPath &) { return true; }, - "Usd", _mallocTagID); + "Usd", _mallocTagID.c_str()); } else if (includeRule == _IncludeNoDiscoveredPayloads) { _cache->ComputePrimIndexesInParallel( primIndexPaths, &errs, _NameChildrenPred(_instanceCache.get()), [](const SdfPath &) { return false; }, - "Usd", _mallocTagID); + "Usd", _mallocTagID.c_str()); } else if (includeRule == _IncludeNewPayloadsIfAncestorWasIncluded) { _cache->ComputePrimIndexesInParallel( primIndexPaths, &errs, _NameChildrenPred(_instanceCache.get()), _IncludeNewlyDiscoveredPayloadsPredicate(this), - "Usd", _mallocTagID); + "Usd", _mallocTagID.c_str()); } if (not errs.empty()) { From c784e50cdc6fd4a5808c05bbda8cc968dbe00206 Mon Sep 17 00:00:00 2001 From: George ElKoura Date: Wed, 31 Aug 2016 22:09:16 -0700 Subject: [PATCH 075/380] Fix up integration from dev for Windows. --- pxr/imaging/lib/garch/glPlatformDebugContext.h | 12 ++++++------ pxr/imaging/lib/garch/wrapPlatformDebugContext.cpp | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/pxr/imaging/lib/garch/glPlatformDebugContext.h b/pxr/imaging/lib/garch/glPlatformDebugContext.h index 301913b8e6..2efa31d582 100644 --- a/pxr/imaging/lib/garch/glPlatformDebugContext.h +++ b/pxr/imaging/lib/garch/glPlatformDebugContext.h @@ -24,7 +24,7 @@ #ifndef GARCH_GLPLATFORM_DEBUG_CONTEXT_H #define GARCH_GLPLATFORM_DEBUG_CONTEXT_H -#include "pxr/imaging/glfq/api.h" +#include "pxr/imaging/garch/api.h" #include "pxr/base/tf/declarePtrs.h" #include "pxr/base/tf/weakBase.h" @@ -42,23 +42,23 @@ TF_DECLARE_WEAK_PTRS(GarchGLPlatformDebugContext); /// class GarchGLPlatformDebugContext : public TfWeakBase { public: - GLFQ_API + GARCH_API GarchGLPlatformDebugContext(int majorVersion, int minorVersion, bool coreProfile, bool directRenderering); virtual ~GarchGLPlatformDebugContext(); - GLFQ_API + GARCH_API static bool IsEnabledDebugOutput(); - GLFQ_API + GARCH_API static bool IsEnabledCoreProfile(); - GLFQ_API + GARCH_API void makeCurrent(); - GLFQ_API + GARCH_API void *chooseMacVisual(); public: diff --git a/pxr/imaging/lib/garch/wrapPlatformDebugContext.cpp b/pxr/imaging/lib/garch/wrapPlatformDebugContext.cpp index 6f726da71c..7afc581c54 100644 --- a/pxr/imaging/lib/garch/wrapPlatformDebugContext.cpp +++ b/pxr/imaging/lib/garch/wrapPlatformDebugContext.cpp @@ -50,4 +50,4 @@ void wrapPlatformDebugContext() ; } -TF_REFPTR_CONST_VOLATILE_GET(GlfQGLPlatformDebugContext) +TF_REFPTR_CONST_VOLATILE_GET(GarchGLPlatformDebugContext) From 4919a07fb4e84d360666be38f689312d1bdeadb8 Mon Sep 17 00:00:00 2001 From: George ElKoura Date: Wed, 31 Aug 2016 22:29:44 -0700 Subject: [PATCH 076/380] Hack to temporarily comment out some static asserts for Windows. --- pxr/usd/lib/pcp/statistics.cpp | 10 +++++----- pxr/usd/lib/usd/primData.cpp | 4 ++-- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/pxr/usd/lib/pcp/statistics.cpp b/pxr/usd/lib/pcp/statistics.cpp index eb2e6ef874..edd01df671 100644 --- a/pxr/usd/lib/pcp/statistics.cpp +++ b/pxr/usd/lib/pcp/statistics.cpp @@ -332,8 +332,8 @@ class Pcp_Statistics // This object is 120 bytes when building against libstdc++ // and 96 for libc++ because std::set is 48 bytes in the // former case and 24 bytes in the latter. - BOOST_STATIC_ASSERT(sizeof(PcpMapExpression::_Node) == 120 or - sizeof(PcpMapExpression::_Node) == 96); + //BOOST_STATIC_ASSERT(sizeof(PcpMapExpression::_Node) == 120 or + // sizeof(PcpMapExpression::_Node) == 96); BOOST_STATIC_ASSERT(sizeof(PcpLayerStackPtr) == 16); BOOST_STATIC_ASSERT(sizeof(PcpLayerStackSite) == 24); @@ -341,10 +341,10 @@ class Pcp_Statistics // This object is 104 bytes when building against libstdc++ // and 88 for libc++ because std::vector is 40 bytes // in the former case and 24 bytes in the latter. - BOOST_STATIC_ASSERT(sizeof(PcpPrimIndex_Graph) == 104 or - sizeof(PcpPrimIndex_Graph) == 88); + //BOOST_STATIC_ASSERT(sizeof(PcpPrimIndex_Graph) == 104 or + // sizeof(PcpPrimIndex_Graph) == 88); - BOOST_STATIC_ASSERT(sizeof(PcpPrimIndex_Graph::_Node) == 48); + //BOOST_STATIC_ASSERT(sizeof(PcpPrimIndex_Graph::_Node) == 48); BOOST_STATIC_ASSERT(sizeof(PcpPrimIndex_Graph::_SharedData) == 32); #endif } diff --git a/pxr/usd/lib/usd/primData.cpp b/pxr/usd/lib/usd/primData.cpp index 1cfe04bb1d..31923de96a 100644 --- a/pxr/usd/lib/usd/primData.cpp +++ b/pxr/usd/lib/usd/primData.cpp @@ -41,8 +41,8 @@ namespace { // Static assertion on PrimData size. We want to be warned when its size // changes. -static_assert(sizeof(Usd_PrimData) == 64, - "Expected sizeof(Usd_PrimData) == 64"); +//static_assert(sizeof(Usd_PrimData) == 64, +// "Expected sizeof(Usd_PrimData) == 64"); } #endif From 01368b8d286db510352dcd4511e63a3e9f9eaf9f Mon Sep 17 00:00:00 2001 From: George ElKoura Date: Wed, 31 Aug 2016 22:43:31 -0700 Subject: [PATCH 077/380] We no longer need to undef FindResource --- pxr/base/lib/plug/plugin.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/pxr/base/lib/plug/plugin.cpp b/pxr/base/lib/plug/plugin.cpp index d13c198515..5f46926522 100644 --- a/pxr/base/lib/plug/plugin.cpp +++ b/pxr/base/lib/plug/plugin.cpp @@ -59,8 +59,6 @@ #include #include -#undef FindResource // Defined on Windows. - using std::pair; using std::string; using std::vector; From 1c48fc7a91adc77956ac934eef4b58b8a267f109 Mon Sep 17 00:00:00 2001 From: George ElKoura Date: Wed, 31 Aug 2016 22:43:58 -0700 Subject: [PATCH 078/380] Hacking the plugin paths for Windows temporarily. --- pxr/base/lib/plug/initConfig.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pxr/base/lib/plug/initConfig.cpp b/pxr/base/lib/plug/initConfig.cpp index 083e269b1f..271a9b9d2f 100644 --- a/pxr/base/lib/plug/initConfig.cpp +++ b/pxr/base/lib/plug/initConfig.cpp @@ -32,8 +32,8 @@ namespace { const char* pathEnvVarName = BOOST_PP_STRINGIZE(PXR_PLUGINPATH_NAME); const char* buildLocation = BOOST_PP_STRINGIZE(PXR_BUILD_LOCATION); -const char* userLocation = BOOST_PP_STRINGIZE(C:\\ProgramData\\usd\\plugins); -const char* installLocation = BOOST_PP_STRINGIZE(PXR_INSTALL_LOCATION); +const char* userLocation = "";//BOOST_PP_STRINGIZE(C:\\ProgramData\\usd\\plugins); +const char* installLocation = "";//BOOST_PP_STRINGIZE(PXR_INSTALL_LOCATION); void _AppendPathList(std::vector* result, const std::string& paths) { From 37169645f884dbe72cb45fc57edfe8c4046bcee3 Mon Sep 17 00:00:00 2001 From: George ElKoura Date: Wed, 31 Aug 2016 22:45:06 -0700 Subject: [PATCH 079/380] Suppress a warning on Windows. Not meant to make it back to dev. --- pxr/imaging/lib/glf/oiioImage.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/pxr/imaging/lib/glf/oiioImage.cpp b/pxr/imaging/lib/glf/oiioImage.cpp index 115c670c58..2910cd0f00 100644 --- a/pxr/imaging/lib/glf/oiioImage.cpp +++ b/pxr/imaging/lib/glf/oiioImage.cpp @@ -438,6 +438,10 @@ Glf_OIIOImage::ReadCropped(int const cropTop, image = &scaled; } +//XXX: +//'OpenImageIO::v1_7::ImageBuf::get_pixels': Use get_pixels(ROI, ...) instead. [1.6] +#pragma warning(disable:4996) + // Read pixel data TypeDesc type = _GetOIIOBaseType(storage.type); if (not image->get_pixels(0, storage.width, 0, storage.height, 0, 1, From 3bcf183b07e9860aeb9037d330ff442c52753ee7 Mon Sep 17 00:00:00 2001 From: George ElKoura Date: Wed, 31 Aug 2016 22:46:17 -0700 Subject: [PATCH 080/380] Add a few more global warnings to ignore. We can't check this into dev. We should be able to resolve both of these without suppressing the warning. --- cmake/defaults/msvcdefaults.cmake | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/cmake/defaults/msvcdefaults.cmake b/cmake/defaults/msvcdefaults.cmake index 4279fb0798..cdbc982579 100644 --- a/cmake/defaults/msvcdefaults.cmake +++ b/cmake/defaults/msvcdefaults.cmake @@ -62,6 +62,14 @@ add_definitions("/wd4267") # this affects Glf only add_definitions("/wd4506") +# 'typedef ': ignored on left of '' when no variable is declared +# XXX:figure out why we need this +add_definitions("/wd4091") + +# c:\python27\include\pymath.h(22): warning C4273: 'round': inconsistent dll linkage +# XXX:figure out real fix +add_definitions("/wd4273") + # Enable PDB generation add_definitions("/Zi") From 69a3cd50a835bab4bfe028fe7fbaa6837e644c16 Mon Sep 17 00:00:00 2001 From: George ElKoura Date: Wed, 31 Aug 2016 22:48:00 -0700 Subject: [PATCH 081/380] Temporary hack to disable static assert in mallocTag.cpp. --- pxr/base/lib/tf/mallocTag.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/pxr/base/lib/tf/mallocTag.cpp b/pxr/base/lib/tf/mallocTag.cpp index fb5687bd55..98db4850b6 100644 --- a/pxr/base/lib/tf/mallocTag.cpp +++ b/pxr/base/lib/tf/mallocTag.cpp @@ -175,8 +175,9 @@ struct Tf_MallocBlockInfo { #if defined(ARCH_COMPILER_HAS_STATIC_ASSERT) -static_assert(sizeof(Tf_MallocBlockInfo) == 8, - "Unexpected size for Tf_MallocBlockInfo"); +//XXX:Windows -- why are we compiling mallocTag at all? +//static_assert(sizeof(Tf_MallocBlockInfo) == 8, +// "Unexpected size for Tf_MallocBlockInfo"); #endif /* From 79fa6ccb03af80482fb0de863dd4ebd390dc32fb Mon Sep 17 00:00:00 2001 From: George ElKoura Date: Wed, 31 Aug 2016 22:48:45 -0700 Subject: [PATCH 082/380] Temporary hack for TfRealPath for Windows for drive letter capitalization. --- pxr/base/lib/tf/pathUtils.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/pxr/base/lib/tf/pathUtils.cpp b/pxr/base/lib/tf/pathUtils.cpp index b563860d69..903a0c317f 100644 --- a/pxr/base/lib/tf/pathUtils.cpp +++ b/pxr/base/lib/tf/pathUtils.cpp @@ -67,7 +67,15 @@ TfRealPath(string const& path, bool allowInaccessibleSuffix, string* error) *error = "Call to GetFullPathName failed"; } return string(); - } + } else { + // Make sure drive letters are always lower-case out of TfRealPath on + // Windows -- this is so that we can be sure we can reliably use the + // paths as keys in tables, etc. + if (fullPath[1] == ':') { + fullPath[0] = tolower(fullPath[0]); + } + + } return std::string(fullPath); #else From 10cb607091904d6867a1c3b3427580da81421f2b Mon Sep 17 00:00:00 2001 From: George ElKoura Date: Wed, 31 Aug 2016 22:50:49 -0700 Subject: [PATCH 083/380] Add dependency on Qt5 and fix up the install path for the icons. --- pxr/usdImaging/lib/usdviewq/CMakeLists.txt | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/pxr/usdImaging/lib/usdviewq/CMakeLists.txt b/pxr/usdImaging/lib/usdviewq/CMakeLists.txt index a6cf13b2bd..92304d2d9f 100644 --- a/pxr/usdImaging/lib/usdviewq/CMakeLists.txt +++ b/pxr/usdImaging/lib/usdviewq/CMakeLists.txt @@ -1,7 +1,7 @@ set(PXR_PREFIX pxr/usdImaging) set(PXR_PACKAGE usdviewq) -if (NOT QT4_FOUND) +if (NOT Qt5Core_FOUND) message(WARNING "Not building ${PXR_PACKAGE} because of missing dependency: Qt4") return() endif() @@ -73,7 +73,8 @@ pxr_shared_library(usdviewq referenceEditorUI.ui ) +_get_install_dir(lib/python/pxr/Usdviewq destDir) install(DIRECTORY icons - DESTINATION lib/python/pxr/Usdviewq + DESTINATION ${destDir} ) From 6b8aeaf6ecad5e9f92c4f08e094398532f9e5d12 Mon Sep 17 00:00:00 2001 From: George ElKoura Date: Wed, 31 Aug 2016 22:53:28 -0700 Subject: [PATCH 084/380] Add Qt5 dependencies. --- cmake/defaults/Packages.cmake | 10 ++++++++-- pxr/imaging/lib/glfq/CMakeLists.txt | 13 ++++++------- 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/cmake/defaults/Packages.cmake b/cmake/defaults/Packages.cmake index e947f966f7..e2a1fb7194 100644 --- a/cmake/defaults/Packages.cmake +++ b/cmake/defaults/Packages.cmake @@ -102,8 +102,14 @@ if (PXR_BUILD_IMAGING) find_package(X11) endif() # --Qt - find_package(Qt4) - if (QT4_FOUND) + #find_package(Qt4) + #if (QT4_FOUND) + find_package(Qt5Core) + find_package(Qt5Gui) + find_package(Qt5OpenGL) + find_package(Qt5Xml) + find_package(Qt5Network) + if (Qt5Core_FOUND) find_package(PySide REQUIRED) endif() # --Zlib diff --git a/pxr/imaging/lib/glfq/CMakeLists.txt b/pxr/imaging/lib/glfq/CMakeLists.txt index e5858e2097..24134e39de 100644 --- a/pxr/imaging/lib/glfq/CMakeLists.txt +++ b/pxr/imaging/lib/glfq/CMakeLists.txt @@ -1,7 +1,7 @@ set(PXR_PREFIX pxr/imaging) set(PXR_PACKAGE glfq) -if (NOT QT4_FOUND) +if (NOT Qt5Core_FOUND) message(WARNING "Not building ${PXR_PACKAGE} because of missing dependency: Qt4") return() endif() @@ -17,12 +17,11 @@ pxr_shared_library(glfq glf arch tf - Qt4::QtCore - Qt4::QtGui - Qt4::QtOpenGL - Qt4::QtXml - Qt4::QtNetwork - ${Boost_SYSTEM_LIBRARY} + Qt5::Core + Qt5::Gui + Qt5::OpenGL + Qt5::Xml + Qt5::Network ${OPENGL_gl_LIBRARY} ${GLEW_LIBRARY} From 9343faee190a4ec03757cf2e4c60990175fd49ce Mon Sep 17 00:00:00 2001 From: George ElKoura Date: Wed, 31 Aug 2016 22:54:19 -0700 Subject: [PATCH 085/380] Fix up a few places where we were not getting the right install paths. --- cmake/macros/Private.cmake | 4 ++-- cmake/macros/Public.cmake | 5 +++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/cmake/macros/Private.cmake b/cmake/macros/Private.cmake index cf29c3a381..c258438c3a 100644 --- a/cmake/macros/Private.cmake +++ b/cmake/macros/Private.cmake @@ -110,7 +110,7 @@ function(_install_python LIBRARY_NAME) ${ARGN} ) - set(libPythonPrefix lib/python) + _get_install_dir(lib/python libPythonPrefix) _get_python_module_name(${LIBRARY_NAME} LIBRARY_INSTALLNAME) foreach(file ${ip_FILES}) @@ -238,7 +238,7 @@ function(_install_pyside_ui_files) DEPENDS ${uiFiles} ) - set(libPythonPrefix lib/python) + _get_install_dir(lib/python libPythonPrefix) _get_python_module_name(${LIBRARY_NAME} LIBRARY_INSTALLNAME) install( diff --git a/cmake/macros/Public.cmake b/cmake/macros/Public.cmake index 03efc94172..7a2c48f5df 100644 --- a/cmake/macros/Public.cmake +++ b/cmake/macros/Public.cmake @@ -218,8 +218,9 @@ function(pxr_shared_library LIBRARY_NAME) # 'from pxr import X'. Additionally, python libraries always install # into the default lib install, not into the third_party subdirectory # or similar. - set(LIB_INSTALL_PREFIX "lib/python/pxr/${pyModuleName}") - + _get_install_dir(lib/python/pxr installPrefix) + set(LIB_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}/${installPrefix}/${pyModuleName}") + set_property(GLOBAL APPEND PROPERTY PXR_PYTHON_MODULES ${pyModuleName} ) From 6a611456db3dff9000725c53bf1e04901f5b5dc5 Mon Sep 17 00:00:00 2001 From: sunyab Date: Tue, 6 Sep 2016 12:45:06 -0700 Subject: [PATCH 086/380] Add symbol visibility tagging to pxr/base/arch. (Internal change: 1651294) (Internal change: 1651459) --- pxr/base/lib/arch/CMakeLists.txt | 1 + pxr/base/lib/arch/api.h | 45 +++++++++++++++++++++++++++++++ pxr/base/lib/arch/daemon.h | 3 +++ pxr/base/lib/arch/debugger.h | 5 ++++ pxr/base/lib/arch/demangle.h | 4 ++- pxr/base/lib/arch/errno.h | 5 ++-- pxr/base/lib/arch/error.h | 3 +++ pxr/base/lib/arch/fileSystem.h | 32 ++++++++++++++-------- pxr/base/lib/arch/function.h | 2 ++ pxr/base/lib/arch/hash.h | 9 ++++--- pxr/base/lib/arch/mallocHook.h | 12 +++++++-- pxr/base/lib/arch/nap.h | 4 +++ pxr/base/lib/arch/pixarConfig.cpp | 4 +++ pxr/base/lib/arch/stackTrace.h | 31 ++++++++++++++++++++- pxr/base/lib/arch/symbols.h | 2 ++ pxr/base/lib/arch/systemInfo.h | 5 ++++ pxr/base/lib/arch/testArchAbi.h | 12 +++------ pxr/base/lib/arch/threads.h | 4 ++- pxr/base/lib/arch/timing.h | 5 ++++ pxr/base/lib/arch/vsnprintf.h | 4 +++ 20 files changed, 161 insertions(+), 31 deletions(-) create mode 100644 pxr/base/lib/arch/api.h diff --git a/pxr/base/lib/arch/CMakeLists.txt b/pxr/base/lib/arch/CMakeLists.txt index 1d4b3171df..582fb7ac76 100644 --- a/pxr/base/lib/arch/CMakeLists.txt +++ b/pxr/base/lib/arch/CMakeLists.txt @@ -30,6 +30,7 @@ pxr_shared_library(arch PUBLIC_HEADERS align.h + api.h attributes.h buildMode.h defines.h diff --git a/pxr/base/lib/arch/api.h b/pxr/base/lib/arch/api.h new file mode 100644 index 0000000000..463af444a2 --- /dev/null +++ b/pxr/base/lib/arch/api.h @@ -0,0 +1,45 @@ +// +// 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 ARCH_API_H +#define ARCH_API_H + +#include "pxr/base/arch/export.h" + +#if defined(ARCH_STATIC) +# define ARCH_API +# define ARCH_LOCAL +#else +# if defined(ARCH_EXPORTS) +# define ARCH_API ARCH_EXPORT +# define ARCH_API_TEMPLATE_CLASS(...) +# define ARCH_API_TEMPLATE_STRUCT(...) +# else +# define ARCH_API ARCH_IMPORT +# define ARCH_API_TEMPLATE_CLASS(...) extern template class ARCH_API __VA_ARGS__ +# define ARCH_API_TEMPLATE_STRUCT(...) extern template struct ARCH_API __VA_ARGS__ +# endif +# define ARCH_LOCAL ARCH_HIDDEN +#endif + +#endif diff --git a/pxr/base/lib/arch/daemon.h b/pxr/base/lib/arch/daemon.h index 6dea0c01d0..f886694e14 100644 --- a/pxr/base/lib/arch/daemon.h +++ b/pxr/base/lib/arch/daemon.h @@ -28,6 +28,8 @@ /// \ingroup group_arch_Multithreading /// Create background or daemon processes. +#include "pxr/base/arch/api.h" + /// Close all file descriptors (with possible exceptions) /// /// \c ArchCloseAllFiles will close all file descriptors open in the @@ -55,6 +57,7 @@ /// value. Returns 0 on success. /// /// \ingroup group_arch_Multithreading +ARCH_API int ArchCloseAllFiles(int nExcept, const int* exceptFds); #endif // ARCH_DAEMON_H diff --git a/pxr/base/lib/arch/debugger.h b/pxr/base/lib/arch/debugger.h index f1776d2b5d..89c90fd13e 100644 --- a/pxr/base/lib/arch/debugger.h +++ b/pxr/base/lib/arch/debugger.h @@ -27,6 +27,7 @@ /// \file arch/debugger.h /// Routines for interacting with a debugger. +#include "pxr/base/arch/api.h" #include "pxr/base/arch/attributes.h" /// Stop in a debugger. @@ -51,6 +52,7 @@ /// attached terminal by putting the process into the foreground or /// background. /// +ARCH_API void ArchDebuggerTrap() ARCH_NOINLINE; /// Cause debug traps to wait for the debugger or not. @@ -60,6 +62,7 @@ void ArchDebuggerTrap() ARCH_NOINLINE; /// a debugger to continue the process. The process will not wait /// again until another call to this function with \p wait \c true. /// +ARCH_API void ArchDebuggerWait(bool wait); /// Attach a debugger. @@ -71,11 +74,13 @@ void ArchDebuggerWait(bool wait); /// /// Returns true if ARCH_DEBUGGER is set and the debugger was successfully /// launched, otherwise returns false. +ARCH_API bool ArchDebuggerAttach() ARCH_NOINLINE; /// Test if a debugger is attached /// /// Attempts to detect if a debugger is currently attached to the process. +ARCH_API bool ArchDebuggerIsAttached() ARCH_NOINLINE; /// Stop in the debugger. diff --git a/pxr/base/lib/arch/demangle.h b/pxr/base/lib/arch/demangle.h index 03cb688ecf..0a7a59c0de 100644 --- a/pxr/base/lib/arch/demangle.h +++ b/pxr/base/lib/arch/demangle.h @@ -32,6 +32,7 @@ /// \ingroup group_arch_Strings /// Demangle C++ typenames generated by the \c typeid() facility. +#include "pxr/base/arch/api.h" #include #include #include @@ -48,7 +49,7 @@ /// readable form, and overwrites \c typeName. If \c typeName /// cannot be unmangled, the function returns \c false without altering /// \c typeName. Otherwise \c true is returned. -bool ArchDemangle(std::string* typeName); +ARCH_API bool ArchDemangle(std::string* typeName); /// Return demangled RTTI-generated type name. /// @@ -102,6 +103,7 @@ ArchGetDemangled() { ///@} /// \private +ARCH_API void Arch_DemangleFunctionName(std::string* functionName); #endif // ARCH_DEMANGLE_H diff --git a/pxr/base/lib/arch/errno.h b/pxr/base/lib/arch/errno.h index a83c1efb3a..3a1a136455 100644 --- a/pxr/base/lib/arch/errno.h +++ b/pxr/base/lib/arch/errno.h @@ -28,6 +28,7 @@ /// \ingroup group_arch_SystemFunctions /// Functions for dealing with system errors. +#include "pxr/base/arch/api.h" #include /// \addtogroup group_arch_SystemFunctions @@ -39,12 +40,12 @@ /// from errno. POSIX.1c defines errno as a macro which provides access to a /// thread-local integer. This function uses strerror_r, which is thread-safe. /// \overload -std::string ArchStrerror(); +ARCH_API std::string ArchStrerror(); /// Return the error string for the specified value of errno. /// /// This function uses strerror_r, which is thread-safe. -std::string ArchStrerror(int errorCode); +ARCH_API std::string ArchStrerror(int errorCode); ///@} diff --git a/pxr/base/lib/arch/error.h b/pxr/base/lib/arch/error.h index 3ff42e5fc0..a66c16c73c 100644 --- a/pxr/base/lib/arch/error.h +++ b/pxr/base/lib/arch/error.h @@ -28,6 +28,7 @@ /// \ingroup group_arch_Diagnostics /// Low-level fatal error reporting. +#include "pxr/base/arch/api.h" #include "pxr/base/arch/defines.h" #include "pxr/base/arch/functionLite.h" #include @@ -40,6 +41,7 @@ /// \param fileName The name of the file that \c Arch_Error was called from. /// /// \private +ARCH_API void Arch_Error(const char* msg, const char* funcName, size_t lineNo, const char* fileName); @@ -51,6 +53,7 @@ void Arch_Error(const char* msg, const char* funcName, /// \param fileName The name of the file that \c Arch_Warning was called from. /// /// \private +ARCH_API void Arch_Warning(const char* msg, const char* funcName, size_t lineNo, const char* fileName); diff --git a/pxr/base/lib/arch/fileSystem.h b/pxr/base/lib/arch/fileSystem.h index 9e7689b36e..4ad781edfd 100644 --- a/pxr/base/lib/arch/fileSystem.h +++ b/pxr/base/lib/arch/fileSystem.h @@ -28,6 +28,7 @@ /// \ingroup group_arch_SystemFunctions /// Architecture dependent file system access +#include "pxr/base/arch/api.h" #include "pxr/base/arch/defines.h" #include "pxr/base/arch/inttypes.h" #include @@ -51,8 +52,8 @@ /// Return the length of a file in bytes. /// /// Returns -1 if the file cannot be opened/read. -int64_t ArchGetFileLength(const char *fileName); -int64_t ArchGetFileLength(FILE *file); +ARCH_API int64_t ArchGetFileLength(const char *fileName); +ARCH_API int64_t ArchGetFileLength(FILE *file); /// Returns true if the data in \c stat struct \p st indicates that the target /// file or directory is writable. @@ -60,25 +61,25 @@ int64_t ArchGetFileLength(FILE *file); /// This returns true if the struct pointer is valid, and the stat indicates /// the target is writable by the effective user, effective group, or all /// users. -bool ArchStatIsWritable(const struct stat *st); +ARCH_API bool ArchStatIsWritable(const struct stat *st); /// Returns the modification time (mtime) in seconds from the stat struct. /// /// This function returns the modification time with as much precision as is /// available in the stat structure for the current platform. -double ArchGetModificationTime(const struct stat& st); +ARCH_API double ArchGetModificationTime(const struct stat& st); /// Returns the access time (atime) in seconds from the stat struct. /// /// This function returns the access time with as much precision as is /// available in the stat structure for the current platform. -double ArchGetAccessTime(const struct stat& st); +ARCH_API double ArchGetAccessTime(const struct stat& st); /// Returns the status change time (ctime) in seconds from the stat struct. /// /// This function returns the status change time with as much precision as is /// available in the stat structure for the current platform. -double ArchGetStatusChangeTime(const struct stat& st); +ARCH_API double ArchGetStatusChangeTime(const struct stat& st); /// Return the path to a temporary directory for this platform. /// @@ -89,7 +90,7 @@ double ArchGetStatusChangeTime(const struct stat& st); /// see "man hier"). The returned string will not have a trailing slash. /// /// This routine is threadsafe and will not perform any memory allocations. -const char *ArchGetTmpDir(); +ARCH_API const char *ArchGetTmpDir(); /// Make a temporary file name, in a system-determined temporary directory. /// @@ -104,6 +105,7 @@ const char *ArchGetTmpDir(); /// \warning This call opens a security hole because of the race between /// choosing the name and opening the file. This call should be avoided in /// favor of \c ArchMakeTmpFile(). +ARCH_API std::string ArchMakeTmpFileName(const std::string& prefix, const std::string& suffix = std::string()); @@ -116,6 +118,7 @@ std::string ArchMakeTmpFileName(const std::string& prefix, /// pathname. Returns -1 on failure and errno is set. /// /// The call is threadsafe. +ARCH_API int ArchMakeTmpFile(const std::string& prefix, std::string* pathname = 0); /// Create a temporary file, in a given temporary directory. @@ -126,6 +129,7 @@ int ArchMakeTmpFile(const std::string& prefix, std::string* pathname = 0); /// path to the file in pathname. Returns -1 on failure and errno is set. /// /// The call is threadsafe. +ARCH_API int ArchMakeTmpFile(const std::string& tmpdir, const std::string& prefix, std::string* pathname = 0); @@ -137,26 +141,28 @@ int ArchMakeTmpFile(const std::string& tmpdir, /// errno is set. /// /// The call is threadsafe. +ARCH_API std::string ArchMakeTmpSubdir(const std::string& tmpdir, const std::string& prefix); /// Return all automounted directories. /// /// Returns a set of all directories that are automount points for the host. +ARCH_API std::set ArchGetAutomountDirectories(); // Helper 'deleter' for use with std::unique_ptr for file mappings. #if defined(ARCH_OS_WINDOWS) struct Arch_Unmapper { - void operator()(char *mapStart) const; - void operator()(char const *mapStart) const; + ARCH_API void operator()(char *mapStart) const; + ARCH_API void operator()(char const *mapStart) const; }; #else // assume POSIX struct Arch_Unmapper { Arch_Unmapper() : _length(~0) {} explicit Arch_Unmapper(size_t length) : _length(length) {} - void operator()(char *mapStart) const; - void operator()(char const *mapStart) const; + ARCH_API void operator()(char *mapStart) const; + ARCH_API void operator()(char const *mapStart) const; private: size_t _length; }; @@ -171,24 +177,28 @@ using ArchMutableFileMapping = std::unique_ptr; /// Privately map the passed \p file into memory and return a unique_ptr to the /// read-only mapped contents. The contents may not be modified. +ARCH_API ArchConstFileMapping ArchMapFileReadOnly(FILE *file); /// Privately map the passed \p file into memory and return a unique_ptr to the /// copy-on-write mapped contents. If modified, the affected pages are /// dissociated from the underlying file and become backed by the system's swap /// or page-file storage. Edits are not carried through to the underlying file. +ARCH_API ArchMutableFileMapping ArchMapFileReadWrite(FILE *file); /// Read up to \p count bytes from \p offset in \p file into \p buffer. The /// file position indicator for \p file is not changed. Return the number of /// bytes read, or zero if at end of file. Return -1 in case of an error, with /// errno set appropriately. +ARCH_API int64_t ArchPRead(FILE *file, void *buffer, size_t count, int64_t offset); /// Write up to \p count bytes from \p buffer to \p file at \p offset. The file /// position indicator for \p file is not changed. Return the number of bytes /// written, possibly zero if none written. Return -1 in case of an error, with /// errno set appropriately. +ARCH_API int64_t ArchPWrite(FILE *file, void const *bytes, size_t count, int64_t offset); ///@} diff --git a/pxr/base/lib/arch/function.h b/pxr/base/lib/arch/function.h index 4ac19d43f9..d2b7fc4663 100644 --- a/pxr/base/lib/arch/function.h +++ b/pxr/base/lib/arch/function.h @@ -31,6 +31,7 @@ /// This file needs to be public but shouldn't be included directly by /// anything outside of \c lib/tf. +#include "pxr/base/arch/api.h" #include "pxr/base/arch/functionLite.h" #include @@ -41,6 +42,7 @@ /// reconstruct a well formatted function name. /// /// \ingroup group_arch_Diagnostic +ARCH_API std::string ArchGetPrettierFunctionName(const std::string &function, const std::string &prettyFunction); diff --git a/pxr/base/lib/arch/hash.h b/pxr/base/lib/arch/hash.h index 90d568b417..728d4813a8 100644 --- a/pxr/base/lib/arch/hash.h +++ b/pxr/base/lib/arch/hash.h @@ -27,6 +27,7 @@ /// \file arch/hash.h /// Hash functions. +#include "pxr/base/arch/api.h" #include "pxr/base/arch/inttypes.h" /// Hash \a len bytes of \a data. @@ -36,9 +37,9 @@ /// passing it on as \p seed. Note that this is *not* equivalent to hashing the /// contiguous pieces as a whole. Support for that may be added in future. /// -uint32_t ArchHash(const char *data, size_t len); +ARCH_API uint32_t ArchHash(const char *data, size_t len); /// \overload -uint32_t ArchHash(const char *data, size_t len, uint32_t seed); +ARCH_API uint32_t ArchHash(const char *data, size_t len, uint32_t seed); /// Hash \a len bytes of \a data. /// @@ -47,8 +48,8 @@ uint32_t ArchHash(const char *data, size_t len, uint32_t seed); /// passing it on as \p seed. Note that this is *not* equivalent to hashing the /// contiguous pieces as a whole. Support for that may be added in future. /// -uint64_t ArchHash64(const char *data, size_t len); +ARCH_API uint64_t ArchHash64(const char *data, size_t len); /// \overload -uint64_t ArchHash64(const char *data, size_t len, uint64_t seed); +ARCH_API uint64_t ArchHash64(const char *data, size_t len, uint64_t seed); #endif // ARCH_HASH_H diff --git a/pxr/base/lib/arch/mallocHook.h b/pxr/base/lib/arch/mallocHook.h index 33d67db639..f5d1618be4 100644 --- a/pxr/base/lib/arch/mallocHook.h +++ b/pxr/base/lib/arch/mallocHook.h @@ -28,6 +28,8 @@ /// \ingroup group_arch_Memory /// Routines for controlling malloc behavior. +#include "pxr/base/arch/api.h" + #include #include @@ -39,7 +41,7 @@ /// determine if it is the active allocator. /// /// \ingroup group_arch_Memory -bool ArchIsPtmallocActive(); +ARCH_API bool ArchIsPtmallocActive(); /// Return true if the C++ STL allocator was requested to be turned off. /// @@ -48,7 +50,7 @@ bool ArchIsPtmallocActive(); /// platforms. /// /// \ingroup group_arch_Memory -bool ArchIsStlAllocatorOff(); +ARCH_API bool ArchIsStlAllocatorOff(); /// \class ArchMallocHook /// \ingroup group_arch_Memory @@ -80,6 +82,7 @@ class ArchMallocHook { /// If initialization fails, \c false is returned and \p *errMsg is set /// accordingly. If \c *this has already been initialized, calling \c /// Initialize() a second time will fail. + ARCH_API bool Initialize(void* (*mallocWrapper)(size_t, const void*), void* (*reallocWrapper)(void*, size_t, const void*), void* (*memalignWrapper)(size_t, size_t, const void*), @@ -91,6 +94,7 @@ class ArchMallocHook { /// In order for this function to work properly, \c this cannot be a local /// or dynamically initialized variable; rather, \c this must be a global /// variable, to ensure zero-initialization. + ARCH_API bool IsInitialized(); /// Call the original system \c malloc() function. @@ -99,6 +103,7 @@ class ArchMallocHook { /// system-supplied malloc() call. For speed reasons, no safety checks /// are performed; in particular, calling this function without having /// successfully initialized \p *this will likely crash your program. + ARCH_API void* Malloc(size_t nBytes) { return (*_underlyingMallocFunc)(nBytes); } @@ -109,6 +114,7 @@ class ArchMallocHook { /// system-supplied \c realloc() call. For speed reasons, no safety checks /// are performed; in particular, calling this function without having /// successfully initialized \p *this will likely crash your program. + ARCH_API void* Realloc(void* ptr, size_t nBytes) { return (*_underlyingReallocFunc)(ptr, nBytes); } @@ -119,6 +125,7 @@ class ArchMallocHook { /// system-supplied \c memalign() call. For speed reasons, no safety checks /// are performed; in particular, calling this function without having /// successfully initialized \p *this will likely crash your program. + ARCH_API void* Memalign(size_t alignment, size_t nBytes) { return (*_underlyingMemalignFunc)(alignment, nBytes); } @@ -129,6 +136,7 @@ class ArchMallocHook { /// system-supplied \c free() call. For speed reasons, no safety checks /// are performed; in particular, calling this function without having /// successfully initialized \p *this will likely crash your program. + ARCH_API void Free(void* ptr) { (*_underlyingFreeFunc)(ptr); } diff --git a/pxr/base/lib/arch/nap.h b/pxr/base/lib/arch/nap.h index 58742bff18..bd9a7ce71a 100644 --- a/pxr/base/lib/arch/nap.h +++ b/pxr/base/lib/arch/nap.h @@ -28,7 +28,9 @@ /// \ingroup group_arch_Multithreading /// Routines for very brief pauses in execution. +#include "pxr/base/arch/api.h" #include "pxr/base/arch/inttypes.h" + #if defined(ARCH_OS_WINDOWS) #include #endif @@ -41,12 +43,14 @@ /// Sleep for \c n/100 seconds. Note: if your intent is to simply yield the /// processors, DO NOT call this with a value of zero (as one can do with /// sginap()). Call \c ArchThreadYield() instead. +ARCH_API void ArchNap(size_t nhundredths); /// Yield to the operating system thread scheduler. /// /// Returns control to the operating system thread scheduler as a means of /// temporarily suspending the calling thread. +ARCH_API void ArchThreadYield(); /// Pause execution of the current thread. diff --git a/pxr/base/lib/arch/pixarConfig.cpp b/pxr/base/lib/arch/pixarConfig.cpp index 1f590e0ae6..eb7d60d47a 100644 --- a/pxr/base/lib/arch/pixarConfig.cpp +++ b/pxr/base/lib/arch/pixarConfig.cpp @@ -21,6 +21,7 @@ // KIND, either express or implied. See the Apache License for the specific // language governing permissions and limitations under the Apache License. // +#include "pxr/base/arch/api.h" #include "pxr/base/arch/attributes.h" #include "pxr/base/arch/stackTrace.h" #include "pxr/base/arch/systemInfo.h" @@ -36,6 +37,9 @@ using std::string; // namespace so that it can be called in archext/datetime.cpp. We // do not include its declaration in any header in arch because // we don't want to expose this in the open source distribution. +// We need to tag this function with ARCH_API to ensure it's visible +// from outside this library. +ARCH_API string Arch_GetTimezone() { diff --git a/pxr/base/lib/arch/stackTrace.h b/pxr/base/lib/arch/stackTrace.h index 4f88fbcaab..edd6c9b9a3 100644 --- a/pxr/base/lib/arch/stackTrace.h +++ b/pxr/base/lib/arch/stackTrace.h @@ -28,7 +28,9 @@ /// \ingroup group_arch_Diagnostics /// Architecture-specific call-stack tracing routines. +#include "pxr/base/arch/api.h" #include "pxr/base/arch/defines.h" + #include #include #include @@ -55,6 +57,7 @@ /// Note the use of \c char* as opposed to \c string: this is intentional, /// because we are trying to use only async-safe function from here on and /// malloc() is not async-safe. +ARCH_API void ArchLogPostMortem(const char* reason, const char* message = nullptr); /// Sets the command line that gathers call-stack info. @@ -75,6 +78,7 @@ void ArchLogPostMortem(const char* reason, const char* message = nullptr); /// \li $time: Substitutes the user time (if available, else wall time) /// /// \sa ArchLogPostMortem +ARCH_API void ArchSetPostMortem(const char* command, const char *const argv[]); /// Log session info. @@ -82,6 +86,7 @@ void ArchSetPostMortem(const char* command, const char *const argv[]); /// Optionally indicate that this is due to a crash by providing /// the path to a file containing a stack trace in \p crashStackTrace. /// +ARCH_API void ArchLogSessionInfo(const char *crashStackTrace=NULL); /// Sets the command line to log sessions. @@ -105,6 +110,7 @@ void ArchLogSessionInfo(const char *crashStackTrace=NULL); /// \li $stack: Substitutes the crash stack string (only in crashArgv) /// /// \sa ArchLogSessionInfo +ARCH_API void ArchSetLogSession(const char* command, const char* const argv[], const char* const crashArgv[]); @@ -113,9 +119,11 @@ void ArchSetLogSession(const char* command, /// /// This function registers ArchLogSessionInfo() and records the current /// timestamp, to send up-time to the DB upon exiting. +ARCH_API void ArchEnableSessionLogging(); /// Print a stack trace to the given FILE pointer. +ARCH_API void ArchPrintStackTrace(FILE *fout, const std::string& programName, const std::string& reason); @@ -123,10 +131,12 @@ void ArchPrintStackTrace(FILE *fout, /// Print a stack trace to the given FILE pointer. /// This function uses ArchGetProgramInfoForErrors as the \c programName. /// \overload +ARCH_API void ArchPrintStackTrace(FILE *fout, const std::string& reason); /// Print a stack trace to the given ostream. /// \overload +ARCH_API void ArchPrintStackTrace(std::ostream& out, const std::string& programName, const std::string& reason); @@ -134,6 +144,7 @@ void ArchPrintStackTrace(std::ostream& out, /// Print a stack trace to the given iostream. /// This function uses ArchGetProgramInfoForErrors as the \c programName. /// \overload +ARCH_API void ArchPrintStackTrace(std::ostream& out, const std::string& reason); /// A callback to get a symbolic representation of an address. @@ -144,43 +155,52 @@ typedef std::function ArchStackTraceCallback; /// The callback returns a string for an address in a stack trace, typically /// including the name of the function containing the address. \p cb may be \c /// NULL to use a default implementation. +ARCH_API void ArchSetStackTraceCallback(const ArchStackTraceCallback& cb); /// Returns the callback to get a symbolic representation of an address. /// \sa ArchSetStackTraceCallback +ARCH_API void ArchGetStackTraceCallback(ArchStackTraceCallback* cb); /// Returns the set value for the application's launch time. /// The timestamp for this value is set when the arch library is initialized. +ARCH_API time_t ArchGetAppLaunchTime(); /// Enables or disables the automatic logging of crash information. /// /// This function controls whether the stack trace and build information is /// automatically caught and stored to an internal database when a fatal crash -/// occurs. +/// occurs. +ARCH_API void ArchSetFatalStackLogging(bool flag); /// Returns whether automatic logging of fatal crashes is enabled /// This is set to false by default. /// \see ArchSetFatalStackLogging +ARCH_API bool ArchGetFatalStackLogging(); /// Sets the program name to be used in diagnostic output /// /// The default value is initialized to ArchGetExecutablePath(). +ARCH_API void ArchSetProgramNameForErrors(const char * progName); /// Returns the currently set program name for reporting errors. /// Defaults to ArchGetExecutablePath(). +ARCH_API const char * ArchGetProgramNameForErrors(); /// Sets additional program info to be reported to the terminal in case of a /// fatal error. +ARCH_API void ArchSetProgramInfoForErrors( const std::string& key, const std::string& value ); /// Returns currently set program info. /// \see ArchSetExtraLogInfoForErrors +ARCH_API std::string ArchGetProgramInfoForErrors(const std::string& key); /// Stores (or removes if \p text is NULL) a pointer to additional log data @@ -188,6 +208,7 @@ std::string ArchGetProgramInfoForErrors(const std::string& key); /// that the pointer \p text is copied, not the pointed-to text. Thus it is /// the caller's responsibility to ensure that \p text is valid until the /// caller removes it by invoking this function again with text==NULL. +ARCH_API void ArchSetExtraLogInfoForErrors(const std::string &key, char const *text); /// Logs a stack trace to a file in /var/tmp. @@ -200,6 +221,7 @@ void ArchSetExtraLogInfoForErrors(const std::string &key, char const *text); /// reporting that a stack trace has been taken and what file it has been /// written to. And if \c fatal is true, then the stack trace will be added /// to the stack_trace database table. +ARCH_API void ArchLogStackTrace(const std::string& progName, const std::string& reason, bool fatal = false, @@ -215,6 +237,7 @@ void ArchLogStackTrace(const std::string& progName, /// reporting that a stack trace has been taken and what file it has been /// written to. And if \c fatal is true, then the stack trace will be added /// to the stack_trace database table. +ARCH_API void ArchLogStackTrace(const std::string& reason, bool fatal = false, const std::string& sessionLog = ""); @@ -223,6 +246,7 @@ void ArchLogStackTrace(const std::string& reason, /// /// This function will return a vector of strings containing the current /// stack. The vector will be of maximum size \p maxDepth. +ARCH_API std::vector ArchGetStackTrace(size_t maxDepth); @@ -230,6 +254,7 @@ std::vector ArchGetStackTrace(size_t maxDepth); /// /// This function saves at maximum \c maxDepth frames of the current stack /// into the vector \c frames. +ARCH_API void ArchGetStackFrames(size_t maxDepth, std::vector *frames); /// Save frames of current stack. @@ -238,10 +263,12 @@ void ArchGetStackFrames(size_t maxDepth, std::vector *frames); /// into the vector \p frames, skipping the first \p numFramesToSkipAtTop /// frames. The first frame will be at depth \p numFramesToSkipAtTop and the /// last at depth \p numFramesToSkipAtTop + \p maxDepth - 1. +ARCH_API void ArchGetStackFrames(size_t maxDepth, size_t numFramesToSkipAtTop, std::vector *frames); /// Print stack frames to the given iostream. +ARCH_API void ArchPrintStackFrames(std::ostream& out, const std::vector &frames); @@ -262,6 +289,7 @@ typedef void (*ArchCrashHandlerSystemCB)(void* userData); /// setitimer or other calls to alarm, and this function uses non-locking fork /// and exec if available so should not generally be used except following a /// catastrophe. +ARCH_API int ArchCrashHandlerSystemv(const char* pathname, char *const argv[], int timeout, ArchCrashHandlerSystemCB callback, void* userData); @@ -273,6 +301,7 @@ int ArchCrashHandlerSystemv(const char* pathname, char *const argv[], /// remains alive during the crash. It aborts if it fails to crash. /// /// \private +ARCH_API void ArchTestCrash(bool spawnthread); #if defined(ARCH_OS_DARWIN) diff --git a/pxr/base/lib/arch/symbols.h b/pxr/base/lib/arch/symbols.h index 56a2e1b553..0f4df1ea0e 100644 --- a/pxr/base/lib/arch/symbols.h +++ b/pxr/base/lib/arch/symbols.h @@ -28,6 +28,7 @@ /// \ingroup group_arch_Diagnostics /// Architecture-specific symbol lookup routines. +#include "pxr/base/arch/api.h" #include /// Returns information about the address \p address in the running program. @@ -43,6 +44,7 @@ /// This will return \c false if \c NULL is passed to \p address. /// /// \ingroup group_arch_Diagnostics +ARCH_API bool ArchGetAddressInfo(void* address, std::string* objectPath, void** baseAddress, std::string* symbolName, void** symbolAddress); diff --git a/pxr/base/lib/arch/systemInfo.h b/pxr/base/lib/arch/systemInfo.h index ade8bd063f..cc2a4267eb 100644 --- a/pxr/base/lib/arch/systemInfo.h +++ b/pxr/base/lib/arch/systemInfo.h @@ -28,12 +28,14 @@ /// \ingroup group_arch_SystemFunctions /// Provide architecture-specific system information. +#include "pxr/base/arch/api.h" #include /// \addtogroup group_arch_SystemFunctions ///@{ /// Return current working directory as a string. +ARCH_API std::string ArchGetCwd(); /// Return user's home directory. @@ -42,14 +44,17 @@ std::string ArchGetCwd(); /// returned. Otherwise, the home directory of the user with the specified /// login is returned. If the home directory cannot be determined, the empty /// string is returned. +ARCH_API std::string ArchGetHomeDirectory(const std::string &login = std::string()); /// Return user name. /// /// If the user name cannot determined, the empty string is returned. +ARCH_API std::string ArchGetUserName(); /// Return the path to the program's executable. +ARCH_API std::string ArchGetExecutablePath(); ///@} diff --git a/pxr/base/lib/arch/testArchAbi.h b/pxr/base/lib/arch/testArchAbi.h index 9117ab0014..d13ad187cb 100644 --- a/pxr/base/lib/arch/testArchAbi.h +++ b/pxr/base/lib/arch/testArchAbi.h @@ -21,19 +21,13 @@ // KIND, either express or implied. See the Apache License for the specific // language governing permissions and limitations under the Apache License. // -#if defined(_WIN32) -#ifndef ARCH_ABI_API -#define ARCH_ABI_API __declspec(dllimport) -#endif -#else -#define ARCH_ABI_API __attribute__((visibility("default"))) -#endif +#include "pxr/base/arch/api.h" -struct ARCH_ABI_API ArchAbiBase1 { +struct ArchAbiBase1 { void* dummy; }; -struct ARCH_ABI_API ArchAbiBase2 { +struct ArchAbiBase2 { virtual ~ArchAbiBase2() { } virtual const char* name() const = 0; }; diff --git a/pxr/base/lib/arch/threads.h b/pxr/base/lib/arch/threads.h index 8cbe5f88da..d804a243ad 100644 --- a/pxr/base/lib/arch/threads.h +++ b/pxr/base/lib/arch/threads.h @@ -28,8 +28,10 @@ /// \ingroup group_arch_Multithreading /// Architecture-specific thread function calls. +#include "pxr/base/arch/api.h" + /// Return true if the calling thread is the main thread, false otherwise. /// \ingroup group_arch_Multithreading -bool ArchIsMainThread(); +ARCH_API bool ArchIsMainThread(); #endif // ARCH_THREADS_H diff --git a/pxr/base/lib/arch/timing.h b/pxr/base/lib/arch/timing.h index 1193cc4214..dc5902a22d 100644 --- a/pxr/base/lib/arch/timing.h +++ b/pxr/base/lib/arch/timing.h @@ -28,6 +28,7 @@ /// \ingroup group_arch_SystemFunctions /// High-resolution, low-cost timing routines. +#include "pxr/base/arch/api.h" #include "pxr/base/arch/defines.h" #include "pxr/base/arch/inttypes.h" @@ -89,18 +90,22 @@ ArchGetTickTime() /// int64_t duration = ArchTicksToNanoseconds(t2 - t1); /// \endcode /// +ARCH_API int64_t ArchTicksToNanoseconds(uint64_t nTicks); /// Convert a duration measured in "ticks", as returned by /// \c ArchGetTickTime(), to seconds. +ARCH_API double ArchTicksToSeconds(uint64_t nTicks); /// Convert a duration in seconds to "ticks", as returned by /// \c ArchGetTickTime(). +ARCH_API uint64_t ArchSecondsToTicks(double seconds); /// Get nanoseconds per tick. Useful when converting ticks obtained from /// \c ArchTickTime() +ARCH_API double ArchGetNanosecondsPerTick(); ///@} diff --git a/pxr/base/lib/arch/vsnprintf.h b/pxr/base/lib/arch/vsnprintf.h index 8d8064ea5f..9396072fee 100644 --- a/pxr/base/lib/arch/vsnprintf.h +++ b/pxr/base/lib/arch/vsnprintf.h @@ -28,6 +28,7 @@ /// \ingroup group_arch_Strings /// Architecture dependent memory-safe sprintf capability +#include "pxr/base/arch/api.h" #include "pxr/base/arch/attributes.h" #include #include @@ -48,6 +49,7 @@ /// You probably want to use the functionality of this call via /// \c TfStringPrintf(). /// +ARCH_API int ArchVsnprintf(char *str, size_t size, const char *format, va_list ap) #ifndef doxygen ARCH_PRINTF_FUNCTION(3, 0) @@ -70,6 +72,7 @@ int ArchVsnprintf(char *str, size_t size, const char *format, va_list ap) /// into \c ArchStringPrintf() as in the above example (i.e. \c caller.c_str() /// as opposed to just passing \c caller). /// +ARCH_API std::string ArchStringPrintf(const char *fmt, ...) #ifndef doxygen ARCH_PRINTF_FUNCTION(1, 2) @@ -84,6 +87,7 @@ std::string ArchStringPrintf(const char *fmt, ...) /// the value of \c ap is undefined after the call. A functions that calls \c /// ArchVStringPrintf() should call \c va_end(ap) itself afterwards. /// +ARCH_API std::string ArchVStringPrintf(const char *fmt, va_list ap) #ifndef doxygen ARCH_PRINTF_FUNCTION(1, 0) From d35ad5d4a6078a2a5001189b77cd02b5623a2337 Mon Sep 17 00:00:00 2001 From: pixar-oss Date: Tue, 6 Sep 2016 12:45:37 -0700 Subject: [PATCH 087/380] Allow collection membership to be specified per-path. (Internal change: 1651428) --- pxr/usdImaging/lib/usdImaging/delegate.cpp | 54 ++++++++++++++++++---- pxr/usdImaging/lib/usdImaging/delegate.h | 16 ++++++- 2 files changed, 61 insertions(+), 9 deletions(-) diff --git a/pxr/usdImaging/lib/usdImaging/delegate.cpp b/pxr/usdImaging/lib/usdImaging/delegate.cpp index 2fb3a5e04c..ec9872ca30 100644 --- a/pxr/usdImaging/lib/usdImaging/delegate.cpp +++ b/pxr/usdImaging/lib/usdImaging/delegate.cpp @@ -1614,6 +1614,32 @@ UsdImagingDelegate::_UpdateSingleValue(SdfPath const& usdPath, int requestBits) } } +// Given a a map from paths to purpose mask values, find the longest prefix +// of usdPath in the map, and return the corresponding value, or PurposeNone +// if no prefix is found. +static int +_GetPurposeMask(const UsdImagingDelegate::CollectionMembershipMap &map, + const SdfPath &path) +{ + // Use upper_bound to find the first item that's greater than path. + // Then search backwards to find the longest prefix of path, if there's + // a prefix in the map. + // + // In the worst case, this is log(N) + N in the number of paths in the map. + // If we expect these maps to get large, we can consider other approaches, + // such as using an unordered_map and calling find() repeatedly on parent + // paths. + auto it = map.upper_bound(path); + while (it != map.begin()) { + it = std::prev(it); + if (path.HasPrefix(it->first)) { + return it->second; + } + } + + return UsdImagingDelegate::PurposeNone; +} + /*virtual*/ bool UsdImagingDelegate::IsInCollection(SdfPath const& id, @@ -1633,7 +1659,11 @@ UsdImagingDelegate::IsInCollection(SdfPath const& id, // lookup user-configured collections int purposeMask = PurposeNone; - TfMapLookup(_collectionMap, collectionName, &purposeMask); + auto it = _collectionMap.find(collectionName); + if (it != _collectionMap.end()) { + purposeMask = _GetPurposeMask(it->second, usdPath); + } + bool res = false; if (purpose == UsdGeomTokens->default_) { @@ -2109,13 +2139,21 @@ void UsdImagingDelegate::SetInCollection(TfToken const &collectionName, int purposeMask) { - CollectionMap::iterator it = _collectionMap.find(collectionName); - if (it != _collectionMap.end()) { - if (it->second == purposeMask) return; // nothing changed - it->second = purposeMask; - } else { - _collectionMap.insert(std::make_pair(collectionName, purposeMask)); - } + // Create a membership map containing just the absolute root. + CollectionMembershipMap membershipMap; + membershipMap.insert( + std::make_pair(SdfPath::AbsoluteRootPath(), purposeMask)); + _collectionMap[collectionName] = std::move(membershipMap); + + GetRenderIndex().GetChangeTracker().MarkCollectionDirty(collectionName); +} + +void +UsdImagingDelegate::TransferCollectionMembershipMap( + TfToken const &collectionName, + CollectionMembershipMap &&membershipMap) +{ + _collectionMap[collectionName] = membershipMap; GetRenderIndex().GetChangeTracker().MarkCollectionDirty(collectionName); } diff --git a/pxr/usdImaging/lib/usdImaging/delegate.h b/pxr/usdImaging/lib/usdImaging/delegate.h index 87fc97eb37..7a3af27d5f 100644 --- a/pxr/usdImaging/lib/usdImaging/delegate.h +++ b/pxr/usdImaging/lib/usdImaging/delegate.h @@ -51,8 +51,10 @@ #include "pxr/base/tf/hashmap.h" #include "pxr/base/tf/hashset.h" +#include #include #include +#include #include TF_DECLARE_WEAK_PTRS(UsdImagingDelegate); @@ -74,7 +76,10 @@ class UsdImagingDelegate : public HdSceneDelegate, public TfWeakBase { public: typedef TfHashMap RigidXformOverridesMap; - typedef TfHashMap CollectionMap; + typedef boost::container::flat_map + CollectionMembershipMap; + typedef TfHashMap + CollectionMap; UsdImagingDelegate(); @@ -218,6 +223,15 @@ class UsdImagingDelegate : public HdSceneDelegate, public TfWeakBase { /// entire delegate. IsInCollection responds based on this setting. void SetInCollection(TfToken const &collectionName, int purposeMask); + /// Sets the membership of user-defined \p collectionName as determined + /// by \p membershipMap, a SdfPathMap to purposeMask (int) from rprim + /// memership (or not) can be determined. + /// + /// IsInCollection responds based on this setting. + void TransferCollectionMembershipMap( + TfToken const &collectionName, + CollectionMembershipMap &&membershipMap); + /// Sets the collection map /// (discard previously set existing map by SetInCollection) void SetCollectionMap(CollectionMap const &collectionMap); From 9587600b7a0abe075b444aa1654c5b83c866faf8 Mon Sep 17 00:00:00 2001 From: poljere Date: Tue, 6 Sep 2016 12:51:44 -0700 Subject: [PATCH 088/380] [Hdx] Extract the clip planes from the camera, set them in the render pass state and make sure the render pass state is binded/unbinded (Internal change: 1651450) --- pxr/imaging/lib/hdx/drawTargetTask.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/pxr/imaging/lib/hdx/drawTargetTask.cpp b/pxr/imaging/lib/hdx/drawTargetTask.cpp index 40c7e3eae1..f1d6220466 100644 --- a/pxr/imaging/lib/hdx/drawTargetTask.cpp +++ b/pxr/imaging/lib/hdx/drawTargetTask.cpp @@ -199,6 +199,10 @@ HdxDrawTargetTask::_Sync(HdTaskContext* ctx) const GfMatrix4d &projMatrix = projMatrixVt.Get(); GfMatrix4d projectionMatrix = projMatrix * yflip; + const VtValue &vClipPlanes = camera->Get(HdTokens->clipPlanes); + const HdRenderPassState::ClipPlanesVector &clipPlanes = + vClipPlanes.Get(); + GfVec2i const &resolution = drawTarget->GetGlfDrawTarget()->GetSize(); GfVec4d viewport(0, 0, resolution[0], resolution[1]); @@ -219,6 +223,8 @@ HdxDrawTargetTask::_Sync(HdTaskContext* ctx) renderPassState->SetLightingShader(simpleLightingShader); renderPassState->SetCamera(viewMatrix, projectionMatrix, viewport); + renderPassState->SetClipPlanes(clipPlanes); + simpleLightingContext->SetCamera(viewMatrix, projectionMatrix); if (lightingContext) { @@ -296,7 +302,9 @@ HdxDrawTargetTask::_Execute(HdTaskContext* ctx) _renderPasses[renderPassIdx].pass.get(); HdRenderPassStateSharedPtr renderPassState = _renderPasses[renderPassIdx].renderPassState; + renderPassState->Bind(); renderPass->Execute(renderPassState); + renderPassState->Unbind(); } if (oldAlphaToCoverage) { From b315446106f129c9c3170063e1ff52fa99be1648 Mon Sep 17 00:00:00 2001 From: pixar-oss Date: Tue, 6 Sep 2016 13:57:59 -0700 Subject: [PATCH 089/380] Getting Python traceback and exception string no longer clobber exception state. Previously TfPyExceptionState::GetExceptionString() and TfPyGetTraceback() could clobber the current exception state. This means raising an error like a coding error that should bubble up to Python as an exception could instead cause the exception state to be cleared, either leading to no error in Python or a SystemError when no result was produced but no error was set. Now we have the RAII TfPyExceptionStateScope type that saves and restores the exception state in its c'tor and d'tor, respectively. We put one of those around each of the GetExceptionString() and TfPyGetTraceback() implementations to ensure they don't mess up the exception state. (Internal change: 1651753) --- pxr/base/lib/tf/pyErrorInternal.cpp | 22 ++++++++++++++++++++++ pxr/base/lib/tf/pyErrorInternal.h | 19 +++++++++++++++++++ pxr/base/lib/tf/pyExceptionState.cpp | 6 ++++-- pxr/base/lib/tf/pyUtils.cpp | 6 ++++-- 4 files changed, 49 insertions(+), 4 deletions(-) diff --git a/pxr/base/lib/tf/pyErrorInternal.cpp b/pxr/base/lib/tf/pyErrorInternal.cpp index 7aa5e3311a..629ceb3b98 100644 --- a/pxr/base/lib/tf/pyErrorInternal.cpp +++ b/pxr/base/lib/tf/pyErrorInternal.cpp @@ -68,3 +68,25 @@ void Tf_PyRestorePythonExceptionState(TfPyExceptionState state) { // *without* decrementing the reference count (since it has been stolen). state.Release(); } + +TfPyExceptionStateScope::TfPyExceptionStateScope() : + _state(Tf_PyFetchPythonExceptionState()) +{ + // Tf_PyFetchPythonExceptionState() clears the exception state + // but we want it back. + Restore(); +} + +TfPyExceptionStateScope::~TfPyExceptionStateScope() +{ + Restore(); +} + +void +TfPyExceptionStateScope::Restore() +{ + // Note that Tf_PyRestorePythonExceptionState() leaves _state with + // a reference to the state, unlike PyErr_Restore, because it makes + // a copy of _state and that bumps the reference counts. + Tf_PyRestorePythonExceptionState(_state); +} diff --git a/pxr/base/lib/tf/pyErrorInternal.h b/pxr/base/lib/tf/pyErrorInternal.h index 2176c49715..d07afed2a7 100644 --- a/pxr/base/lib/tf/pyErrorInternal.h +++ b/pxr/base/lib/tf/pyErrorInternal.h @@ -37,4 +37,23 @@ void Tf_PyRestorePythonExceptionState(TfPyExceptionState state); boost::python::handle<> Tf_PyGetErrorExceptionClass(); void Tf_PySetErrorExceptionClass(boost::python::object const &cls); +/// RAII class to save and restore the Python exception state. The client +/// must hold the GIL during all methods, including the c'tor and d'tor. +class TfPyExceptionStateScope { +public: + // Save the current exception state but don't unset it. + TfPyExceptionStateScope(); + TfPyExceptionStateScope(const TfPyExceptionStateScope&) = delete; + TfPyExceptionStateScope& operator=(const TfPyExceptionStateScope&) = delete; + + // Restore the exception state as it was in the c'tor. + ~TfPyExceptionStateScope(); + + // Restore the exception state as it was in the c'tor. + void Restore(); + +private: + TfPyExceptionState _state; +}; + #endif // TF_PYERRORINTERNAL_H diff --git a/pxr/base/lib/tf/pyExceptionState.cpp b/pxr/base/lib/tf/pyExceptionState.cpp index 75c49397ef..62fd5064d1 100644 --- a/pxr/base/lib/tf/pyExceptionState.cpp +++ b/pxr/base/lib/tf/pyExceptionState.cpp @@ -21,7 +21,7 @@ // KIND, either express or implied. See the Apache License for the specific // language governing permissions and limitations under the Apache License. // -#include "pxr/base/tf/pyExceptionState.h" +#include "pxr/base/tf/pyErrorInternal.h" #include #include @@ -34,6 +34,9 @@ TfPyExceptionState::GetExceptionString() const { TfPyLock lock; string s; + // Save the exception state so we can restore it -- getting the exception + // string should not affect the exception state. + TfPyExceptionStateScope exceptionStateScope; try { object tbModule(handle<>(PyImport_ImportModule("traceback"))); object exception = tbModule.attr("format_exception")(_type, _value, @@ -44,7 +47,6 @@ TfPyExceptionState::GetExceptionString() const } } catch (boost::python::error_already_set const &) { // Just ignore the exception. - PyErr_Clear(); } return s; } diff --git a/pxr/base/lib/tf/pyUtils.cpp b/pxr/base/lib/tf/pyUtils.cpp index 5ce553985e..21bf14c3ff 100644 --- a/pxr/base/lib/tf/pyUtils.cpp +++ b/pxr/base/lib/tf/pyUtils.cpp @@ -25,6 +25,7 @@ #include "pxr/base/tf/errorMark.h" #include "pxr/base/tf/pyEnum.h" #include "pxr/base/tf/pyError.h" +#include "pxr/base/tf/pyErrorInternal.h" #include "pxr/base/tf/pyInterpreter.h" #include "pxr/base/tf/pyLock.h" #include "pxr/base/tf/pyUtils.h" @@ -279,6 +280,9 @@ vector TfPyGetTraceback() return result; TfPyLock lock; + // Save the exception state so we can restore it -- getting a traceback + // should not affect the exception state. + TfPyExceptionStateScope exceptionStateScope; try { object tbModule(handle<>(PyImport_ImportModule("traceback"))); object stack = tbModule.attr("format_stack")(); @@ -290,9 +294,7 @@ vector TfPyGetTraceback() } } catch (boost::python::error_already_set const &) { TfPyConvertPythonExceptionToTfErrors(); - PyErr_Clear(); } - return result; } From 1e7fff0d13521ca9ebfa3ccb27cec814ded9b177 Mon Sep 17 00:00:00 2001 From: poljere Date: Tue, 6 Sep 2016 13:58:23 -0700 Subject: [PATCH 090/380] Texture mip maps can now be loaded from disk if the chain is provided and it is valid. [glf] Added new function GetNumMipLevels in base class glf/baseTextureData, the function will return the number of mip levels available. - Most of the work to support loading of mipmaps happened in uvTextureData which is now aware of the fact that some texture might provide mips and, if so, we might need to load them if they are correct. - The rendering work happens in baseTexture.cpp which now knows about mips provided by the user and it will send them to the driver. - To calculate the number of mips it will first try to read them from the newly implemented function and then it will use the old mechanism of trying (a certain amount of times) to open a file, in a future implementation we can add proper mip computation in oiio or tex. (Internal change: 1651785) --- pxr/imaging/lib/glf/baseTexture.cpp | 165 ++++----- pxr/imaging/lib/glf/baseTextureData.h | 18 +- pxr/imaging/lib/glf/image.h | 3 + pxr/imaging/lib/glf/oiioImage.cpp | 9 + pxr/imaging/lib/glf/uvTextureData.cpp | 337 ++++++++++++------- pxr/imaging/lib/glf/uvTextureData.h | 63 +++- pxr/imaging/lib/glf/uvTextureStorageData.cpp | 12 +- pxr/imaging/lib/glf/uvTextureStorageData.h | 19 +- 8 files changed, 394 insertions(+), 232 deletions(-) diff --git a/pxr/imaging/lib/glf/baseTexture.cpp b/pxr/imaging/lib/glf/baseTexture.cpp index 4587fc485a..ddba728319 100644 --- a/pxr/imaging/lib/glf/baseTexture.cpp +++ b/pxr/imaging/lib/glf/baseTexture.cpp @@ -128,102 +128,107 @@ GlfBaseTexture::_UpdateTexture(GlfBaseTextureDataConstPtr texData) void GlfBaseTexture::_CreateTexture(GlfBaseTextureDataConstPtr texData, - bool const generateMipmap, - int const unpackCropTop, - int const unpackCropBottom, - int const unpackCropLeft, - int const unpackCropRight) + bool const generateMipmap, + int const unpackCropTop, + int const unpackCropBottom, + int const unpackCropLeft, + int const unpackCropRight) { TRACE_FUNCTION(); if (texData and texData->HasRawBuffer()) { - glBindTexture( - GL_TEXTURE_2D, - _textureName); - - glTexParameteri( - GL_TEXTURE_2D, - GL_GENERATE_MIPMAP, - generateMipmap ? GL_TRUE - : GL_FALSE); + glBindTexture(GL_TEXTURE_2D, _textureName); + + // Check if mip maps have been requested, if so, it will either + // enable automatic generation or use the ones loaded in cpu memory + const int numMipLevels = texData->GetNumMipLevels(); + if (generateMipmap) { + if( numMipLevels > 1 ) { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, numMipLevels - 1); + } else { + glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE); + } + } + // Uncompressed textures can have cropping and other special + // behaviours. if (not texData->IsCompressed()) { if (GlfGetNumElements(texData->GLFormat()) == 1) { - GLint swizzleMask[] = {GL_RED, GL_RED, GL_RED, GL_ONE}; - glTexParameteriv( - GL_TEXTURE_2D, - GL_TEXTURE_SWIZZLE_RGBA, - swizzleMask); + GLint swizzleMask[] = {GL_RED, GL_RED, GL_RED, GL_ONE}; + glTexParameteriv( + GL_TEXTURE_2D, + GL_TEXTURE_SWIZZLE_RGBA, + swizzleMask); } - int texDataWidth = texData->ResizedWidth(); - int texDataHeight = texData->ResizedHeight(); - - int unpackRowLength = texDataWidth; - int unpackSkipPixels = 0; - int unpackSkipRows = 0; - - if (unpackCropTop < 0 or unpackCropTop > texDataHeight) { - return; - } else if (unpackCropTop > 0) { - unpackSkipRows = unpackCropTop; - texDataHeight -= unpackCropTop; - } - if (unpackCropBottom < 0 or unpackCropBottom > texDataHeight) { - return; - } else if (unpackCropBottom) { - texDataHeight -= unpackCropBottom; + // If we are not sending full mipchains to the gpu then we can + // do some extra work in the driver to prepare our textures. + if (numMipLevels == 1) { + int texDataWidth = texData->ResizedWidth(); + int texDataHeight = texData->ResizedHeight(); + int unpackRowLength = texDataWidth; + int unpackSkipPixels = 0; + int unpackSkipRows = 0; + + if (unpackCropTop < 0 or unpackCropTop > texDataHeight) { + return; + } else if (unpackCropTop > 0) { + unpackSkipRows = unpackCropTop; + texDataHeight -= unpackCropTop; + } + if (unpackCropBottom < 0 or unpackCropBottom > texDataHeight) { + return; + } else if (unpackCropBottom) { + texDataHeight -= unpackCropBottom; + } + if (unpackCropLeft < 0 or unpackCropLeft > texDataWidth) { + return; + } else { + unpackSkipPixels = unpackCropLeft; + texDataWidth -= unpackCropLeft; + } + if (unpackCropRight < 0 or unpackCropRight > texDataWidth) { + return; + } else if (unpackCropRight > 0) { + texDataWidth -= unpackCropRight; + } + + glPushClientAttrib(GL_CLIENT_PIXEL_STORE_BIT); + glPixelStorei(GL_UNPACK_ROW_LENGTH, unpackRowLength); + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + glPixelStorei(GL_UNPACK_SKIP_PIXELS, unpackSkipPixels); + glPixelStorei(GL_UNPACK_SKIP_ROWS, unpackSkipRows); } - if (unpackCropLeft < 0 or unpackCropLeft > texDataWidth) { - return; + } + + // Send the mips to the driver now, either compressed or uncompressed. + for (int i = 0 ; i < numMipLevels; i++) { + if (texData->IsCompressed()) { + glCompressedTexImage2D( GL_TEXTURE_2D, i, + texData->GLInternalFormat(), + texData->ResizedWidth(i), + texData->ResizedHeight(i), + 0, + texData->ComputeBytesUsedByMip(i), + texData->GetRawBuffer(i)); } else { - unpackSkipPixels = unpackCropLeft; - texDataWidth -= unpackCropLeft; - } - if (unpackCropRight < 0 or unpackCropRight > texDataWidth) { - return; - } else if (unpackCropRight > 0) { - texDataWidth -= unpackCropRight; + glTexImage2D( GL_TEXTURE_2D, i, + texData->GLInternalFormat(), + texData->ResizedWidth(i), + texData->ResizedHeight(i), + 0, + texData->GLFormat(), + texData->GLType(), + texData->GetRawBuffer(i)); } + } - glPushClientAttrib(GL_CLIENT_PIXEL_STORE_BIT); - glPixelStorei(GL_UNPACK_ROW_LENGTH, unpackRowLength); - glPixelStorei(GL_UNPACK_ALIGNMENT, 1); - glPixelStorei(GL_UNPACK_SKIP_PIXELS, unpackSkipPixels); - glPixelStorei(GL_UNPACK_SKIP_ROWS, unpackSkipRows); - - glTexImage2D( - GL_TEXTURE_2D, - 0, - texData->GLInternalFormat(), - texDataWidth, - texDataHeight, - 0, - texData->GLFormat(), - texData->GLType(), - texData->GetRawBuffer()); - + // Reset the OpenGL state if we have modify it previously + if (not texData->IsCompressed() and numMipLevels == 1) { glPopClientAttrib(); - } else { - // There should be no cropping when using compressed textures - TF_VERIFY(unpackCropTop == 0 && unpackCropBottom == 0 && - unpackCropLeft == 0 && unpackCropRight == 0); - - glCompressedTexImage2D( - GL_TEXTURE_2D, - 0, - texData->GLInternalFormat(), - texData->ResizedWidth(), - texData->ResizedHeight(), - 0, - texData->ComputeBytesUsed(), - texData->GetRawBuffer()); } - glBindTexture( - GL_TEXTURE_2D, - 0); - + glBindTexture(GL_TEXTURE_2D, 0); _SetMemoryUsed(texData->ComputeBytesUsed()); } } diff --git a/pxr/imaging/lib/glf/baseTextureData.h b/pxr/imaging/lib/glf/baseTextureData.h index 6b8c8efa21..60383afc19 100644 --- a/pxr/imaging/lib/glf/baseTextureData.h +++ b/pxr/imaging/lib/glf/baseTextureData.h @@ -55,9 +55,9 @@ class GlfBaseTextureData : public TfRefBase, GLenum wrapModeT; }; - virtual int ResizedWidth() const = 0; + virtual int ResizedWidth(int mipLevel = 0) const = 0; - virtual int ResizedHeight() const = 0; + virtual int ResizedHeight(int mipLevel = 0) const = 0; virtual GLenum GLInternalFormat() const = 0; @@ -69,14 +69,18 @@ class GlfBaseTextureData : public TfRefBase, virtual WrapInfo GetWrapInfo() const = 0; - virtual int ComputeBytesUsed() const = 0; + virtual size_t ComputeBytesUsed() const = 0; - virtual bool HasRawBuffer() const = 0; - - virtual unsigned char * GetRawBuffer() const = 0; + virtual size_t ComputeBytesUsedByMip(int mipLevel = 0) const = 0; virtual bool Read(int degradeLevel, bool generateMipmap) = 0; + virtual bool HasRawBuffer(int mipLevel = 0) const = 0; + + virtual unsigned char * GetRawBuffer(int mipLevel = 0) const = 0; + + virtual int GetNumMipLevels() const = 0; + virtual bool IsCompressed() const { return GlfIsCompressedFormat(GLFormat()); } @@ -88,4 +92,4 @@ class GlfBaseTextureData : public TfRefBase, }; -#endif // GLF_UVTEXTURE_DATA +#endif // GLF_BASETEXTURE_DATA diff --git a/pxr/imaging/lib/glf/image.h b/pxr/imaging/lib/glf/image.h index 599a455e83..6c2d91e4c2 100644 --- a/pxr/imaging/lib/glf/image.h +++ b/pxr/imaging/lib/glf/image.h @@ -122,6 +122,9 @@ class GlfImage : public boost::noncopyable { /// Returns the number of bytes per pixel. virtual int GetBytesPerPixel() const = 0; + /// Returns the number of mips available. + virtual int GetNumMipLevels() const = 0; + /// Returns whether the iamge is in the sRGB color space. virtual bool IsColorSpaceSRGB() const = 0; diff --git a/pxr/imaging/lib/glf/oiioImage.cpp b/pxr/imaging/lib/glf/oiioImage.cpp index 8d1d711f2b..1325cf6037 100644 --- a/pxr/imaging/lib/glf/oiioImage.cpp +++ b/pxr/imaging/lib/glf/oiioImage.cpp @@ -55,6 +55,7 @@ class Glf_OIIOImage : public GlfImage { virtual GLenum GetFormat() const; virtual GLenum GetType() const; virtual int GetBytesPerPixel() const; + virtual int GetNumMipLevels() const; virtual bool IsColorSpaceSRGB() const; @@ -371,6 +372,14 @@ Glf_OIIOImage::GetSamplerMetadata(GLenum pname, VtValue * param) const } } +/* virtual */ +int +Glf_OIIOImage::GetNumMipLevels() const +{ + // XXX Add support for mip counting + return 1; +} + /* virtual */ bool Glf_OIIOImage::_OpenForReading(std::string const & filename, int subimage) diff --git a/pxr/imaging/lib/glf/uvTextureData.cpp b/pxr/imaging/lib/glf/uvTextureData.cpp index bd069c9d74..2e8d6e4b34 100644 --- a/pxr/imaging/lib/glf/uvTextureData.cpp +++ b/pxr/imaging/lib/glf/uvTextureData.cpp @@ -56,10 +56,6 @@ GlfUVTextureData::New(std::string const &filePath, Params const ¶ms) GlfUVTextureData::~GlfUVTextureData() { - if (_rawBuffer) { - delete [] _rawBuffer; - _rawBuffer = 0; - } } GlfUVTextureData::GlfUVTextureData(std::string const &filePath, @@ -73,8 +69,7 @@ GlfUVTextureData::GlfUVTextureData(std::string const &filePath, _glInternalFormat(GL_RGB), _glFormat(GL_RGB), _glType(GL_UNSIGNED_BYTE), - _size(0), - _rawBuffer(0) + _size(0) { /* nothing */ } @@ -97,6 +92,64 @@ GlfUVTextureData_ComputeMemory(GlfImageSharedPtr const &img, return scale * numPixels * img->GetBytesPerPixel(); } +GlfUVTextureData::_DegradedImageInput +GlfUVTextureData::_GetDegradedImageInputChain(double scaleX, double scaleY, + int startMip, int lastMip) +{ + _DegradedImageInput chain(scaleX, scaleY); + for (int level = startMip; level < lastMip; level++) { + GlfImageSharedPtr image = GlfImage::OpenForReading(_filePath, level); + chain.images.push_back(image); + } + return chain; +} + +int +GlfUVTextureData::_GetNumMipLevelsValid(const GlfImageSharedPtr image) const +{ + int potentialMipLevels = image->GetNumMipLevels(); + + // Some of our texture loaders will always return an image (even if that + // mip is not available) so the easiest way to figure out the number of + // mip levels is by loading mips and looking at the sizes. + int previousWidth = image->GetWidth(); + int previousHeight = image->GetHeight(); + + // Count mips since certain formats will not fail when quering mips, + // in that case + for (int mipCounter = 1; mipCounter < 32; mipCounter++) { + GlfImageSharedPtr image = GlfImage::OpenForReading(_filePath, mipCounter); + if (not image) { + potentialMipLevels = mipCounter; + break; + } + + int currentWidth = image->GetWidth(); + int currentHeight = image->GetHeight(); + + // If previous mip and current mip are equal we have found the end of + // the chain. + if (previousWidth == currentWidth and + previousHeight == currentHeight) { + potentialMipLevels = mipCounter; + break; + } + + // We need to make sure that the previous mip and the current mip + // are consecutives powers of two. + if (previousWidth >> 1 != currentWidth or + previousHeight>> 1 != currentHeight) { + potentialMipLevels = 1; + break; + } + + previousWidth = currentWidth; + previousHeight = currentHeight; + } + + return potentialMipLevels; +} + GlfUVTextureData::_DegradedImageInput GlfUVTextureData::_ReadDegradedImageInput(bool generateMipmap, size_t targetMemory, @@ -112,10 +165,13 @@ GlfUVTextureData::_ReadDegradedImageInput(bool generateMipmap, return _DegradedImageInput(1.0, 1.0, nullImage); } + // Load full chain if needed + int numMipLevels = generateMipmap ? _GetNumMipLevelsValid(fullImage) : 1; + // Return full resolution if the targetMemory and the degradeLevel are not // set, i.e., equal to 0. if (not (targetMemory > 0 or degradeLevel > 0)) { - return _DegradedImageInput(1.0, 1.0, fullImage); + return _GetDegradedImageInputChain(1.0, 1.0, 0, numMipLevels); } // Compute the estimate required memory at full resolution. @@ -125,7 +181,7 @@ GlfUVTextureData::_ReadDegradedImageInput(bool generateMipmap, // If targetMemory is set and more than required for full resolution, // return full resolution. if (targetMemory > 0 and fullSize <= targetMemory) { - return _DegradedImageInput(1.0, 1.0, fullImage); + return _GetDegradedImageInputChain(1.0, 1.0, 0, numMipLevels); } // If no targetMemory set, use degradeLevel to determine mipLevel @@ -135,25 +191,25 @@ GlfUVTextureData::_ReadDegradedImageInput(bool generateMipmap, if (not image) { return _DegradedImageInput(1.0, 1.0, nullImage); } - return _DegradedImageInput( + + return _GetDegradedImageInputChain( double(image->GetWidth()) / fullImage->GetWidth(), - double(image->GetHeight()) / fullImage->GetHeight(), - image); + double(image->GetHeight()) / fullImage->GetHeight(), + degradeLevel, numMipLevels); } // We actually have an image requiring more memory than targetMemory. // Iterate through the levels of down-sampled images until either: // - The required memory is less or equal to targetMemory // - There are no more down-sampled images - // - An iteration limit (32) has been reached + // - An iteration limit has been reached // Remember the previous image and size to detect that there are no more // down-sampled images GlfImageSharedPtr prevImage = fullImage; size_t prevSize = fullSize; - for (int i = 1; i < 32; i++) { - + for (int i = 1; i < numMipLevels; i++) { // Open the image and is requested to use the i-th // down-sampled image (mipLevel). GlfImageSharedPtr image = GlfImage::OpenForReading(_filePath, i); @@ -162,7 +218,7 @@ GlfUVTextureData::_ReadDegradedImageInput(bool generateMipmap, // not supposed to hit this. GlfImage will return the last // down-sampled image if the subimageIndex is beyond the range. if (not image) { - return _DegradedImageInput(1.0, 1.0, fullImage); + return _GetDegradedImageInputChain(1.0, 1.0, 0, 1); } // Compute the size at the down-sampled resolution. @@ -171,20 +227,20 @@ GlfUVTextureData::_ReadDegradedImageInput(bool generateMipmap, if (size <= targetMemory) { // We found an image with small enough memory requirement, // return it. - return _DegradedImageInput( + return _GetDegradedImageInputChain( double(image->GetWidth()) / fullImage->GetWidth(), double(image->GetHeight()) / fullImage->GetHeight(), - image); + i, numMipLevels); } if (not (size < prevSize)) { // GlfImage stopped providing more further-downsampled // images, no point to continue, return image from last // iteration. - return _DegradedImageInput( + return _GetDegradedImageInputChain( double(prevImage->GetWidth()) / fullImage->GetWidth(), double(prevImage->GetHeight()) / fullImage->GetHeight(), - prevImage); + i-1, numMipLevels); } // Set values to see try to fetch the next downsampled images. @@ -193,10 +249,10 @@ GlfUVTextureData::_ReadDegradedImageInput(bool generateMipmap, } // Iteration limit reached, return image from last iteration. - return _DegradedImageInput( + return _GetDegradedImageInputChain( double(prevImage->GetWidth()) / fullImage->GetWidth(), double(prevImage->GetHeight()) / fullImage->GetHeight(), - prevImage); + numMipLevels-1, numMipLevels); } bool @@ -212,147 +268,190 @@ GlfUVTextureData::Read(int degradeLevel, bool generateMipmap) // Read the image from a file, if possible and necessary, a down-sampled // version const _DegradedImageInput degradedImage = _ReadDegradedImageInput( - generateMipmap, _params.targetMemory, degradeLevel); - - GlfImageSharedPtr image = degradedImage.image; - - if (not image) { + generateMipmap, _params.targetMemory, degradeLevel); + if (degradedImage.images.size()<1) { TF_CODING_ERROR("Unable to load Texture '%s'.", _filePath.c_str()); return false; } - int imageWidth = image->GetWidth(); - int imageHeight = image->GetHeight(); - - int cropTop = _params.cropTop; - int cropBottom = _params.cropBottom; - int cropLeft = _params.cropLeft; - int cropRight = _params.cropRight; + // Load the first mip to extract important data + GlfImageSharedPtr image = degradedImage.images[0]; + _glFormat = image->GetFormat(); + _glType = image->GetType(); + _targetMemory = _params.targetMemory; + _wrapInfo.hasWrapModeS = + image->GetSamplerMetadata(GL_TEXTURE_WRAP_S, &_wrapInfo.wrapModeS); + _wrapInfo.hasWrapModeT = + image->GetSamplerMetadata(GL_TEXTURE_WRAP_T, &_wrapInfo.wrapModeT); + _size = 0; + _nativeWidth = _resizedWidth = image->GetWidth(); + _nativeHeight = _resizedHeight = image->GetHeight(); - // Check if the format of the image is compressed bool isCompressed = GlfIsCompressedFormat(image->GetFormat()); + bool needsCropping = _params.cropTop or _params.cropBottom or + _params.cropLeft or _params.cropRight; + bool needsResizeOnLoad = false; + int cropTop = 0, cropBottom = 0, cropLeft = 0, cropRight = 0; - if (cropTop or cropBottom or cropLeft or cropRight) { - - TRACE_SCOPE("GlfUVTextureData::Read(int, bool) (cropping)"); - - if (isCompressed) { - TF_CODING_ERROR("Compressed images can not be cropped '%s'.", - _filePath.c_str()); - return false; - } - - // The cropping parameters are with respect to the original image, - // we need to scale them if we have a down-sampled image. - // Usually, we crop the slates that are black and the boundary might - // not hit a pixel boundary of the down-sampled image and thus black - // bleeds into the pixels near the border of the texture. To avoid - // this, we use ceil here to cut out the pixels with black bleeding. - cropTop = ceil(_params.cropTop * degradedImage.scaleY); - cropBottom = ceil(_params.cropBottom * degradedImage.scaleY); - cropLeft = ceil(_params.cropLeft * degradedImage.scaleX); - cropRight = ceil(_params.cropRight * degradedImage.scaleX); - - imageWidth = std::max(0, imageWidth - (cropLeft + cropRight)); - imageHeight = std::max(0, imageHeight - (cropTop + cropBottom)); - } - - _targetMemory = _params.targetMemory; - _nativeWidth = _resizedWidth = imageWidth; - _nativeHeight = _resizedHeight = imageHeight; - _glFormat = image->GetFormat(); - _glType = image->GetType(); - - // When using compressed formats the bytesPerPixel is not - // used and the glFormat matches the glInternalFormat. if (isCompressed) { + // When using compressed formats the bytesPerPixel is not + // used and the glFormat matches the glInternalFormat. _bytesPerPixel = image->GetBytesPerPixel(); _glInternalFormat = _glFormat; - } else { + } else { _bytesPerPixel = GlfGetNumElements(_glFormat) * GlfGetElementSize(_glType); _glInternalFormat = _GLInternalFormatFromImageData( _glFormat, _glType, image->IsColorSpaceSRGB()); - } - // Extract wrap modes from image metadata. - _wrapInfo.hasWrapModeS = - image->GetSamplerMetadata(GL_TEXTURE_WRAP_S, &_wrapInfo.wrapModeS); - _wrapInfo.hasWrapModeT = - image->GetSamplerMetadata(GL_TEXTURE_WRAP_T, &_wrapInfo.wrapModeT); + if (needsCropping) { + TRACE_SCOPE("GlfUVTextureData::Read(int, bool) (cropping)"); - const double scale = generateMipmap ? 4.0 / 3 : 1.0; + // The cropping parameters are with respect to the original image, + // we need to scale them if we have a down-sampled image. + // Usually, we crop the slates that are black and the boundary might + // not hit a pixel boundary of the down-sampled image and thus black + // bleeds into the pixels near the border of the texture. To avoid + // this, we use ceil here to cut out the pixels with black bleeding. + cropTop = ceil(_params.cropTop * degradedImage.scaleY); + cropBottom = ceil(_params.cropBottom * degradedImage.scaleY); + cropLeft = ceil(_params.cropLeft * degradedImage.scaleX); + cropRight = ceil(_params.cropRight * degradedImage.scaleX); - _size = _nativeWidth * _nativeHeight * _bytesPerPixel * scale; + _resizedWidth = std::max(0, _resizedWidth - (cropLeft + cropRight)); + _resizedHeight = std::max(0, _resizedHeight - (cropTop + cropBottom)); - int imageSize = 0; - if (isCompressed) { - TF_VERIFY((_nativeWidth == _resizedWidth) && - (_nativeHeight == _resizedHeight)); + needsResizeOnLoad = true; + } - int compressedSize = GlfGetCompressedTextureSize(_nativeWidth, - _nativeHeight, _glFormat, _glType); - _size = compressedSize * scale; - imageSize = compressedSize; - } else { - while (_targetMemory > 0 && (_size > _targetMemory)) { + const double scale = generateMipmap ? 4.0 / 3 : 1.0; + int sizeAprox = _resizedWidth * _resizedHeight * _bytesPerPixel * scale; + + while (_targetMemory > 0 && (sizeAprox > _targetMemory)) { _resizedWidth >>= 1; _resizedHeight >>= 1; - _size = _resizedWidth * _resizedHeight * _bytesPerPixel * scale; + sizeAprox = _resizedWidth * _resizedHeight * _bytesPerPixel * scale; + needsResizeOnLoad = true; } if (_targetMemory == 0) { for (int i = 0; i < degradeLevel; i++) { _resizedWidth >>= 1; _resizedHeight >>= 1; + needsResizeOnLoad = true; } } - imageSize = _resizedWidth * _resizedHeight * _bytesPerPixel; - } + } + + // Check if the image is providing a mip chain and check if it is valid + // Also, if the user wants cropping/resize then the mip chain + // will be discarded. + bool usePregeneratedMips = not needsResizeOnLoad and generateMipmap; + int numMipLevels = usePregeneratedMips ? degradedImage.images.size() : 1; + + // If rawbuffer has any memory let's clean it now before we load the + // new textures in memory + _rawBufferMips.clear(); + _rawBufferMips.resize(numMipLevels); + + // Read the metadata for the degraded mips in the structure that keeps + // track of all the mips + for(int i = 0 ; i < numMipLevels; i++) { + GlfImageSharedPtr image = degradedImage.images[i]; + if (not image) { + TF_RUNTIME_ERROR("Unable to load mip from Texture '%s'.", + _filePath.c_str()); + return false; + } - if (_rawBuffer) { - delete [] _rawBuffer; - _rawBuffer = NULL; - } + // Create the new mipmap + Mip & mip = _rawBufferMips[i]; + mip.width = needsResizeOnLoad ? _resizedWidth : image->GetWidth(); + mip.height = needsResizeOnLoad ? _resizedHeight : image->GetHeight(); + mip.size = isCompressed ? GlfGetCompressedTextureSize( + mip.width, mip.height, _glFormat, _glType): + mip.width * mip.height * _bytesPerPixel; + mip.offset = _size; + _size += mip.size; + } - _rawBuffer = new unsigned char[imageSize]; - if (_rawBuffer == NULL) { - TF_RUNTIME_ERROR("Unable to allocate image buffer."); + _rawBuffer.reset(new unsigned char[_size]); + if (not _rawBuffer) { + TF_RUNTIME_ERROR("Unable to allocate memory for the mip levels."); return false; } - // Retrieve raw pixels. - GlfImage::StorageSpec storage; - storage.width = _resizedWidth; - storage.height = _resizedHeight; - storage.format = _glFormat; - storage.type = _glType; - storage.data = _rawBuffer; + // Read the actual mips from each image and store them in a big buffer of + // contiguous memory. + for(int i = 0 ; i < numMipLevels; i++) { + GlfImageSharedPtr image = degradedImage.images[i]; + if (not image) { + TF_RUNTIME_ERROR("Unable to load mip from Texture '%s'.", + _filePath.c_str()); + return false; + } + + Mip & mip = _rawBufferMips[i]; + GlfImage::StorageSpec storage; + storage.width = mip.width; + storage.height = mip.height; + storage.format = _glFormat; + storage.type = _glType; + storage.data = _rawBuffer.get() + mip.offset; + + if (not image->ReadCropped(cropTop, cropBottom, cropLeft, cropRight, storage)) { + TF_CODING_ERROR("Unable to read Texture '%s'.", _filePath.c_str()); + return false; + } + } + + return true; +} - return image->ReadCropped(cropTop, cropBottom, cropLeft, cropRight, storage); +size_t +GlfUVTextureData::ComputeBytesUsedByMip(int mipLevel) const +{ + // Returns specific mip level sizes + if (mipLevel >= _rawBufferMips.size()) return 0; + return _rawBufferMips[mipLevel].size; } -int GlfUVTextureData::ComputeBytesUsed() const +size_t +GlfUVTextureData::ComputeBytesUsed() const { - if (_rawBuffer) { - if (GlfIsCompressedFormat(_glFormat)) { - return GlfGetCompressedTextureSize(_resizedWidth, _resizedHeight, - _glFormat, _glType); - } else { - return _resizedWidth * _resizedHeight * _bytesPerPixel; - } - } else { - return 0; - } + return _size; +} + +bool +GlfUVTextureData::HasRawBuffer(int mipLevel) const +{ + if (mipLevel >= _rawBufferMips.size()) return false; + return (_rawBufferMips[mipLevel].size > 0); } -bool GlfUVTextureData::HasRawBuffer() const +unsigned char * +GlfUVTextureData::GetRawBuffer(int mipLevel) const { - return (_rawBuffer != NULL); + if (mipLevel >= _rawBufferMips.size() or not _rawBuffer) return 0; + return _rawBuffer.get() + _rawBufferMips[mipLevel].offset; } -unsigned char * GlfUVTextureData::GetRawBuffer() const +int +GlfUVTextureData::ResizedWidth(int mipLevel) const { - return _rawBuffer; + if (mipLevel >= _rawBufferMips.size()) return 0; + return _rawBufferMips[mipLevel].width; } +int +GlfUVTextureData::ResizedHeight(int mipLevel) const +{ + if (mipLevel >= _rawBufferMips.size()) return 0; + return _rawBufferMips[mipLevel].height; +} + +int +GlfUVTextureData::GetNumMipLevels() const +{ + return (int)_rawBufferMips.size(); +} diff --git a/pxr/imaging/lib/glf/uvTextureData.h b/pxr/imaging/lib/glf/uvTextureData.h index f00e4e1bab..2a6c0afc9e 100644 --- a/pxr/imaging/lib/glf/uvTextureData.h +++ b/pxr/imaging/lib/glf/uvTextureData.h @@ -27,6 +27,7 @@ #include "pxr/imaging/glf/baseTextureData.h" #include +#include #include @@ -78,13 +79,9 @@ class GlfUVTextureData : public GlfBaseTextureData const Params& GetParams() const { return _params; } // GlfBaseTextureData overrides - virtual int ResizedWidth() const { - return _resizedWidth; - }; + virtual int ResizedWidth(int mipLevel = 0) const; - virtual int ResizedHeight() const { - return _resizedHeight; - }; + virtual int ResizedHeight(int mipLevel = 0) const; virtual GLenum GLInternalFormat() const { return _glInternalFormat; @@ -106,27 +103,49 @@ class GlfUVTextureData : public GlfBaseTextureData return _wrapInfo; }; - virtual int ComputeBytesUsed() const; + virtual size_t ComputeBytesUsed() const; + + virtual size_t ComputeBytesUsedByMip(int mipLevel = 0) const; - virtual bool HasRawBuffer() const; + virtual bool HasRawBuffer(int mipLevel = 0) const; - virtual unsigned char * GetRawBuffer() const; + virtual unsigned char * GetRawBuffer(int mipLevel = 0) const; virtual bool Read(int degradeLevel, bool generateMipmap); + virtual int GetNumMipLevels() const; + private: + // A structure that keeps the mips loaded from disk in the format + // that the gpu needs. + struct Mip { + Mip() + : size(0), offset(0), width(0), height(0) + { } + + size_t size; + size_t offset; + int width; + int height; + }; + // A structure keeping a down-sampled image input and floats indicating the // downsample rate (e.g., if the resolution changed from 2048x1024 to // 512x256, scaleX=0.25 and scaleY=0.25). struct _DegradedImageInput { - _DegradedImageInput(double scaleX, double scaleY, - GlfImageSharedPtr image) - : scaleX(scaleX), scaleY(scaleY), image(image) + _DegradedImageInput(double scaleX, double scaleY, + GlfImageSharedPtr image) : scaleX(scaleX), scaleY(scaleY) + { + images.push_back(image); + } + + _DegradedImageInput(double scaleX, double scaleY) + : scaleX(scaleX), scaleY(scaleY) { } double scaleX; double scaleY; - GlfImageSharedPtr image; + std::vector images; }; // Reads an image using GlfImage. If possible and requested, it will @@ -140,8 +159,19 @@ class GlfUVTextureData : public GlfBaseTextureData size_t targetMemory, size_t degradeLevel); - GlfUVTextureData(std::string const &filePath, - Params const ¶ms); + // Helper to read degraded image chains, given a starting mip and an + // ending mip it will fill the image chain. + _DegradedImageInput _GetDegradedImageInputChain(double scaleX, + double scaleY, + int startMip, + int lastMip); + + // Given a GlfImage it will return the number of mip levels that + // are actually valid to be loaded to the GPU. For instance, it will + // drop textures with non valid OpenGL pyramids. + int _GetNumMipLevelsValid(const GlfImageSharedPtr image) const; + + GlfUVTextureData(std::string const &filePath, Params const ¶ms); virtual ~GlfUVTextureData(); const std::string _filePath; @@ -159,7 +189,8 @@ class GlfUVTextureData : public GlfBaseTextureData size_t _size; - unsigned char *_rawBuffer; + boost::scoped_ptr _rawBuffer; + std::vector _rawBufferMips; }; #endif // GLF_UVTEXTURE_DATA_H diff --git a/pxr/imaging/lib/glf/uvTextureStorageData.cpp b/pxr/imaging/lib/glf/uvTextureStorageData.cpp index d459969cb2..df5d80146a 100644 --- a/pxr/imaging/lib/glf/uvTextureStorageData.cpp +++ b/pxr/imaging/lib/glf/uvTextureStorageData.cpp @@ -51,7 +51,7 @@ GlfUVTextureStorageData::~GlfUVTextureStorageData() } } -int GlfUVTextureStorageData::ComputeBytesUsed() const +size_t GlfUVTextureStorageData::ComputeBytesUsed() const { if (_rawBuffer) { return _resizedWidth * _resizedHeight * _bytesPerPixel; @@ -60,12 +60,12 @@ int GlfUVTextureStorageData::ComputeBytesUsed() const } } -bool GlfUVTextureStorageData::HasRawBuffer() const +bool GlfUVTextureStorageData::HasRawBuffer(int mipLevel) const { return (_rawBuffer != nullptr); } -unsigned char * GlfUVTextureStorageData::GetRawBuffer() const +unsigned char * GlfUVTextureStorageData::GetRawBuffer(int mipLevel) const { return _rawBuffer; } @@ -131,6 +131,12 @@ bool GlfUVTextureStorageData::Read(int degradeLevel, bool generateMipmap) { return true; } +int GlfUVTextureStorageData::GetNumMipLevels() const +{ + if (_rawBuffer) return 1; + return 0; +} + bool GlfUVTextureStorageData::IsCompressed() const { return false; } diff --git a/pxr/imaging/lib/glf/uvTextureStorageData.h b/pxr/imaging/lib/glf/uvTextureStorageData.h index 3e9f940f3a..bb475d0dbc 100644 --- a/pxr/imaging/lib/glf/uvTextureStorageData.h +++ b/pxr/imaging/lib/glf/uvTextureStorageData.h @@ -43,11 +43,11 @@ class GlfUVTextureStorageData : public GlfBaseTextureData virtual ~GlfUVTextureStorageData(); // GlfBaseTextureData overrides - virtual int ResizedWidth() const { + virtual int ResizedWidth(int mipLevel = 0) const { return _resizedWidth; }; - virtual int ResizedHeight() const { + virtual int ResizedHeight(int mipLevel = 0) const { return _resizedHeight; }; @@ -71,16 +71,22 @@ class GlfUVTextureStorageData : public GlfBaseTextureData return _wrapInfo; }; - virtual int ComputeBytesUsed() const; + virtual size_t ComputeBytesUsed() const; - virtual bool HasRawBuffer() const; + virtual size_t ComputeBytesUsedByMip(int mipLevel = 0) const { + return ComputeBytesUsed(); + } - virtual unsigned char * GetRawBuffer() const; + virtual bool HasRawBuffer(int mipLevel = 0) const; + + virtual unsigned char * GetRawBuffer(int mipLevel = 0) const; virtual bool Read(int degradeLevel, bool generateMipmap); virtual bool IsCompressed() const; + virtual int GetNumMipLevels() const; + private: GlfUVTextureStorageData( @@ -104,6 +110,5 @@ class GlfUVTextureStorageData : public GlfBaseTextureData int _size; unsigned char *_rawBuffer; - }; -#endif // GLF_UVTEXTURESTORAGE_DATA_H \ No newline at end of file +#endif // GLF_UVTEXTURESTORAGE_DATA_H From 6a6eafc866f9aaed679f5187f52cf12204211f03 Mon Sep 17 00:00:00 2001 From: takahito-tejima Date: Tue, 6 Sep 2016 14:02:05 -0700 Subject: [PATCH 091/380] [Hd, Hdx] move simpleLightingShader from Hd to Hdx - refactor Hd to not depend on GlfSimpleLightingContext. - rename hd's fallback lighting shader (N.L) from simpleLighting to fallbackLighting, to reduce some confusion. All relevant classes and files have been renamed. - to keep unit tests compatible, add Hd_TestLightingShader in unitTestHelper. this mimics simpleLightingShader in a minimal way - still two baseline images need to be updated for subtle pixel differences due to floating point operation reordering. - add and use API guard HD_API > 24 and HDX_API > 2 (used in katana plugin) - HD_SHADER_API to 2 (SimpleLighting -> FallbackLighting) (Internal change: 1651855) (Internal change: 1651885) --- pxr/imaging/lib/hd/CMakeLists.txt | 8 +- pxr/imaging/lib/hd/codeGen.cpp | 2 +- ...gShader.cpp => fallbackLightingShader.cpp} | 24 ++-- ...htingShader.h => fallbackLightingShader.h} | 14 +- pxr/imaging/lib/hd/package.cpp | 16 +-- pxr/imaging/lib/hd/package.h | 3 +- pxr/imaging/lib/hd/renderPass.cpp | 1 - pxr/imaging/lib/hd/renderPassState.cpp | 12 +- pxr/imaging/lib/hd/renderPassState.h | 6 +- pxr/imaging/lib/hd/shaders/basisCurves.glslfx | 3 - ...ighting.glslfx => fallbackLighting.glslfx} | 6 +- ...r.glslfx => fallbackLightingShader.glslfx} | 6 +- .../lib/hd/shaders/fallbackSurface.glslfx | 2 +- pxr/imaging/lib/hd/shaders/mesh.glslfx | 2 - pxr/imaging/lib/hd/shaders/points.glslfx | 1 - .../lib/hd/testenv/testHdBasicDrawing.cpp | 10 +- pxr/imaging/lib/hd/unitTestHelper.cpp | 131 ++++++++++++++++++ pxr/imaging/lib/hd/unitTestHelper.h | 39 ++++++ pxr/imaging/lib/hd/version.h | 6 +- pxr/imaging/lib/hdx/CMakeLists.txt | 2 + pxr/imaging/lib/hdx/drawTargetTask.cpp | 10 +- pxr/imaging/lib/hdx/drawTargetTask.h | 13 +- pxr/imaging/lib/hdx/package.cpp | 7 + pxr/imaging/lib/hdx/package.h | 1 + pxr/imaging/lib/hdx/selectionTask.cpp | 1 - .../shaders/simpleLightingShader.glslfx | 9 +- pxr/imaging/lib/hdx/shadowTask.cpp | 3 +- pxr/imaging/lib/hdx/shadowTask.h | 1 - pxr/imaging/lib/hdx/simpleLightBypassTask.cpp | 4 +- pxr/imaging/lib/hdx/simpleLightBypassTask.h | 4 +- pxr/imaging/lib/hdx/simpleLightTask.cpp | 4 +- pxr/imaging/lib/hdx/simpleLightTask.h | 4 +- .../lib/{hd => hdx}/simpleLightingShader.cpp | 30 ++-- .../lib/{hd => hdx}/simpleLightingShader.h | 16 +-- pxr/imaging/lib/hdx/version.h | 3 +- 35 files changed, 286 insertions(+), 118 deletions(-) rename pxr/imaging/lib/hd/{defaultLightingShader.cpp => fallbackLightingShader.cpp} (71%) rename pxr/imaging/lib/hd/{defaultLightingShader.h => fallbackLightingShader.h} (87%) rename pxr/imaging/lib/hd/shaders/{simpleLighting.glslfx => fallbackLighting.glslfx} (89%) rename pxr/imaging/lib/hd/shaders/{defaultLightingShader.glslfx => fallbackLightingShader.glslfx} (88%) rename pxr/imaging/lib/{hd => hdx}/shaders/simpleLightingShader.glslfx (89%) rename pxr/imaging/lib/{hd => hdx}/simpleLightingShader.cpp (83%) rename pxr/imaging/lib/{hd => hdx}/simpleLightingShader.h (87%) diff --git a/pxr/imaging/lib/hd/CMakeLists.txt b/pxr/imaging/lib/hd/CMakeLists.txt index 6defd6ebb1..abe4e3cb7c 100644 --- a/pxr/imaging/lib/hd/CMakeLists.txt +++ b/pxr/imaging/lib/hd/CMakeLists.txt @@ -99,7 +99,6 @@ pxr_shared_library(hd shader shaderKey shaderParam - simpleLightingShader surfaceShader strategyBase task @@ -120,7 +119,7 @@ pxr_shared_library(hd basisCurvesComputations basisCurvesShaderKey cullingShaderKey - defaultLightingShader + fallbackLightingShader geometricShader meshShaderKey pointsShaderKey @@ -139,7 +138,8 @@ pxr_shared_library(hd plugInfo.json shaders/basisCurves.glslfx shaders/compute.glslfx - shaders/defaultLightingShader.glslfx + shaders/fallbackLighting.glslfx + shaders/fallbackLightingShader.glslfx shaders/fallbackSurface.glslfx shaders/frustumCull.glslfx shaders/instancing.glslfx @@ -150,8 +150,6 @@ pxr_shared_library(hd shaders/ptexTexture.glslfx shaders/renderPass.glslfx shaders/renderPassShader.glslfx - shaders/simpleLighting.glslfx - shaders/simpleLightingShader.glslfx ) if (QT4_FOUND) diff --git a/pxr/imaging/lib/hd/codeGen.cpp b/pxr/imaging/lib/hd/codeGen.cpp index 100a5e240f..6fab3ebf98 100644 --- a/pxr/imaging/lib/hd/codeGen.cpp +++ b/pxr/imaging/lib/hd/codeGen.cpp @@ -311,7 +311,7 @@ Hd_CodeGen::Compile() // Used in glslfx files to determine if it is using new/old // imaging system. It can also be used as API guards when // we need new versions of Hydra shading. - _genCommon << "#define HD_SHADER_API 1\n"; + _genCommon << "#define HD_SHADER_API " << HD_SHADER_API << "\n"; // XXX: this is a hacky workaround for experimental support of GL 3.3 // the double is used in hd_dvec3 akin, so we are likely able to diff --git a/pxr/imaging/lib/hd/defaultLightingShader.cpp b/pxr/imaging/lib/hd/fallbackLightingShader.cpp similarity index 71% rename from pxr/imaging/lib/hd/defaultLightingShader.cpp rename to pxr/imaging/lib/hd/fallbackLightingShader.cpp index 997b63852e..73f4eb8363 100644 --- a/pxr/imaging/lib/hd/defaultLightingShader.cpp +++ b/pxr/imaging/lib/hd/fallbackLightingShader.cpp @@ -21,7 +21,7 @@ // KIND, either express or implied. See the Apache License for the specific // language governing permissions and limitations under the Apache License. // -#include "pxr/imaging/hd/defaultLightingShader.h" +#include "pxr/imaging/hd/fallbackLightingShader.h" #include "pxr/imaging/hd/binding.h" #include "pxr/imaging/hd/package.h" @@ -34,21 +34,21 @@ #include -Hd_DefaultLightingShader::Hd_DefaultLightingShader() +Hd_FallbackLightingShader::Hd_FallbackLightingShader() { - _glslfx.reset(new GlfGLSLFX(HdPackageDefaultLightingShader())); + _glslfx.reset(new GlfGLSLFX(HdPackageFallbackLightingShader())); } -Hd_DefaultLightingShader::~Hd_DefaultLightingShader() +Hd_FallbackLightingShader::~Hd_FallbackLightingShader() { // nothing } /* virtual */ -Hd_DefaultLightingShader::ID -Hd_DefaultLightingShader::ComputeHash() const +Hd_FallbackLightingShader::ID +Hd_FallbackLightingShader::ComputeHash() const { - TfToken glslfxFile = HdPackageDefaultLightingShader(); + TfToken glslfxFile = HdPackageFallbackLightingShader(); size_t hash = glslfxFile.Hash(); @@ -57,7 +57,7 @@ Hd_DefaultLightingShader::ComputeHash() const /* virtual */ std::string -Hd_DefaultLightingShader::GetSource(TfToken const &shaderStageKey) const +Hd_FallbackLightingShader::GetSource(TfToken const &shaderStageKey) const { HD_TRACE_FUNCTION(); HD_MALLOC_TAG_FUNCTION(); @@ -67,21 +67,21 @@ Hd_DefaultLightingShader::GetSource(TfToken const &shaderStageKey) const /* virtual */ void -Hd_DefaultLightingShader::SetCamera(GfMatrix4d const &worldToViewMatrix, +Hd_FallbackLightingShader::SetCamera(GfMatrix4d const &worldToViewMatrix, GfMatrix4d const &projectionMatrix) { // nothing } void -Hd_DefaultLightingShader::BindResources(Hd_ResourceBinder const &binder, +Hd_FallbackLightingShader::BindResources(Hd_ResourceBinder const &binder, int program) { // nothing } void -Hd_DefaultLightingShader::UnbindResources(Hd_ResourceBinder const &binder, +Hd_FallbackLightingShader::UnbindResources(Hd_ResourceBinder const &binder, int program) { // nothing @@ -89,7 +89,7 @@ Hd_DefaultLightingShader::UnbindResources(Hd_ResourceBinder const &binder, /*virtual*/ void -Hd_DefaultLightingShader::AddBindings(HdBindingRequestVector *customBindings) +Hd_FallbackLightingShader::AddBindings(HdBindingRequestVector *customBindings) { // no-op } diff --git a/pxr/imaging/lib/hd/defaultLightingShader.h b/pxr/imaging/lib/hd/fallbackLightingShader.h similarity index 87% rename from pxr/imaging/lib/hd/defaultLightingShader.h rename to pxr/imaging/lib/hd/fallbackLightingShader.h index faeaa2ef4e..dd97e082c0 100644 --- a/pxr/imaging/lib/hd/defaultLightingShader.h +++ b/pxr/imaging/lib/hd/fallbackLightingShader.h @@ -21,8 +21,8 @@ // KIND, either express or implied. See the Apache License for the specific // language governing permissions and limitations under the Apache License. // -#ifndef HD_DEFAULT_LIGHTING_SHADER_H -#define HD_DEFAULT_LIGHTING_SHADER_H +#ifndef HD_FALLBACK_LIGHTING_SHADER_H +#define HD_FALLBACK_LIGHTING_SHADER_H #include "pxr/imaging/hd/version.h" #include "pxr/imaging/hd/lightingShader.h" @@ -38,14 +38,14 @@ #include -/// \class Hd_DefaultLightingShader +/// \class Hd_FallbackLightingShader /// /// A shader that provides fallback lighting behavior. /// -class Hd_DefaultLightingShader : public HdLightingShader { +class Hd_FallbackLightingShader : public HdLightingShader { public: - Hd_DefaultLightingShader(); - virtual ~Hd_DefaultLightingShader(); + Hd_FallbackLightingShader(); + virtual ~Hd_FallbackLightingShader(); // HdShader overrides virtual ID ComputeHash() const; @@ -62,4 +62,4 @@ class Hd_DefaultLightingShader : public HdLightingShader { boost::scoped_ptr _glslfx; }; -#endif // HD_DEFAULT_LIGHTING_SHADER_H +#endif // HD_FALLBACK_LIGHTING_SHADER_H diff --git a/pxr/imaging/lib/hd/package.cpp b/pxr/imaging/lib/hd/package.cpp index a6834ddf58..b890cba003 100644 --- a/pxr/imaging/lib/hd/package.cpp +++ b/pxr/imaging/lib/hd/package.cpp @@ -55,19 +55,11 @@ HdPackageRenderPassShader() } TfToken -HdPackageDefaultLightingShader() +HdPackageFallbackLightingShader() { - static TfToken defaultLightingShader = - _GetShaderPath("defaultLightingShader.glslfx"); - return defaultLightingShader; -} - -TfToken -HdPackageSimpleLightingShader() -{ - static TfToken simpleLightingShader = - _GetShaderPath("simpleLightingShader.glslfx"); - return simpleLightingShader; + static TfToken fallbackLightingShader = + _GetShaderPath("fallbackLightingShader.glslfx"); + return fallbackLightingShader; } TfToken diff --git a/pxr/imaging/lib/hd/package.h b/pxr/imaging/lib/hd/package.h index b7694641a5..2e2594f97a 100644 --- a/pxr/imaging/lib/hd/package.h +++ b/pxr/imaging/lib/hd/package.h @@ -31,8 +31,7 @@ TfToken HdPackageComputeShader(); TfToken HdPackageRenderPassShader(); -TfToken HdPackageDefaultLightingShader(); -TfToken HdPackageSimpleLightingShader(); +TfToken HdPackageFallbackLightingShader(); TfToken HdPackageFallbackSurfaceShader(); diff --git a/pxr/imaging/lib/hd/renderPass.cpp b/pxr/imaging/lib/hd/renderPass.cpp index 67111d120d..bd6b28b0b1 100644 --- a/pxr/imaging/lib/hd/renderPass.cpp +++ b/pxr/imaging/lib/hd/renderPass.cpp @@ -26,7 +26,6 @@ #include "pxr/imaging/hd/renderPass.h" #include "pxr/imaging/hd/changeTracker.h" -#include "pxr/imaging/hd/defaultLightingShader.h" #include "pxr/imaging/hd/dirtyList.h" #include "pxr/imaging/hd/drawItem.h" #include "pxr/imaging/hd/glslProgram.h" diff --git a/pxr/imaging/lib/hd/renderPassState.cpp b/pxr/imaging/lib/hd/renderPassState.cpp index 2c99dfb2ed..80e2111c5f 100644 --- a/pxr/imaging/lib/hd/renderPassState.cpp +++ b/pxr/imaging/lib/hd/renderPassState.cpp @@ -26,7 +26,7 @@ #include "pxr/imaging/hd/renderPassState.h" #include "pxr/imaging/hd/changeTracker.h" -#include "pxr/imaging/hd/defaultLightingShader.h" +#include "pxr/imaging/hd/fallbackLightingShader.h" #include "pxr/imaging/hd/drawItem.h" #include "pxr/imaging/hd/glslProgram.h" #include "pxr/imaging/hd/renderPassShader.h" @@ -49,7 +49,7 @@ TF_DEFINE_PRIVATE_TOKENS( HdRenderPassState::HdRenderPassState() : _renderPassShader(new HdRenderPassShader()) - , _defaultLightingShader(new Hd_DefaultLightingShader()) + , _fallbackLightingShader(new Hd_FallbackLightingShader()) , _worldToViewMatrix(1) , _projectionMatrix(1) , _viewport(0, 0, 1, 1) @@ -68,13 +68,13 @@ HdRenderPassState::HdRenderPassState() , _alphaToCoverageUseDefault(true) , _alphaToCoverageEnabled(true) { - _lightingShader = _defaultLightingShader; + _lightingShader = _fallbackLightingShader; } HdRenderPassState::HdRenderPassState( HdRenderPassShaderSharedPtr const &renderPassShader) : _renderPassShader(renderPassShader) - , _defaultLightingShader(new Hd_DefaultLightingShader()) + , _fallbackLightingShader(new Hd_FallbackLightingShader()) , _worldToViewMatrix(1) , _projectionMatrix(1) , _viewport(0, 0, 1, 1) @@ -93,7 +93,7 @@ HdRenderPassState::HdRenderPassState( , _alphaToCoverageUseDefault(true) , _alphaToCoverageEnabled(true) { - _lightingShader = _defaultLightingShader; + _lightingShader = _fallbackLightingShader; } HdRenderPassState::~HdRenderPassState() @@ -280,7 +280,7 @@ HdRenderPassState::SetLightingShader(HdLightingShaderSharedPtr const &lightingSh if (lightingShader) { _lightingShader = lightingShader; } else { - _lightingShader = _defaultLightingShader; + _lightingShader = _fallbackLightingShader; } } diff --git a/pxr/imaging/lib/hd/renderPassState.h b/pxr/imaging/lib/hd/renderPassState.h index 8afea87ac6..307fd6cd5b 100644 --- a/pxr/imaging/lib/hd/renderPassState.h +++ b/pxr/imaging/lib/hd/renderPassState.h @@ -40,8 +40,8 @@ typedef boost::shared_ptr HdShaderSharedPtr; typedef boost::shared_ptr HdLightingShaderSharedPtr; typedef boost::shared_ptr HdRenderPassShaderSharedPtr; -typedef boost::shared_ptr - Hd_DefaultLightingShaderSharedPtr; +typedef boost::shared_ptr + Hd_FallbackLightingShaderSharedPtr; typedef std::vector HdShaderSharedPtrVector; /// \class HdRenderPassState @@ -154,7 +154,7 @@ class HdRenderPassState { // Shader Objects // ---------------------------------------------------------------------- // HdRenderPassShaderSharedPtr _renderPassShader; - Hd_DefaultLightingShaderSharedPtr _defaultLightingShader; + Hd_FallbackLightingShaderSharedPtr _fallbackLightingShader; HdLightingShaderSharedPtr _lightingShader; HdShaderSharedPtr _overrideShader; diff --git a/pxr/imaging/lib/hd/shaders/basisCurves.glslfx b/pxr/imaging/lib/hd/shaders/basisCurves.glslfx index c4c72000dc..288137deeb 100644 --- a/pxr/imaging/lib/hd/shaders/basisCurves.glslfx +++ b/pxr/imaging/lib/hd/shaders/basisCurves.glslfx @@ -380,8 +380,6 @@ in VertexData vec3 Neye; } inData; -vec3 SimpleLighting(in vec3 Peye, in vec3 Neye, in vec3 color); -vec3 getNormal(vec3 Peye, vec3 Neye); vec4 surfaceShader(vec4 Peye, vec3 Neye, vec4 color, vec4 patchCoord); void main(void) @@ -439,7 +437,6 @@ in VertexData vec4 Peye; } inData; -vec3 SimpleLighting(in vec3 Peye, in vec3 Neye, in vec3 color); vec4 surfaceShader(vec4 Peye, vec3 Neye, vec4 color, vec4 patchCoord); void main(void) diff --git a/pxr/imaging/lib/hd/shaders/simpleLighting.glslfx b/pxr/imaging/lib/hd/shaders/fallbackLighting.glslfx similarity index 89% rename from pxr/imaging/lib/hd/shaders/simpleLighting.glslfx rename to pxr/imaging/lib/hd/shaders/fallbackLighting.glslfx index 1abc9396b7..8babcfcf80 100644 --- a/pxr/imaging/lib/hd/shaders/simpleLighting.glslfx +++ b/pxr/imaging/lib/hd/shaders/fallbackLighting.glslfx @@ -25,12 +25,12 @@ // --- This is what an import might look like. ---- #import $TOOLS/hd/shaders/simpleLighting.glslfx +--- #import $TOOLS/hd/shaders/fallbackLighting.glslfx --- -------------------------------------------------------------------------- --- glsl SimpleLighting.DefaultLighting +-- glsl Fallback.Lighting -vec3 SimpleLighting(in vec3 Peye, in vec3 Neye, in vec3 color) +vec3 FallbackLighting(in vec3 Peye, in vec3 Neye, in vec3 color) { return (color * dot(normalize(Neye), vec3(0,0,1))); } diff --git a/pxr/imaging/lib/hd/shaders/defaultLightingShader.glslfx b/pxr/imaging/lib/hd/shaders/fallbackLightingShader.glslfx similarity index 88% rename from pxr/imaging/lib/hd/shaders/defaultLightingShader.glslfx rename to pxr/imaging/lib/hd/shaders/fallbackLightingShader.glslfx index 284c5010e7..0d3ed2a161 100644 --- a/pxr/imaging/lib/hd/shaders/defaultLightingShader.glslfx +++ b/pxr/imaging/lib/hd/shaders/fallbackLightingShader.glslfx @@ -25,16 +25,16 @@ // --- This is what an import might look like. ---- #import $TOOLS/hd/shaders/defaultLightingShader.glslfx +--- #import $TOOLS/hd/shaders/fallbackLightingShader.glslfx -#import $TOOLS/hd/shaders/simpleLighting.glslfx +#import $TOOLS/hd/shaders/fallbackLighting.glslfx -- configuration { "techniques": { "default": { "fragmentShader" : { - "source": [ "SimpleLighting.DefaultLighting" ] + "source": [ "Fallback.Lighting" ] } } } diff --git a/pxr/imaging/lib/hd/shaders/fallbackSurface.glslfx b/pxr/imaging/lib/hd/shaders/fallbackSurface.glslfx index 205458b946..e930087627 100644 --- a/pxr/imaging/lib/hd/shaders/fallbackSurface.glslfx +++ b/pxr/imaging/lib/hd/shaders/fallbackSurface.glslfx @@ -55,6 +55,6 @@ vec4 displacementShader(int index, vec4 Peye, vec3 Neye, vec4 patchCoord) vec4 surfaceShader(vec4 Peye, vec3 Neye, vec4 color, vec4 patchCoord) { // lighting - color.rgb = SimpleLighting(Peye.xyz, Neye, color.rgb); + color.rgb = FallbackLighting(Peye.xyz, Neye, color.rgb); return color; } diff --git a/pxr/imaging/lib/hd/shaders/mesh.glslfx b/pxr/imaging/lib/hd/shaders/mesh.glslfx index 49c653d02f..e718fdf8b6 100644 --- a/pxr/imaging/lib/hd/shaders/mesh.glslfx +++ b/pxr/imaging/lib/hd/shaders/mesh.glslfx @@ -387,8 +387,6 @@ in VertexData in vec4 gsPatchCoord; in vec2 gsTessCoord; -vec3 SimpleLighting(in vec3 Peye, in vec3 Neye, in vec3 color); - #ifndef HD_HAS_ptexFaceOffset #define HD_HAS_ptexFaceOffset int HdGet_ptexFaceOffset() diff --git a/pxr/imaging/lib/hd/shaders/points.glslfx b/pxr/imaging/lib/hd/shaders/points.glslfx index bf92a7635e..1a15bf623e 100644 --- a/pxr/imaging/lib/hd/shaders/points.glslfx +++ b/pxr/imaging/lib/hd/shaders/points.glslfx @@ -69,7 +69,6 @@ in VertexData vec4 Peye; } inData; -vec3 SimpleLighting(in vec3 Peye, in vec3 Neye, in vec3 color); vec4 surfaceShader(vec4 Peye, vec3 Neye, vec4 color, vec4 patchCoord); void main(void) diff --git a/pxr/imaging/lib/hd/testenv/testHdBasicDrawing.cpp b/pxr/imaging/lib/hd/testenv/testHdBasicDrawing.cpp index 515864a99a..f606ad7d42 100644 --- a/pxr/imaging/lib/hd/testenv/testHdBasicDrawing.cpp +++ b/pxr/imaging/lib/hd/testenv/testHdBasicDrawing.cpp @@ -24,7 +24,6 @@ #include "pxr/imaging/glf/glew.h" #include "pxr/imaging/hd/renderPassState.h" -#include "pxr/imaging/hd/simpleLightingShader.h" #include "pxr/imaging/hd/tokens.h" #include "pxr/imaging/hd/unitTestGLDrawing.h" #include "pxr/imaging/hd/unitTestHelper.h" @@ -58,7 +57,7 @@ class My_TestGLDrawing : public Hd_UnitTestGLDrawing { private: Hd_TestDriver* _driver; - HdSimpleLightingShaderSharedPtr _lightingShader; + Hd_TestLightingShaderSharedPtr _lightingShader; std::vector _clipPlanes; TfToken _reprName; @@ -95,14 +94,9 @@ My_TestGLDrawing::InitTest() glBindVertexArray(0); if (_testLighting) { - _lightingShader.reset(new HdSimpleLightingShader()); + _lightingShader.reset(new Hd_TestLightingShader()); _driver->GetRenderPassState()->SetLightingShader( _lightingShader); - - glEnable(GL_LIGHTING); - glEnable(GL_LIGHT0); - - _lightingShader->SetLightingStateFromOpenGL(); } _driver->GetRenderPassState()->SetClipPlanes(_clipPlanes); diff --git a/pxr/imaging/lib/hd/unitTestHelper.cpp b/pxr/imaging/lib/hd/unitTestHelper.cpp index da6fdca47d..a0a87332f4 100644 --- a/pxr/imaging/lib/hd/unitTestHelper.cpp +++ b/pxr/imaging/lib/hd/unitTestHelper.cpp @@ -30,8 +30,22 @@ #include "pxr/base/gf/matrix4d.h" #include "pxr/base/gf/frustum.h" #include "pxr/base/tf/getenv.h" +#include "pxr/base/tf/staticTokens.h" + +#include #include +#include + +TF_DEFINE_PRIVATE_TOKENS( + _tokens, + (l0dir) + (l0color) + (l1dir) + (l1color) + (sceneAmbient) + (vec3) +); template static VtArray @@ -144,3 +158,120 @@ Hd_TestDriver::SetRepr(TfToken const &reprName) HdRprimCollection(HdTokens->geometry, _reprName)); } } + +// -------------------------------------------------------------------------- + +Hd_TestLightingShader::Hd_TestLightingShader() +{ + const char *lightingShader = + "-- glslfx version 0.1 \n" + "-- configuration \n" + "{\"techniques\": {\"default\": {\"fragmentShader\" : { \n" + " \"source\": [\"TestLighting.Lighting\"] \n" + "}}}} \n" + "-- glsl TestLighting.Lighting \n" + "vec3 FallbackLighting(vec3 Peye, vec3 Neye, vec3 color) { \n" + " vec3 n = normalize(Neye); \n" + " return HdGet_sceneAmbient() \n" + " + color * HdGet_l0color() * max(0.0, dot(n, HdGet_l0dir())) \n" + " + color * HdGet_l1color() * max(0.0, dot(n, HdGet_l1dir())); \n" + "} \n"; + + _lights[0].dir = GfVec3f(0, 0, 1); + _lights[0].color = GfVec3f(1, 1, 1); + _lights[1].dir = GfVec3f(0, 0, 1); + _lights[1].color = GfVec3f(0, 0, 0); + _sceneAmbient = GfVec3f(0.04, 0.04, 0.04); + + std::stringstream ss(lightingShader); + _glslfx.reset(new GlfGLSLFX(ss)); +} + +Hd_TestLightingShader::~Hd_TestLightingShader() +{ +} + +/* virtual */ +Hd_TestLightingShader::ID +Hd_TestLightingShader::ComputeHash() const +{ + HD_TRACE_FUNCTION(); + + size_t hash = _glslfx->GetHash(); + return (ID)hash; +} + +/* virtual */ +std::string +Hd_TestLightingShader::GetSource(TfToken const &shaderStageKey) const +{ + HD_TRACE_FUNCTION(); + HD_MALLOC_TAG_FUNCTION(); + + std::string source = _glslfx->GetSource(shaderStageKey); + return source; +} + +/* virtual */ +void +Hd_TestLightingShader::SetCamera(GfMatrix4d const &worldToViewMatrix, + GfMatrix4d const &projectionMatrix) +{ + for (int i = 0; i < 2; ++i) { + _lights[i].eyeDir + = worldToViewMatrix.TransformDir(_lights[i].dir).GetNormalized(); + } +} + +/* virtual */ +void +Hd_TestLightingShader::BindResources(Hd_ResourceBinder const &binder, + int program) +{ + binder.BindUniformf(_tokens->l0dir, 3, _lights[0].eyeDir.GetArray()); + binder.BindUniformf(_tokens->l0color, 3, _lights[0].color.GetArray()); + binder.BindUniformf(_tokens->l1dir, 3, _lights[1].eyeDir.GetArray()); + binder.BindUniformf(_tokens->l1color, 3, _lights[1].color.GetArray()); + binder.BindUniformf(_tokens->sceneAmbient, 3, _sceneAmbient.GetArray()); +} + +/* virtual */ +void +Hd_TestLightingShader::UnbindResources(Hd_ResourceBinder const &binder, + int program) +{ +} + +/*virtual*/ +void +Hd_TestLightingShader::AddBindings(HdBindingRequestVector *customBindings) +{ + customBindings->push_back( + HdBindingRequest(HdBinding::UNIFORM, _tokens->l0dir, _tokens->vec3)); + customBindings->push_back( + HdBindingRequest(HdBinding::UNIFORM, _tokens->l0color, _tokens->vec3)); + customBindings->push_back( + HdBindingRequest(HdBinding::UNIFORM, _tokens->l1dir, _tokens->vec3)); + customBindings->push_back( + HdBindingRequest(HdBinding::UNIFORM, _tokens->l1color, _tokens->vec3)); + customBindings->push_back( + HdBindingRequest(HdBinding::UNIFORM, _tokens->sceneAmbient, _tokens->vec3)); +} + +void +Hd_TestLightingShader::SetSceneAmbient(GfVec3f const &color) +{ + _sceneAmbient = color; +} + +void +Hd_TestLightingShader::SetLight(int light, + GfVec3f const &dir, GfVec3f const &color) +{ + if (light < 2) { + _lights[light].dir = dir; + _lights[light].eyeDir = dir; + _lights[light].color = color; + } +} + diff --git a/pxr/imaging/lib/hd/unitTestHelper.h b/pxr/imaging/lib/hd/unitTestHelper.h index f330bf7237..689dca6283 100644 --- a/pxr/imaging/lib/hd/unitTestHelper.h +++ b/pxr/imaging/lib/hd/unitTestHelper.h @@ -25,14 +25,17 @@ #define HD_UNIT_TEST_HELPER #include "pxr/imaging/hd/engine.h" +#include "pxr/imaging/hd/lightingShader.h" #include "pxr/imaging/hd/renderPass.h" #include "pxr/imaging/hd/renderPassState.h" #include "pxr/imaging/hd/unitTestDelegate.h" +#include "pxr/imaging/glf/glslfx.h" #include "pxr/base/gf/vec4d.h" #include "pxr/base/gf/matrix4d.h" #include +#include /// \class Hd_TestDriver /// @@ -87,4 +90,40 @@ class Hd_TestDriver { HdRenderPassStateSharedPtr _renderPassState; }; +/// \class Hd_TestLightingShader +/// +/// A custom lighting shader for unit tests. +/// +typedef boost::shared_ptr Hd_TestLightingShaderSharedPtr; + +class Hd_TestLightingShader : public HdLightingShader { +public: + Hd_TestLightingShader(); + virtual ~Hd_TestLightingShader(); + + /// HdShader overrides + virtual ID ComputeHash() const; + virtual std::string GetSource(TfToken const &shaderStageKey) const; + virtual void BindResources(Hd_ResourceBinder const &binder, int program); + virtual void UnbindResources(Hd_ResourceBinder const &binder, int program); + virtual void AddBindings(HdBindingRequestVector *customBindings); + + /// HdLightingShader overrides + virtual void SetCamera(GfMatrix4d const &worldToViewMatrix, + GfMatrix4d const &projectionMatrix); + + void SetSceneAmbient(GfVec3f const &color); + void SetLight(int light, GfVec3f const &dir, GfVec3f const &color); + +private: + struct Light { + GfVec3f dir; + GfVec3f eyeDir; + GfVec3f color; + }; + Light _lights[2]; + GfVec3f _sceneAmbient; + boost::scoped_ptr _glslfx; +}; + #endif // HD_UNIT_TEST_HELPER diff --git a/pxr/imaging/lib/hd/version.h b/pxr/imaging/lib/hd/version.h index 5c44bac33b..88acc226ea 100644 --- a/pxr/imaging/lib/hd/version.h +++ b/pxr/imaging/lib/hd/version.h @@ -31,7 +31,11 @@ // HdEngine::Draw API change. // 22 -> 23: remove ID render API // 23 -> 24: GetPathForInstanceIndex returns absolute instance index. -#define HD_API 24 +// 24 -> 25: move simpleLightingShader to Hdx. +#define HD_API 25 + +// 1 -> 2: SimpleLighting -> FallbackLighting +#define HD_SHADER_API 2 // 1 -> 2: Changes "doubleShaded" API to "doubleSided". #define HD_CHANGETRACKER_API 2 diff --git a/pxr/imaging/lib/hdx/CMakeLists.txt b/pxr/imaging/lib/hdx/CMakeLists.txt index 62acaebe44..ac6e6f24f5 100644 --- a/pxr/imaging/lib/hdx/CMakeLists.txt +++ b/pxr/imaging/lib/hdx/CMakeLists.txt @@ -28,6 +28,7 @@ pxr_shared_library(hdx selectionTask selectionTracker shadowTask + simpleLightingShader simpleLightTask simpleLightBypassTask tokens @@ -42,6 +43,7 @@ pxr_shared_library(hdx RESOURCE_FILES plugInfo.json + shaders/simpleLightingShader.glslfx shaders/renderPass.glslfx shaders/renderPassShader.glslfx shaders/renderPassIdShader.glslfx diff --git a/pxr/imaging/lib/hdx/drawTargetTask.cpp b/pxr/imaging/lib/hdx/drawTargetTask.cpp index f1d6220466..b6633f37ce 100644 --- a/pxr/imaging/lib/hdx/drawTargetTask.cpp +++ b/pxr/imaging/lib/hdx/drawTargetTask.cpp @@ -24,6 +24,7 @@ #include "pxr/imaging/glf/glew.h" #include "pxr/imaging/hdx/drawTargetTask.h" +#include "pxr/imaging/hdx/simpleLightingShader.h" #include "pxr/imaging/hdx/tokens.h" #include "pxr/imaging/hdx/debugCodes.h" @@ -31,7 +32,6 @@ #include "pxr/imaging/hd/drawTarget.h" #include "pxr/imaging/hd/drawTargetRenderPass.h" #include "pxr/imaging/hd/renderPassState.h" -#include "pxr/imaging/hd/simpleLightingShader.h" #include "pxr/imaging/glf/drawTarget.h" @@ -126,8 +126,10 @@ HdxDrawTargetTask::_Sync(HdTaskContext* ctx) pass->SetDrawTarget(drawTarget->GetGlfDrawTarget()); pass->SetRenderPassState(drawTarget->GetRenderPassState()); - HdRenderPassStateSharedPtr renderPassState(new HdRenderPassState()); - HdSimpleLightingShaderSharedPtr simpleLightingShader(new HdSimpleLightingShader()); + HdRenderPassStateSharedPtr renderPassState( + new HdRenderPassState()); + HdxSimpleLightingShaderSharedPtr simpleLightingShader( + new HdxSimpleLightingShader()); _renderPasses.emplace_back( RenderPassInfo { @@ -215,7 +217,7 @@ HdxDrawTargetTask::_Sync(HdTaskContext* ctx) renderPassState->SetDrawingRange(_drawingRange); renderPassState->SetCullStyle(_cullStyle); - HdSimpleLightingShaderSharedPtr &simpleLightingShader + HdxSimpleLightingShaderSharedPtr &simpleLightingShader = _renderPasses[renderPassIdx].simpleLightingShader; GlfSimpleLightingContextRefPtr const& simpleLightingContext = simpleLightingShader->GetLightingContext(); diff --git a/pxr/imaging/lib/hdx/drawTargetTask.h b/pxr/imaging/lib/hdx/drawTargetTask.h index 084050f59e..e7d4e2964a 100644 --- a/pxr/imaging/lib/hdx/drawTargetTask.h +++ b/pxr/imaging/lib/hdx/drawTargetTask.h @@ -25,15 +25,16 @@ #define HDX_DRAW_TARGET_TASK_H #include "pxr/imaging/hdx/version.h" + #include "pxr/imaging/hd/task.h" #include "pxr/imaging/hd/drawTargetRenderPass.h" -#include "pxr/imaging/hd/simpleLightingShader.h" #include "pxr/base/gf/vec2f.h" #include "pxr/base/gf/vec4f.h" typedef boost::weak_ptr HdDrawTargetWeakPtr; typedef std::unique_ptr HdDrawTargetRenderPassUniquePtr; +typedef boost::shared_ptr HdxSimpleLightingShaderSharedPtr; // Not strictly necessary here. // But without it, would require users of the class to include it anyway @@ -55,11 +56,11 @@ class HdxDrawTargetTask : public HdSceneTask { // use by std::vector::reserve(). struct RenderPassInfo { - HdDrawTargetRenderPassUniquePtr pass; - HdRenderPassStateSharedPtr renderPassState; - HdSimpleLightingShaderSharedPtr simpleLightingShader; - HdDrawTargetWeakPtr target; - unsigned int version; + HdDrawTargetRenderPassUniquePtr pass; + HdRenderPassStateSharedPtr renderPassState; + HdxSimpleLightingShaderSharedPtr simpleLightingShader; + HdDrawTargetWeakPtr target; + unsigned int version; }; bool _enableDrawTargets; diff --git a/pxr/imaging/lib/hdx/package.cpp b/pxr/imaging/lib/hdx/package.cpp index c7976b2610..6ec5d49ce6 100644 --- a/pxr/imaging/lib/hdx/package.cpp +++ b/pxr/imaging/lib/hdx/package.cpp @@ -54,3 +54,10 @@ HdxPackageRenderPassIdShader() return shader; } +TfToken +HdxPackageSimpleLightingShader() +{ + static TfToken simpleLightingShader = + _GetShaderPath("simpleLightingShader.glslfx"); + return simpleLightingShader; +} diff --git a/pxr/imaging/lib/hdx/package.h b/pxr/imaging/lib/hdx/package.h index e66eae1216..9e3ab81b5e 100644 --- a/pxr/imaging/lib/hdx/package.h +++ b/pxr/imaging/lib/hdx/package.h @@ -29,5 +29,6 @@ TfToken HdxPackageRenderPassShader(); TfToken HdxPackageRenderPassIdShader(); +TfToken HdxPackageSimpleLightingShader(); #endif diff --git a/pxr/imaging/lib/hdx/selectionTask.cpp b/pxr/imaging/lib/hdx/selectionTask.cpp index e7be69387c..3fe04d3797 100644 --- a/pxr/imaging/lib/hdx/selectionTask.cpp +++ b/pxr/imaging/lib/hdx/selectionTask.cpp @@ -33,7 +33,6 @@ #include "pxr/imaging/hd/renderIndex.h" #include "pxr/imaging/hd/resourceRegistry.h" #include "pxr/imaging/hd/sceneDelegate.h" -#include "pxr/imaging/hd/simpleLightingShader.h" #include "pxr/imaging/hd/vtBufferSource.h" // -------------------------------------------------------------------------- // diff --git a/pxr/imaging/lib/hd/shaders/simpleLightingShader.glslfx b/pxr/imaging/lib/hdx/shaders/simpleLightingShader.glslfx similarity index 89% rename from pxr/imaging/lib/hd/shaders/simpleLightingShader.glslfx rename to pxr/imaging/lib/hdx/shaders/simpleLightingShader.glslfx index cd520699fd..fa4b2ce7bc 100644 --- a/pxr/imaging/lib/hd/shaders/simpleLightingShader.glslfx +++ b/pxr/imaging/lib/hdx/shaders/simpleLightingShader.glslfx @@ -25,7 +25,7 @@ // --- This is what an import might look like. ---- #import $TOOLS/hd/shaders/simpleLightingShader.glslfx +--- #import $TOOLS/hdx/shaders/simpleLightingShader.glslfx #import $TOOLS/glf/shaders/pcfShader.glslfx #import $TOOLS/glf/shaders/simpleLighting.glslfx @@ -47,8 +47,13 @@ -- glsl LightingOverride.SimpleLighting -vec3 SimpleLighting(in vec3 Peye, in vec3 Neye, in vec3 color) +vec3 FallbackLighting(in vec3 Peye, in vec3 Neye, in vec3 color) { return simpleLightingMaterial(vec4(color,1), vec4(Peye,1), Neye, vec4(1)).rgb; } +// XXX: for short-term compatibility. +vec3 SimpleLighting(in vec3 Peye, in vec3 Neye, in vec3 color) +{ + return FallbackLighting(Peye, Neye, color); +} diff --git a/pxr/imaging/lib/hdx/shadowTask.cpp b/pxr/imaging/lib/hdx/shadowTask.cpp index 92116dcb80..3d1b0feeb0 100644 --- a/pxr/imaging/lib/hdx/shadowTask.cpp +++ b/pxr/imaging/lib/hdx/shadowTask.cpp @@ -37,7 +37,8 @@ #include "pxr/imaging/hd/resourceRegistry.h" #include "pxr/imaging/hd/sceneDelegate.h" #include "pxr/imaging/hd/lightingShader.h" -#include "pxr/imaging/hd/simpleLightingShader.h" + +#include "pxr/imaging/glf/simpleLightingContext.h" HdxShadowTask::HdxShadowTask(HdSceneDelegate* delegate, SdfPath const& id) : HdSceneTask(delegate, id) diff --git a/pxr/imaging/lib/hdx/shadowTask.h b/pxr/imaging/lib/hdx/shadowTask.h index c6da945c72..0c2b1e6499 100644 --- a/pxr/imaging/lib/hdx/shadowTask.h +++ b/pxr/imaging/lib/hdx/shadowTask.h @@ -41,7 +41,6 @@ class GlfSimpleLight; typedef boost::shared_ptr HdRenderPassStateSharedPtr; typedef boost::shared_ptr HdRenderPassSharedPtr; -typedef boost::shared_ptr HdSimpleLightingShaderSharedPtr; typedef std::vector HdRenderPassStateSharedPtrVector; typedef std::vector HdRenderPassSharedPtrVector; diff --git a/pxr/imaging/lib/hdx/simpleLightBypassTask.cpp b/pxr/imaging/lib/hdx/simpleLightBypassTask.cpp index 83115698bf..0e322051bf 100644 --- a/pxr/imaging/lib/hdx/simpleLightBypassTask.cpp +++ b/pxr/imaging/lib/hdx/simpleLightBypassTask.cpp @@ -23,20 +23,20 @@ // #include "pxr/imaging/hdx/simpleLightBypassTask.h" +#include "pxr/imaging/hdx/simpleLightingShader.h" #include "pxr/imaging/hdx/tokens.h" #include "pxr/imaging/hd/camera.h" #include "pxr/imaging/hd/perfLog.h" #include "pxr/imaging/hd/renderIndex.h" #include "pxr/imaging/hd/sceneDelegate.h" -#include "pxr/imaging/hd/simpleLightingShader.h" // -------------------------------------------------------------------------- // HdxSimpleLightBypassTask::HdxSimpleLightBypassTask(HdSceneDelegate* delegate, SdfPath const& id) : HdSceneTask(delegate, id) - , _lightingShader(new HdSimpleLightingShader()) + , _lightingShader(new HdxSimpleLightingShader()) , _simpleLightingContext() { } diff --git a/pxr/imaging/lib/hdx/simpleLightBypassTask.h b/pxr/imaging/lib/hdx/simpleLightBypassTask.h index fda09759e3..9f0987c782 100644 --- a/pxr/imaging/lib/hdx/simpleLightBypassTask.h +++ b/pxr/imaging/lib/hdx/simpleLightBypassTask.h @@ -43,7 +43,7 @@ class HdRenderIndex; class HdSceneDelegate; -typedef boost::shared_ptr HdSimpleLightingShaderSharedPtr; +typedef boost::shared_ptr HdxSimpleLightingShaderSharedPtr; class HdxSimpleLightBypassTask : public HdSceneTask { @@ -59,7 +59,7 @@ class HdxSimpleLightBypassTask : public HdSceneTask { private: HdCameraSharedPtr _camera; - HdSimpleLightingShaderSharedPtr _lightingShader; + HdxSimpleLightingShaderSharedPtr _lightingShader; GlfSimpleLightingContextRefPtr _simpleLightingContext; }; diff --git a/pxr/imaging/lib/hdx/simpleLightTask.cpp b/pxr/imaging/lib/hdx/simpleLightTask.cpp index c0bebf2149..12ef948c2d 100644 --- a/pxr/imaging/lib/hdx/simpleLightTask.cpp +++ b/pxr/imaging/lib/hdx/simpleLightTask.cpp @@ -25,6 +25,7 @@ #include "pxr/imaging/hdx/simpleLightTask.h" #include "pxr/imaging/hdx/tokens.h" +#include "pxr/imaging/hdx/simpleLightingShader.h" #include "pxr/imaging/hdx/shadowMatrixComputation.h" #include "pxr/imaging/hd/camera.h" @@ -33,7 +34,6 @@ #include "pxr/imaging/hd/renderIndex.h" #include "pxr/imaging/hd/renderPass.h" #include "pxr/imaging/hd/sceneDelegate.h" -#include "pxr/imaging/hd/simpleLightingShader.h" #include "pxr/imaging/glf/simpleLight.h" @@ -49,7 +49,7 @@ HdxSimpleLightTask::HdxSimpleLightTask(HdSceneDelegate* delegate, SdfPath const& : HdSceneTask(delegate, id) , _camera() , _lights() - , _lightingShader(new HdSimpleLightingShader()) + , _lightingShader(new HdxSimpleLightingShader()) , _collectionVersion(0) , _enableShadows(false) , _viewport(0.0f, 0.0f, 0.0f, 0.0f) diff --git a/pxr/imaging/lib/hdx/simpleLightTask.h b/pxr/imaging/lib/hdx/simpleLightTask.h index 5c36ebacb7..9e3244f85f 100644 --- a/pxr/imaging/lib/hdx/simpleLightTask.h +++ b/pxr/imaging/lib/hdx/simpleLightTask.h @@ -41,7 +41,7 @@ class HdRenderIndex; class HdSceneDelegate; typedef boost::shared_ptr HdRenderPassSharedPtr; -typedef boost::shared_ptr HdSimpleLightingShaderSharedPtr; +typedef boost::shared_ptr HdxSimpleLightingShaderSharedPtr; typedef boost::shared_ptr HdxShadowMatrixComputationSharedPtr; TF_DECLARE_REF_PTRS(GlfSimpleShadowArray); @@ -62,7 +62,7 @@ class HdxSimpleLightTask : public HdSceneTask { // Should be weak ptrs HdCameraSharedPtr _camera; HdLightSharedPtrVector _lights; - HdSimpleLightingShaderSharedPtr _lightingShader; + HdxSimpleLightingShaderSharedPtr _lightingShader; int _collectionVersion; bool _enableShadows; GfVec4f _viewport; diff --git a/pxr/imaging/lib/hd/simpleLightingShader.cpp b/pxr/imaging/lib/hdx/simpleLightingShader.cpp similarity index 83% rename from pxr/imaging/lib/hd/simpleLightingShader.cpp rename to pxr/imaging/lib/hdx/simpleLightingShader.cpp index af2427a526..d64d54e6a0 100644 --- a/pxr/imaging/lib/hd/simpleLightingShader.cpp +++ b/pxr/imaging/lib/hdx/simpleLightingShader.cpp @@ -21,10 +21,10 @@ // KIND, either express or implied. See the Apache License for the specific // language governing permissions and limitations under the Apache License. // -#include "pxr/imaging/hd/simpleLightingShader.h" +#include "pxr/imaging/hdx/simpleLightingShader.h" +#include "pxr/imaging/hdx/package.h" #include "pxr/imaging/hd/binding.h" -#include "pxr/imaging/hd/package.h" #include "pxr/imaging/hd/perfLog.h" #include "pxr/imaging/hd/tokens.h" @@ -37,7 +37,7 @@ #include #include -HdSimpleLightingShader::HdSimpleLightingShader() +HdxSimpleLightingShader::HdxSimpleLightingShader() : _lightingContext(GlfSimpleLightingContext::New()) , _bindingMap(TfCreateRefPtr(new GlfBindingMap())) , _useLighting(true) @@ -48,20 +48,20 @@ HdSimpleLightingShader::HdSimpleLightingShader() _lightingContext->InitUniformBlockBindings(_bindingMap); _lightingContext->InitSamplerUnitBindings(_bindingMap); - _glslfx.reset(new GlfGLSLFX(HdPackageSimpleLightingShader())); + _glslfx.reset(new GlfGLSLFX(HdxPackageSimpleLightingShader())); } -HdSimpleLightingShader::~HdSimpleLightingShader() +HdxSimpleLightingShader::~HdxSimpleLightingShader() { } /* virtual */ -HdSimpleLightingShader::ID -HdSimpleLightingShader::ComputeHash() const +HdxSimpleLightingShader::ID +HdxSimpleLightingShader::ComputeHash() const { HD_TRACE_FUNCTION(); - TfToken glslfxFile = HdPackageSimpleLightingShader(); + TfToken glslfxFile = HdxPackageSimpleLightingShader(); size_t numLights = _useLighting ? _lightingContext->GetNumLightsUsed() : 0; bool useShadows = _useLighting ? _lightingContext->GetUseShadows() : false; @@ -74,7 +74,7 @@ HdSimpleLightingShader::ComputeHash() const /* virtual */ std::string -HdSimpleLightingShader::GetSource(TfToken const &shaderStageKey) const +HdxSimpleLightingShader::GetSource(TfToken const &shaderStageKey) const { HD_TRACE_FUNCTION(); HD_MALLOC_TAG_FUNCTION(); @@ -94,7 +94,7 @@ HdSimpleLightingShader::GetSource(TfToken const &shaderStageKey) const /* virtual */ void -HdSimpleLightingShader::SetCamera(GfMatrix4d const &worldToViewMatrix, +HdxSimpleLightingShader::SetCamera(GfMatrix4d const &worldToViewMatrix, GfMatrix4d const &projectionMatrix) { _lightingContext->SetCamera(worldToViewMatrix, projectionMatrix); @@ -102,7 +102,7 @@ HdSimpleLightingShader::SetCamera(GfMatrix4d const &worldToViewMatrix, /* virtual */ void -HdSimpleLightingShader::BindResources(Hd_ResourceBinder const &binder, +HdxSimpleLightingShader::BindResources(Hd_ResourceBinder const &binder, int program) { // XXX: we'd like to use Hd_ResourceBinder instead of GlfBindingMap. @@ -116,7 +116,7 @@ HdSimpleLightingShader::BindResources(Hd_ResourceBinder const &binder, /* virtual */ void -HdSimpleLightingShader::UnbindResources(Hd_ResourceBinder const &binder, +HdxSimpleLightingShader::UnbindResources(Hd_ResourceBinder const &binder, int program) { // XXX: we'd like to use Hd_ResourceBinder instead of GlfBindingMap. @@ -126,18 +126,18 @@ HdSimpleLightingShader::UnbindResources(Hd_ResourceBinder const &binder, /*virtual*/ void -HdSimpleLightingShader::AddBindings(HdBindingRequestVector *customBindings) +HdxSimpleLightingShader::AddBindings(HdBindingRequestVector *customBindings) { } void -HdSimpleLightingShader::SetLightingStateFromOpenGL() +HdxSimpleLightingShader::SetLightingStateFromOpenGL() { _lightingContext->SetStateFromOpenGL(); } void -HdSimpleLightingShader::SetLightingState( +HdxSimpleLightingShader::SetLightingState( GlfSimpleLightingContextPtr const &src) { if (src) { diff --git a/pxr/imaging/lib/hd/simpleLightingShader.h b/pxr/imaging/lib/hdx/simpleLightingShader.h similarity index 87% rename from pxr/imaging/lib/hd/simpleLightingShader.h rename to pxr/imaging/lib/hdx/simpleLightingShader.h index f5e8098d10..f375ba52aa 100644 --- a/pxr/imaging/lib/hd/simpleLightingShader.h +++ b/pxr/imaging/lib/hdx/simpleLightingShader.h @@ -21,8 +21,8 @@ // KIND, either express or implied. See the Apache License for the specific // language governing permissions and limitations under the Apache License. // -#ifndef HD_SIMPLE_LIGHTING_SHADER_H -#define HD_SIMPLE_LIGHTING_SHADER_H +#ifndef HDX_SIMPLE_LIGHTING_SHADER_H +#define HDX_SIMPLE_LIGHTING_SHADER_H #include "pxr/imaging/hd/version.h" #include "pxr/imaging/hd/lightingShader.h" @@ -42,16 +42,16 @@ #include -typedef boost::shared_ptr HdSimpleLightingShaderSharedPtr; +typedef boost::shared_ptr HdxSimpleLightingShaderSharedPtr; -/// \class HdSimpleLightingShader +/// \class HdxSimpleLightingShader /// /// A shader that supports simple lighting functionality. /// -class HdSimpleLightingShader : public HdLightingShader { +class HdxSimpleLightingShader : public HdLightingShader { public: - HdSimpleLightingShader(); - virtual ~HdSimpleLightingShader(); + HdxSimpleLightingShader(); + virtual ~HdxSimpleLightingShader(); /// HdShader overrides virtual ID ComputeHash() const; @@ -78,4 +78,4 @@ class HdSimpleLightingShader : public HdLightingShader { boost::scoped_ptr _glslfx; }; -#endif // HD_SIMPLE_LIGHTING_SHADER_H +#endif // HDX_SIMPLE_LIGHTING_SHADER_H diff --git a/pxr/imaging/lib/hdx/version.h b/pxr/imaging/lib/hdx/version.h index df78a7c083..5cf965d2d2 100644 --- a/pxr/imaging/lib/hdx/version.h +++ b/pxr/imaging/lib/hdx/version.h @@ -25,6 +25,7 @@ #define HDX_VERSION_H // 1 -> 2 : split HdxRenderSetupTask out of HdxRenderTask -#define HDX_API 2 +// 2 -> 3 : move simpleLightingShader to Hdx. +#define HDX_API 3 #endif // HDX_VERSION_H From fc7a2d45e5b0c69d19d191dbf0ec460f21fd7aa0 Mon Sep 17 00:00:00 2001 From: dakrunch Date: Tue, 6 Sep 2016 14:04:23 -0700 Subject: [PATCH 092/380] usd ui update with state and icon path hint. (Internal change: 1651937) --- pxr/usd/lib/usdUI/generatedSchema.usda | 14 ++++++ pxr/usd/lib/usdUI/nodeGraphNodeAPI.cpp | 36 +++++++++++++++ pxr/usd/lib/usdUI/nodeGraphNodeAPI.h | 51 ++++++++++++++++++++++ pxr/usd/lib/usdUI/schema.usda | 22 ++++++++++ pxr/usd/lib/usdUI/tokens.h | 10 +++++ pxr/usd/lib/usdUI/wrapNodeGraphNodeAPI.cpp | 28 ++++++++++++ 6 files changed, 161 insertions(+) diff --git a/pxr/usd/lib/usdUI/generatedSchema.usda b/pxr/usd/lib/usdUI/generatedSchema.usda index 366c34531b..31ab9ff61e 100644 --- a/pxr/usd/lib/usdUI/generatedSchema.usda +++ b/pxr/usd/lib/usdUI/generatedSchema.usda @@ -14,6 +14,20 @@ class "NodeGraphNodeAPI" ( This hint defines what tint the node should have in the node graph. """ ) + uniform token ui:nodegraph:node:expansionState ( + allowedTokens = ["open", "closed", "minimized"] + doc = """ + The current expansionState of the node in the ui. + 'open' = fully expanded + 'closed' = fully collapsed + 'minimized' = should take the least space possible + """ + ) + uniform asset ui:nodegraph:node:icon ( + doc = """ + This points to an image that should be displayed on the node + """ + ) uniform float2 ui:nodegraph:node:pos ( doc = """ Declared relative position to the parent in a node graph. diff --git a/pxr/usd/lib/usdUI/nodeGraphNodeAPI.cpp b/pxr/usd/lib/usdUI/nodeGraphNodeAPI.cpp index 51635f0af1..32b1c1e1fc 100644 --- a/pxr/usd/lib/usdUI/nodeGraphNodeAPI.cpp +++ b/pxr/usd/lib/usdUI/nodeGraphNodeAPI.cpp @@ -127,6 +127,40 @@ UsdUINodeGraphNodeAPI::CreateDisplayColorAttr(VtValue const &defaultValue, bool writeSparsely); } +UsdAttribute +UsdUINodeGraphNodeAPI::GetIconAttr() const +{ + return GetPrim().GetAttribute(UsdUITokens->uiNodegraphNodeIcon); +} + +UsdAttribute +UsdUINodeGraphNodeAPI::CreateIconAttr(VtValue const &defaultValue, bool writeSparsely) const +{ + return UsdSchemaBase::_CreateAttr(UsdUITokens->uiNodegraphNodeIcon, + SdfValueTypeNames->Asset, + /* custom = */ false, + SdfVariabilityUniform, + defaultValue, + writeSparsely); +} + +UsdAttribute +UsdUINodeGraphNodeAPI::GetExpansionStateAttr() const +{ + return GetPrim().GetAttribute(UsdUITokens->uiNodegraphNodeExpansionState); +} + +UsdAttribute +UsdUINodeGraphNodeAPI::CreateExpansionStateAttr(VtValue const &defaultValue, bool writeSparsely) const +{ + return UsdSchemaBase::_CreateAttr(UsdUITokens->uiNodegraphNodeExpansionState, + SdfValueTypeNames->Token, + /* custom = */ false, + SdfVariabilityUniform, + defaultValue, + writeSparsely); +} + namespace { static inline TfTokenVector _ConcatenateAttributeNames(const TfTokenVector& left,const TfTokenVector& right) @@ -147,6 +181,8 @@ UsdUINodeGraphNodeAPI::GetSchemaAttributeNames(bool includeInherited) UsdUITokens->uiNodegraphNodePos, UsdUITokens->uiNodegraphNodeStackingOrder, UsdUITokens->uiNodegraphNodeDisplayColor, + UsdUITokens->uiNodegraphNodeIcon, + UsdUITokens->uiNodegraphNodeExpansionState, }; static TfTokenVector allNames = _ConcatenateAttributeNames( diff --git a/pxr/usd/lib/usdUI/nodeGraphNodeAPI.h b/pxr/usd/lib/usdUI/nodeGraphNodeAPI.h index 46c84ee093..7bf1cfefde 100644 --- a/pxr/usd/lib/usdUI/nodeGraphNodeAPI.h +++ b/pxr/usd/lib/usdUI/nodeGraphNodeAPI.h @@ -52,6 +52,11 @@ class SdfAssetPath; /// This api helps storing information about nodes in node graphs. /// /// +/// For any described attribute \em Fallback \em Value or \em Allowed \em Values below +/// that are text/tokens, the actual token is published and defined in \ref UsdUITokens. +/// So to set an attribute to the value "rightHanded", use UsdUITokens->rightHanded +/// as the value. +/// class UsdUINodeGraphNodeAPI : public UsdSchemaBase { public: @@ -188,6 +193,52 @@ class UsdUINodeGraphNodeAPI : public UsdSchemaBase /// the default for \p writeSparsely is \c false. UsdAttribute CreateDisplayColorAttr(VtValue const &defaultValue = VtValue(), bool writeSparsely=false) const; +public: + // --------------------------------------------------------------------- // + // ICON + // --------------------------------------------------------------------- // + /// + /// This points to an image that should be displayed on the node + /// + /// + /// \n C++ Type: SdfAssetPath + /// \n Usd Type: SdfValueTypeNames->Asset + /// \n Variability: SdfVariabilityUniform + /// \n Fallback Value: No Fallback + UsdAttribute GetIconAttr() const; + + /// See GetIconAttr(), and also + /// \ref Usd_Create_Or_Get_Property for when to use Get vs Create. + /// If specified, author \p defaultValue as the attribute's default, + /// sparsely (when it makes sense to do so) if \p writeSparsely is \c true - + /// the default for \p writeSparsely is \c false. + UsdAttribute CreateIconAttr(VtValue const &defaultValue = VtValue(), bool writeSparsely=false) const; + +public: + // --------------------------------------------------------------------- // + // EXPANSIONSTATE + // --------------------------------------------------------------------- // + /// + /// The current expansionState of the node in the ui. + /// 'open' = fully expanded + /// 'closed' = fully collapsed + /// 'minimized' = should take the least space possible + /// + /// + /// \n C++ Type: TfToken + /// \n Usd Type: SdfValueTypeNames->Token + /// \n Variability: SdfVariabilityUniform + /// \n Fallback Value: No Fallback + /// \n \ref UsdUITokens "Allowed Values": [open, closed, minimized] + UsdAttribute GetExpansionStateAttr() const; + + /// See GetExpansionStateAttr(), and also + /// \ref Usd_Create_Or_Get_Property for when to use Get vs Create. + /// If specified, author \p defaultValue as the attribute's default, + /// sparsely (when it makes sense to do so) if \p writeSparsely is \c true - + /// the default for \p writeSparsely is \c false. + UsdAttribute CreateExpansionStateAttr(VtValue const &defaultValue = VtValue(), bool writeSparsely=false) const; + public: // ===================================================================== // // Feel free to add custom code below this line, it will be preserved by diff --git a/pxr/usd/lib/usdUI/schema.usda b/pxr/usd/lib/usdUI/schema.usda index 2c516960b6..9d1e252d26 100644 --- a/pxr/usd/lib/usdUI/schema.usda +++ b/pxr/usd/lib/usdUI/schema.usda @@ -62,4 +62,26 @@ class "NodeGraphNodeAPI"( string apiName = "displayColor" } ) + + uniform asset ui:nodegraph:node:icon ( + doc = """ + This points to an image that should be displayed on the node + """ + customData = { + string apiName = "icon" + } + ) + + uniform token ui:nodegraph:node:expansionState ( + allowedTokens = ["open", "closed", "minimized"] + doc = """ + The current expansionState of the node in the ui. + 'open' = fully expanded + 'closed' = fully collapsed + 'minimized' = should take the least space possible + """ + customData = { + string apiName = "expansionState" + } + ) } diff --git a/pxr/usd/lib/usdUI/tokens.h b/pxr/usd/lib/usdUI/tokens.h index 2ee68bf118..89c2df1cab 100644 --- a/pxr/usd/lib/usdUI/tokens.h +++ b/pxr/usd/lib/usdUI/tokens.h @@ -37,7 +37,12 @@ /// \hideinitializer #define USDUI_TOKENS \ + (closed) \ + (minimized) \ + (open) \ ((uiNodegraphNodeDisplayColor, "ui:nodegraph:node:displayColor")) \ + ((uiNodegraphNodeExpansionState, "ui:nodegraph:node:expansionState")) \ + ((uiNodegraphNodeIcon, "ui:nodegraph:node:icon")) \ ((uiNodegraphNodePos, "ui:nodegraph:node:pos")) \ ((uiNodegraphNodeStackingOrder, "ui:nodegraph:node:stackingOrder")) @@ -61,7 +66,12 @@ /// \endcode /// /// The tokens are: +/// \li closed - Possible value for UsdUINodeGraphNodeAPI::GetUiNodegraphNodeExpansionStateAttr() +/// \li minimized - Possible value for UsdUINodeGraphNodeAPI::GetUiNodegraphNodeExpansionStateAttr() +/// \li open - Possible value for UsdUINodeGraphNodeAPI::GetUiNodegraphNodeExpansionStateAttr() /// \li uiNodegraphNodeDisplayColor - UsdUINodeGraphNodeAPI +/// \li uiNodegraphNodeExpansionState - UsdUINodeGraphNodeAPI +/// \li uiNodegraphNodeIcon - UsdUINodeGraphNodeAPI /// \li uiNodegraphNodePos - UsdUINodeGraphNodeAPI /// \li uiNodegraphNodeStackingOrder - UsdUINodeGraphNodeAPI TF_DECLARE_PUBLIC_TOKENS(UsdUITokens, USDUI_TOKENS); diff --git a/pxr/usd/lib/usdUI/wrapNodeGraphNodeAPI.cpp b/pxr/usd/lib/usdUI/wrapNodeGraphNodeAPI.cpp index e6d018ea52..70164d7ee8 100644 --- a/pxr/usd/lib/usdUI/wrapNodeGraphNodeAPI.cpp +++ b/pxr/usd/lib/usdUI/wrapNodeGraphNodeAPI.cpp @@ -66,6 +66,20 @@ _CreateDisplayColorAttr(UsdUINodeGraphNodeAPI &self, return self.CreateDisplayColorAttr( UsdPythonToSdfType(defaultVal, SdfValueTypeNames->Color3f), writeSparsely); } + +static UsdAttribute +_CreateIconAttr(UsdUINodeGraphNodeAPI &self, + object defaultVal, bool writeSparsely) { + return self.CreateIconAttr( + UsdPythonToSdfType(defaultVal, SdfValueTypeNames->Asset), writeSparsely); +} + +static UsdAttribute +_CreateExpansionStateAttr(UsdUINodeGraphNodeAPI &self, + object defaultVal, bool writeSparsely) { + return self.CreateExpansionStateAttr( + UsdPythonToSdfType(defaultVal, SdfValueTypeNames->Token), writeSparsely); +} void wrapUsdUINodeGraphNodeAPI() { @@ -116,6 +130,20 @@ void wrapUsdUINodeGraphNodeAPI() &_CreateDisplayColorAttr, (arg("defaultValue")=object(), arg("writeSparsely")=false)) + + .def("GetIconAttr", + &This::GetIconAttr) + .def("CreateIconAttr", + &_CreateIconAttr, + (arg("defaultValue")=object(), + arg("writeSparsely")=false)) + + .def("GetExpansionStateAttr", + &This::GetExpansionStateAttr) + .def("CreateExpansionStateAttr", + &_CreateExpansionStateAttr, + (arg("defaultValue")=object(), + arg("writeSparsely")=false)) ; From 444e86765b78b0764b95e42ca8c67bfba1615aba Mon Sep 17 00:00:00 2001 From: pixar-oss Date: Tue, 6 Sep 2016 14:04:35 -0700 Subject: [PATCH 093/380] Updating documentation for usd curves to be more doxygen friendly. (Internal change: 1652145) --- pxr/usd/lib/usdGeom/basisCurves.h | 90 +++++++++++----- pxr/usd/lib/usdGeom/curves.h | 8 +- pxr/usd/lib/usdGeom/generatedSchema.usda | 128 +++++++++++++++-------- pxr/usd/lib/usdGeom/nurbsCurves.h | 18 ++-- pxr/usd/lib/usdGeom/schema.usda | 124 ++++++++++++++-------- 5 files changed, 247 insertions(+), 121 deletions(-) diff --git a/pxr/usd/lib/usdGeom/basisCurves.h b/pxr/usd/lib/usdGeom/basisCurves.h index 145de249c1..b420cb1b17 100644 --- a/pxr/usd/lib/usdGeom/basisCurves.h +++ b/pxr/usd/lib/usdGeom/basisCurves.h @@ -48,48 +48,74 @@ class SdfAssetPath; /// \class UsdGeomBasisCurves /// -/// Basis curves are analagous to RiCurves. A basis matrix and vstep -/// are used to uniformly interpolate the curves. These curves are often used -/// to render dense aggregate geometry like hair. +/// Basis curves are analagous to RiCurves. A 'basis' matrix and +/// \em vstep are used to uniformly interpolate the curves. These curves are +/// often used to render dense aggregate geometry like hair. /// -/// A segment is the smoothly interpolated part between vertices. A curves prim -/// may have many curves, determined implicitly by the length of the -/// curveVertexCount vector. The number of segments an individual curve has is -/// determined by the number of vertices it has, the wrap (periodicity), and the -/// vstep of the basis. +/// A curves prim may have many curves, determined implicitly by the length of +/// the 'curveVertexCounts' vector. An individual curve is composed of one +/// or more curve segments, the smoothly interpolated part between vertices. /// -/// Basis to vstep mapping: -/// [bezier - 3, catmullRom - 1, bspline - 1, hermite - 2, power - 4] +/// Curves may have a m'type' of either linear or cubic. Linear curve +/// segments are interpolated between two vertices, and cubic curve segments are +/// interpolated between 4 vertices. The segment count of a cubic curve +/// is determined by the vertex count, the 'wrap' (periodicity), and +/// the vstep of the basis. +/// +/// cubic basis | vstep +/// ------------- | ------------- +/// bezier | 3 +/// catmullRom | 1 +/// bspline | 1 +/// hermite | 2 +/// power | 4 /// /// The first segment of a cubic curve is always defined by its first 4 points. /// The vstep is the increment used to determine what cv determines the -/// next segment. For a two segment bspline basis curve (vstep=1), the first +/// next segment. For a two segment bspline basis curve (vstep = 1), the first /// segment will be defined by interpolating vertices [0, 1, 2, 3] and the /// second segment will be defined by [1, 2, 3, 4]. For a two segment bezier /// basis curve (vstep = 3), the first segment will be defined by interpolating /// vertices [0, 1, 2, 3] and the second segment will be defined by /// [3, 4, 5, 6]. If the vstep is not one, then you must take special care -/// to make sure that the number of cvs properly divides by your vstep. +/// to make sure that the number of cvs properly divides by your vstep. If +/// the type of a curve is linear, the basis matrix and vstep are unused. +/// +/// When validating curve topology, each entry in the curveVertexCounts vector +/// must pass this check. +/// +/// wrap | cubic vertex count validity +/// -------------- | --------------------------------------- +/// nonperiodic | (curveVertexCounts[i] - 4) % vstep == 0 +/// periodic | (curveVertexCounts[i]) % vstep == 0 +/// +/// +/// To convert an entry in the curveVertexCounts vector into a segment count +/// for an individual curve, apply these rules. Sum up all the results in +/// order to compute how many total segments all curves have. /// -/// For a given cubic curve, it holds that: -/// (curveVertexCount - 4) % vstep == 0 [nonperiodic] -/// (curveVertexCount) % vstep == 0 [periodic] +/// wrap | segment count [linear curves] +/// ------------- | ---------------------------------------- +/// nonperiodic | curveVertexCounts[i] - 1 +/// periodic | curveVertexCounts[i] /// -/// For a given linear curve: -/// segmentCount = curveVertexCount - 1 [nonperiodic] -/// segmentCount = curveVertexCount [periodic] -/// For a given cubic curve: -/// segmentCount = (curveVertexCount - 4) / vstep + 1 [nonperiodic] -/// segmentCount = curveVertexCount / vstep [periodic] +/// wrap | segment count [cubic curves] +/// ------------- | ---------------------------------------- +/// nonperiodic | (curveVertexCounts[i] - 4) / vstep + 1 +/// periodic | curveVertexCounts[i] / vstep /// -/// For cubic curves, data can be either interpolated between vertices or -/// across segments. Per vertex data should be the same size as the number +/// +/// For cubic curves, primvar data can be either interpolated cubically between +/// vertices or linearly across segments. The corresponding token +/// for cubic interpolation is 'vertex' and for linear interpolation is +/// 'varying'. Per vertex data should be the same size as the number /// of vertices in your curve. Segment varying data is dependent on the /// wrap (periodicity) and number of segments in your curve. /// -/// For a given curve: -/// segmentVaryingDataSize = segmentCount + 1 [nonperiodic] -/// segmentVaryingDataSize = segmentCount [periodic] +/// wrap | expected linear (varying) data size +/// ------------- | ---------------------------------------- +/// nonperiodic | segmentCount + 1 +/// periodic | segmentCount /// /// This prim represents two different entries in the RI spec: RiBasis /// and RiCurves, hence the name "BasisCurves." If we are interested in @@ -97,6 +123,18 @@ class SdfAssetPath; /// enum could be extended with a new "custom" token and with additional /// attributes vstep and matrix, but for compatability with AbcGeom and the /// rarity of this use case, it is omitted for now. +/// +/// Example of deriving per curve segment and varying primvar data counts from +/// the wrap, type, basis, and curveVertexCount. +/// +/// wrap | type | basis | curveVertexCount | curveSegmentCount | varyingDataCount +/// ------------- | --------------------------------------------------------------------------------------- +/// nonperiodic | linear | N/A | [2 3 2 5] | [1 2 1 4] | [2 3 2 5] +/// nonperiodic | cubic | bezier | [4 7 10 4 7] | [1 2 3 1 2] | [2 3 4 2 3] +/// nonperiodic | cubic | bspline | [5 4 6 7] | [2 1 3 4] | [3 2 4 5] +/// periodic | cubic | bezier | [6 9 6] | [2 3 2] | [2 3 2] +/// periodic | linear | N/A | [3 7] | [3 7] | [3 7] +/// /// /// For any described attribute \em Fallback \em Value or \em Allowed \em Values below /// that are text/tokens, the actual token is published and defined in \ref UsdGeomTokens. diff --git a/pxr/usd/lib/usdGeom/curves.h b/pxr/usd/lib/usdGeom/curves.h index 0b4f7d362c..153ab12012 100644 --- a/pxr/usd/lib/usdGeom/curves.h +++ b/pxr/usd/lib/usdGeom/curves.h @@ -48,8 +48,12 @@ class SdfAssetPath; /// \class UsdGeomCurves /// -/// Base class for BasisCurves (RiCurves) and NurbsCurves -/// (MayaCurves). +/// Base class for BasisCurves and NurbsCurves. The BasisCurves +/// schema is designed to be analagous to RenderMan's RiCurves +/// and RiBasis, while the NurbsCurve schema is designed to be +/// analgous to the NURBS curves found in packages like Maya +/// and Houdini while retaining their consistency with the +/// RenderMan specification for NURBS Patches. /// class UsdGeomCurves : public UsdGeomPointBased { diff --git a/pxr/usd/lib/usdGeom/generatedSchema.usda b/pxr/usd/lib/usdGeom/generatedSchema.usda index e7971dab00..9454354533 100644 --- a/pxr/usd/lib/usdGeom/generatedSchema.usda +++ b/pxr/usd/lib/usdGeom/generatedSchema.usda @@ -1871,8 +1871,12 @@ class NurbsPatch "NurbsPatch" ( } class "Curves" ( - doc = """Base class for BasisCurves (RiCurves) and NurbsCurves - (MayaCurves).""" + doc = """Base class for BasisCurves and NurbsCurves. The BasisCurves + schema is designed to be analagous to RenderMan's RiCurves +\t and RiBasis, while the NurbsCurve schema is designed to be + analgous to the NURBS curves found in packages like Maya + and Houdini while retaining their consistency with the + RenderMan specification for NURBS Patches.""" ) { int[] curveVertexCounts ( @@ -2020,55 +2024,93 @@ class "Curves" ( } class BasisCurves "BasisCurves" ( - doc = '''Basis curves are analagous to RiCurves. A basis matrix and vstep - are used to uniformly interpolate the curves. These curves are often used - to render dense aggregate geometry like hair. + doc = """Basis curves are analagous to RiCurves. A 'basis' matrix and + vstep are used to uniformly interpolate the curves. These curves are + often used to render dense aggregate geometry like hair. - A segment is the smoothly interpolated part between vertices. A curves prim - may have many curves, determined implicitly by the length of the - curveVertexCount vector. The number of segments an individual curve has is - determined by the number of vertices it has, the wrap (periodicity), and the - vstep of the basis. + A curves prim may have many curves, determined implicitly by the length of + the 'curveVertexCounts' vector. An individual curve is composed of one + or more curve segments, the smoothly interpolated part between vertices. + + Curves may have a m'type' of either linear or cubic. Linear curve + segments are interpolated between two vertices, and cubic curve segments are + interpolated between 4 vertices. The segment count of a cubic curve + is determined by the vertex count, the 'wrap' (periodicity), and + the vstep of the basis. - Basis to vstep mapping: - [bezier - 3, catmullRom - 1, bspline - 1, hermite - 2, power - 4] + cubic basis | vstep + ------------- | ------------- + bezier | 3 + catmullRom | 1 + bspline | 1 + hermite | 2 + power | 4 The first segment of a cubic curve is always defined by its first 4 points. - The vstep is the increment used to determine what cv determines the - next segment. For a two segment bspline basis curve (vstep=1), the first + The vstep is the increment used to determine what cv determines the + next segment. For a two segment bspline basis curve (vstep = 1), the first segment will be defined by interpolating vertices [0, 1, 2, 3] and the second segment will be defined by [1, 2, 3, 4]. For a two segment bezier basis curve (vstep = 3), the first segment will be defined by interpolating vertices [0, 1, 2, 3] and the second segment will be defined by [3, 4, 5, 6]. If the vstep is not one, then you must take special care - to make sure that the number of cvs properly divides by your vstep. + to make sure that the number of cvs properly divides by your vstep. If + the type of a curve is linear, the basis matrix and vstep are unused. + + When validating curve topology, each entry in the curveVertexCounts vector + must pass this check. + + wrap | cubic vertex count validity + -------------- | --------------------------------------- + nonperiodic | (curveVertexCounts[i] - 4) % vstep == 0 + periodic | (curveVertexCounts[i]) % vstep == 0 + + + To convert an entry in the curveVertexCounts vector into a segment count + for an individual curve, apply these rules. Sum up all the results in + order to compute how many total segments all curves have. + + wrap | segment count [linear curves] + ------------- | ---------------------------------------- + nonperiodic | curveVertexCounts[i] - 1 + periodic | curveVertexCounts[i] - For a given cubic curve, it holds that: - (curveVertexCount - 4) % vstep == 0 [nonperiodic] - (curveVertexCount) % vstep == 0 [periodic] - - For a given linear curve: - segmentCount = curveVertexCount - 1 [nonperiodic] - segmentCount = curveVertexCount [periodic] - For a given cubic curve: - segmentCount = (curveVertexCount - 4) / vstep + 1 [nonperiodic] - segmentCount = curveVertexCount / vstep [periodic] - - For cubic curves, data can be either interpolated between vertices or - across segments. Per vertex data should be the same size as the number + wrap | segment count [cubic curves] + ------------- | ---------------------------------------- + nonperiodic | (curveVertexCounts[i] - 4) / vstep + 1 + periodic | curveVertexCounts[i] / vstep + + + For cubic curves, primvar data can be either interpolated cubically between + vertices or linearly across segments. The corresponding token + for cubic interpolation is 'vertex' and for linear interpolation is + 'varying'. Per vertex data should be the same size as the number of vertices in your curve. Segment varying data is dependent on the wrap (periodicity) and number of segments in your curve. - For a given curve: - segmentVaryingDataSize = segmentCount + 1 [nonperiodic] - segmentVaryingDataSize = segmentCount [periodic] + wrap | expected linear (varying) data size + ------------- | ---------------------------------------- + nonperiodic | segmentCount + 1 + periodic | segmentCount This prim represents two different entries in the RI spec: RiBasis - and RiCurves, hence the name "BasisCurves." If we are interested in + and RiCurves, hence the name \"BasisCurves.\" If we are interested in specifying a custom basis as RenderMan allows you to do, the basis - enum could be extended with a new "custom" token and with additional + enum could be extended with a new \"custom\" token and with additional attributes vstep and matrix, but for compatability with AbcGeom and the - rarity of this use case, it is omitted for now.''' + rarity of this use case, it is omitted for now. + + Example of deriving per curve segment and varying primvar data counts from + the wrap, type, basis, and curveVertexCount. + + wrap | type | basis | curveVertexCount | curveSegmentCount | varyingDataCount + ------------- | --------------------------------------------------------------------------------------- + nonperiodic | linear | N/A | [2 3 2 5] | [1 2 1 4] | [2 3 2 5] + nonperiodic | cubic | bezier | [4 7 10 4 7] | [1 2 3 1 2] | [2 3 4 2 3] + nonperiodic | cubic | bspline | [5 4 6 7] | [2 1 3 4] | [3 2 4 5] + periodic | cubic | bezier | [6 9 6] | [2 3 2] | [2 3 2] + periodic | linear | N/A | [3 7] | [3 7] | [3 7] +""" ) { uniform token basis = "bezier" ( @@ -2235,20 +2277,20 @@ class BasisCurves "BasisCurves" ( } class NurbsCurves "NurbsCurves" ( - doc = """Nurbs curves are analagous to Maya Nurbs Curves, used for - interchange of rigging and modeling curves. Unlike Maya Curves, this - curve spec supports batching of multiple curves into a single prim and - widths in the schema. Unlike maya, we require + doc = """This schema is analagous to NURBS Curves in packages like Maya + and Houdini, often used for interchange of rigging and modeling curves. + Unlike Maya, this curve spec supports batching of multiple curves into a + single prim and widths in the schema. Additionally, we require 'numSegments + 2 * degree + 1' knots (2 more than maya does). This is to - be more consistent with renderman's NURBS specification. + be more consistent with RenderMan's NURBS patch specification. To express a periodic curve: - knot[0] = knot[1] - (knots[-2] - knots[-3]; - knot[-1] = knot[-2] + (knot[2] - knots[1]); + - knot[0] = knot[1] - (knots[-2] - knots[-3]; + - knot[-1] = knot[-2] + (knot[2] - knots[1]); To express a nonperiodic curve: - knot[0] = knot[1]; - knot[-1] = knot[-2]; + - knot[0] = knot[1]; + - knot[-1] = knot[-2]; In spite of these slight differences in the spec, curves generated in Maya should be preserved when roundtripping.""" diff --git a/pxr/usd/lib/usdGeom/nurbsCurves.h b/pxr/usd/lib/usdGeom/nurbsCurves.h index 47ca2edb1f..ff57964ab8 100644 --- a/pxr/usd/lib/usdGeom/nurbsCurves.h +++ b/pxr/usd/lib/usdGeom/nurbsCurves.h @@ -48,20 +48,20 @@ class SdfAssetPath; /// \class UsdGeomNurbsCurves /// -/// Nurbs curves are analagous to Maya Nurbs Curves, used for -/// interchange of rigging and modeling curves. Unlike Maya Curves, this -/// curve spec supports batching of multiple curves into a single prim and -/// widths in the schema. Unlike maya, we require +/// This schema is analagous to NURBS Curves in packages like Maya +/// and Houdini, often used for interchange of rigging and modeling curves. +/// Unlike Maya, this curve spec supports batching of multiple curves into a +/// single prim and widths in the schema. Additionally, we require /// 'numSegments + 2 * degree + 1' knots (2 more than maya does). This is to -/// be more consistent with renderman's NURBS specification. +/// be more consistent with RenderMan's NURBS patch specification. /// /// To express a periodic curve: -/// knot[0] = knot[1] - (knots[-2] - knots[-3]; -/// knot[-1] = knot[-2] + (knot[2] - knots[1]); +/// - knot[0] = knot[1] - (knots[-2] - knots[-3]; +/// - knot[-1] = knot[-2] + (knot[2] - knots[1]); /// /// To express a nonperiodic curve: -/// knot[0] = knot[1]; -/// knot[-1] = knot[-2]; +/// - knot[0] = knot[1]; +/// - knot[-1] = knot[-2]; /// /// In spite of these slight differences in the spec, curves generated in Maya /// should be preserved when roundtripping. diff --git a/pxr/usd/lib/usdGeom/schema.usda b/pxr/usd/lib/usdGeom/schema.usda index bad4ed5e2f..8d972fc2fc 100644 --- a/pxr/usd/lib/usdGeom/schema.usda +++ b/pxr/usd/lib/usdGeom/schema.usda @@ -932,8 +932,12 @@ class NurbsPatch "NurbsPatch" ( class "Curves" ( inherits = - doc = """Base class for BasisCurves (RiCurves) and NurbsCurves - (MayaCurves).""" + doc = """Base class for BasisCurves and NurbsCurves. The BasisCurves + schema is designed to be analagous to RenderMan's RiCurves + and RiBasis, while the NurbsCurve schema is designed to be + analgous to the NURBS curves found in packages like Maya + and Houdini while retaining their consistency with the + RenderMan specification for NURBS Patches.""" ) { # topology attributes int[] curveVertexCounts ( @@ -956,55 +960,93 @@ class "Curves" ( class BasisCurves "BasisCurves" ( inherits = - doc = """Basis curves are analagous to RiCurves. A basis matrix and vstep - are used to uniformly interpolate the curves. These curves are often used - to render dense aggregate geometry like hair. - - A segment is the smoothly interpolated part between vertices. A curves prim - may have many curves, determined implicitly by the length of the - curveVertexCount vector. The number of segments an individual curve has is - determined by the number of vertices it has, the wrap (periodicity), and the - vstep of the basis. - - Basis to vstep mapping: - [bezier - 3, catmullRom - 1, bspline - 1, hermite - 2, power - 4] + doc = """Basis curves are analagous to RiCurves. A 'basis' matrix and + \\em vstep are used to uniformly interpolate the curves. These curves are + often used to render dense aggregate geometry like hair. + + A curves prim may have many curves, determined implicitly by the length of + the 'curveVertexCounts' vector. An individual curve is composed of one + or more curve segments, the smoothly interpolated part between vertices. + + Curves may have a m'type' of either linear or cubic. Linear curve + segments are interpolated between two vertices, and cubic curve segments are + interpolated between 4 vertices. The segment count of a cubic curve + is determined by the vertex count, the 'wrap' (periodicity), and + the vstep of the basis. + + cubic basis | vstep + ------------- | ------------- + bezier | 3 + catmullRom | 1 + bspline | 1 + hermite | 2 + power | 4 The first segment of a cubic curve is always defined by its first 4 points. - The vstep is the increment used to determine what cv determines the - next segment. For a two segment bspline basis curve (vstep=1), the first + The vstep is the increment used to determine what cv determines the + next segment. For a two segment bspline basis curve (vstep = 1), the first segment will be defined by interpolating vertices [0, 1, 2, 3] and the second segment will be defined by [1, 2, 3, 4]. For a two segment bezier basis curve (vstep = 3), the first segment will be defined by interpolating vertices [0, 1, 2, 3] and the second segment will be defined by [3, 4, 5, 6]. If the vstep is not one, then you must take special care - to make sure that the number of cvs properly divides by your vstep. + to make sure that the number of cvs properly divides by your vstep. If + the type of a curve is linear, the basis matrix and vstep are unused. - For a given cubic curve, it holds that: - (curveVertexCount - 4) % vstep == 0 [nonperiodic] - (curveVertexCount) % vstep == 0 [periodic] + When validating curve topology, each entry in the curveVertexCounts vector + must pass this check. + + wrap | cubic vertex count validity + -------------- | --------------------------------------- + nonperiodic | (curveVertexCounts[i] - 4) % vstep == 0 + periodic | (curveVertexCounts[i]) % vstep == 0 + - For a given linear curve: - segmentCount = curveVertexCount - 1 [nonperiodic] - segmentCount = curveVertexCount [periodic] - For a given cubic curve: - segmentCount = (curveVertexCount - 4) / vstep + 1 [nonperiodic] - segmentCount = curveVertexCount / vstep [periodic] + To convert an entry in the curveVertexCounts vector into a segment count + for an individual curve, apply these rules. Sum up all the results in + order to compute how many total segments all curves have. + + wrap | segment count [linear curves] + ------------- | ---------------------------------------- + nonperiodic | curveVertexCounts[i] - 1 + periodic | curveVertexCounts[i] + + wrap | segment count [cubic curves] + ------------- | ---------------------------------------- + nonperiodic | (curveVertexCounts[i] - 4) / vstep + 1 + periodic | curveVertexCounts[i] / vstep + - For cubic curves, data can be either interpolated between vertices or - across segments. Per vertex data should be the same size as the number + For cubic curves, primvar data can be either interpolated cubically between + vertices or linearly across segments. The corresponding token + for cubic interpolation is 'vertex' and for linear interpolation is + 'varying'. Per vertex data should be the same size as the number of vertices in your curve. Segment varying data is dependent on the wrap (periodicity) and number of segments in your curve. - For a given curve: - segmentVaryingDataSize = segmentCount + 1 [nonperiodic] - segmentVaryingDataSize = segmentCount [periodic] + wrap | expected linear (varying) data size + ------------- | ---------------------------------------- + nonperiodic | segmentCount + 1 + periodic | segmentCount This prim represents two different entries in the RI spec: RiBasis and RiCurves, hence the name "BasisCurves." If we are interested in specifying a custom basis as RenderMan allows you to do, the basis enum could be extended with a new "custom" token and with additional attributes vstep and matrix, but for compatability with AbcGeom and the - rarity of this use case, it is omitted for now.""" + rarity of this use case, it is omitted for now. + + Example of deriving per curve segment and varying primvar data counts from + the wrap, type, basis, and curveVertexCount. + + wrap | type | basis | curveVertexCount | curveSegmentCount | varyingDataCount + ------------- | --------------------------------------------------------------------------------------- + nonperiodic | linear | N/A | [2 3 2 5] | [1 2 1 4] | [2 3 2 5] + nonperiodic | cubic | bezier | [4 7 10 4 7] | [1 2 3 1 2] | [2 3 4 2 3] + nonperiodic | cubic | bspline | [5 4 6 7] | [2 1 3 4] | [3 2 4 5] + periodic | cubic | bezier | [6 9 6] | [2 3 2] | [2 3 2] + periodic | linear | N/A | [3 7] | [3 7] | [3 7] +""" ) { # interpolation attributes uniform token type = "cubic" ( @@ -1029,20 +1071,20 @@ class BasisCurves "BasisCurves" ( class NurbsCurves "NurbsCurves" ( inherits = - doc = """Nurbs curves are analagous to Maya Nurbs Curves, used for - interchange of rigging and modeling curves. Unlike Maya Curves, this - curve spec supports batching of multiple curves into a single prim and - widths in the schema. Unlike maya, we require + doc = """This schema is analagous to NURBS Curves in packages like Maya + and Houdini, often used for interchange of rigging and modeling curves. + Unlike Maya, this curve spec supports batching of multiple curves into a + single prim and widths in the schema. Additionally, we require 'numSegments + 2 * degree + 1' knots (2 more than maya does). This is to - be more consistent with renderman's NURBS specification. + be more consistent with RenderMan's NURBS patch specification. To express a periodic curve: - knot[0] = knot[1] - (knots[-2] - knots[-3]; - knot[-1] = knot[-2] + (knot[2] - knots[1]); + - knot[0] = knot[1] - (knots[-2] - knots[-3]; + - knot[-1] = knot[-2] + (knot[2] - knots[1]); To express a nonperiodic curve: - knot[0] = knot[1]; - knot[-1] = knot[-2]; + - knot[0] = knot[1]; + - knot[-1] = knot[-2]; In spite of these slight differences in the spec, curves generated in Maya should be preserved when roundtripping.""" From 022076fdb1d0aca081095bd08b13a377cb34b364 Mon Sep 17 00:00:00 2001 From: superfunc Date: Tue, 6 Sep 2016 14:06:56 -0700 Subject: [PATCH 094/380] [Usd] Fix error in value clips clipTimes metadata. Previously, it was reporting incorrect results for GetBracketingTimeSamples. (Internal change: 1652513) --- pxr/usd/lib/usd/clip.cpp | 30 ++++++++++++++++++++++++++---- 1 file changed, 26 insertions(+), 4 deletions(-) diff --git a/pxr/usd/lib/usd/clip.cpp b/pxr/usd/lib/usd/clip.cpp index 6bdc665966..a604641bf8 100644 --- a/pxr/usd/lib/usd/clip.cpp +++ b/pxr/usd/lib/usd/clip.cpp @@ -434,8 +434,19 @@ Usd_Clip::GetBracketingTimeSamplesForPath( const double upper = std::max(map1.second, map2.second); if (lower <= lowerInClip and lowerInClip <= upper) { - translatedLower.reset( - _TranslateTimeToExternal(lowerInClip, map1, map2)); + if (map1.second != map2.second) { + translatedLower.reset( + _TranslateTimeToExternal(lowerInClip, map1, map2)); + } else { + const bool lowerUpperMatch = (lowerInClip == upperInClip); + if (lowerUpperMatch && time == map1.first) { + translatedLower.reset(map1.first); + } else if (lowerUpperMatch && time == map2.first) { + translatedLower.reset(map2.first); + } else { + translatedLower.reset(map1.first); + } + } break; } } @@ -449,8 +460,19 @@ Usd_Clip::GetBracketingTimeSamplesForPath( const double upper = std::max(map1.second, map2.second); if (lower <= upperInClip and upperInClip <= upper) { - translatedUpper.reset( - _TranslateTimeToExternal(upperInClip, map1, map2)); + if (map1.second != map2.second) { + translatedUpper.reset( + _TranslateTimeToExternal(upperInClip, map1, map2)); + } else { + const bool lowerUpperMatch = (lowerInClip == upperInClip); + if (lowerUpperMatch && time == map1.first) { + translatedUpper.reset(map1.first); + } else if (lowerUpperMatch && time == map2.first) { + translatedUpper.reset(map2.first); + } else { + translatedUpper.reset(map2.first); + } + } break; } } From 126b0676b4d50b2592706148ad5bb3f01eff30e0 Mon Sep 17 00:00:00 2001 From: jloy Date: Tue, 6 Sep 2016 14:07:05 -0700 Subject: [PATCH 095/380] Tf: implement global swap overload for TfRefPtr. (Internal change: 1652572) --- pxr/base/lib/tf/refPtr.h | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/pxr/base/lib/tf/refPtr.h b/pxr/base/lib/tf/refPtr.h index 7c6999c4b9..2e10df1df7 100644 --- a/pxr/base/lib/tf/refPtr.h +++ b/pxr/base/lib/tf/refPtr.h @@ -1214,6 +1214,13 @@ struct TfTypeFunctions > { #if !defined(doxygen) +template +inline void +swap(TfRefPtr& lhs, TfRefPtr& rhs) +{ + lhs.swap(rhs); +} + namespace boost { template From 753f62b0f867dd176e5da6d184502b1027b05351 Mon Sep 17 00:00:00 2001 From: gitamohr Date: Tue, 6 Sep 2016 14:07:13 -0700 Subject: [PATCH 096/380] usd: Fix structure layout issue found in windows port, due to MSVC bug. Bump usdc minor version to 0.1.0 to accommodate new structure sizes. Software continues reading and writing 0.0.1 files by default. Add new env setting USD_WRITE_NEW_USDC_FILES_AS_VERSION, defaulting to 0.0.1 so clients can choose. Once this support has rolled out to release we'll change the default for this env setting to 0.1.0. (Internal change: 1652643) --- pxr/usd/lib/usd/crateFile.cpp | 365 +++++++++++++++++++++++++--------- pxr/usd/lib/usd/crateFile.h | 103 ++++++++-- 2 files changed, 359 insertions(+), 109 deletions(-) diff --git a/pxr/usd/lib/usd/crateFile.cpp b/pxr/usd/lib/usd/crateFile.cpp index d032e6320d..a33d0e8802 100644 --- a/pxr/usd/lib/usd/crateFile.cpp +++ b/pxr/usd/lib/usd/crateFile.cpp @@ -46,6 +46,7 @@ #include "pxr/base/gf/vec4f.h" #include "pxr/base/gf/vec4h.h" #include "pxr/base/gf/vec4i.h" +#include "pxr/base/tf/envSetting.h" #include "pxr/base/tf/errorMark.h" #include "pxr/base/tf/getenv.h" #include "pxr/base/tf/iterator.h" @@ -79,17 +80,44 @@ TF_REGISTRY_FUNCTION(TfType) { TfType::Define(); } +#define DEFAULT_NEW_VERSION "0.0.1" +TF_DEFINE_ENV_SETTING( + USD_WRITE_NEW_USDC_FILES_AS_VERSION, DEFAULT_NEW_VERSION, + "When writing new Usd Crate files, write them as this version. " + "This must have the same major version as the software and have less or " + "equal minor and patch versions. This is only for new files; saving " + "edits to an existing file preserves its version."); + // Write nbytes bytes to fd at pos. static inline ssize_t WriteToFd(FILE *file, void const *bytes, int64_t nbytes, int64_t pos) { int64_t nwritten = ArchPWrite(file, bytes, nbytes, pos); if (ARCH_UNLIKELY(nwritten < 0)) { - TF_RUNTIME_ERROR("Failed writing usdc data: %s", ArchStrerror().c_str()); + TF_RUNTIME_ERROR("Failed writing usdc data: %s", + ArchStrerror().c_str()); nwritten = 0; } return nwritten; } +namespace Usd_CrateFile +{ +// Metafunction that determines if a T instance can be read/written by simple +// bitwise copy. +template +struct _IsBitwiseReadWrite { + static const bool value = + std::is_enum::value || + std::is_arithmetic::value || + std::is_same::value || + std::is_trivial::value || + GfIsGfVec::value || + GfIsGfMatrix::value || + GfIsGfQuat::value || + std::is_base_of::value; +}; +} // Usd_CrateFile + namespace { using namespace Usd_CrateFile; @@ -108,21 +136,6 @@ constexpr _SectionName _KnownSections[] = { _FieldSetsSectionName, _PathsSectionName, _SpecsSectionName }; -// Metafunction that determines if a T instance can be read/written by simple -// bitwise copy. -template -struct _IsBitwiseReadWrite { - static const bool value = - std::is_enum::value or - std::is_arithmetic::value or - std::is_same::value or - std::is_trivial::value or - GfIsGfVec::value or - GfIsGfMatrix::value or - GfIsGfQuat::value or - std::is_base_of<_BitwiseReadWrite, T>::value; -}; - template constexpr bool _IsInlinedType() { using std::is_same; @@ -166,23 +179,6 @@ static constexpr ValueRep ValueRepForArray(uint64_t payload = 0) { /*isInlined=*/false, /*isArray=*/true, payload); } -int64_t -_GetFileSize(FILE *f) -{ - const int fd = fileno(f); - struct stat fileInfo; - if (fstat(fd, &fileInfo) != 0) { - TF_RUNTIME_ERROR("Error retrieving file size"); - return -1; - } - return fileInfo.st_size; -} - -string -_GetVersionString(uint8_t major, uint8_t minor, uint8_t patch) { - return TfStringPrintf("%d.%d.%d", major, minor, patch); -} - } // anon @@ -205,18 +201,118 @@ using std::unordered_map; using std::vector; constexpr uint8_t USDC_MAJOR = 0; -constexpr uint8_t USDC_MINOR = 0; -constexpr uint8_t USDC_PATCH = 1; +constexpr uint8_t USDC_MINOR = 1; +constexpr uint8_t USDC_PATCH = 0; + +struct CrateFile::Version +{ + // Not named 'major' since that's a macro name conflict on POSIXes. + uint8_t majver, minver, patchver; + + constexpr Version() : Version(0,0,0) {} + constexpr Version(uint8_t majver, uint8_t minver, uint8_t patchver) + : majver(majver), minver(minver), patchver(patchver) {} + + explicit Version(CrateFile::_BootStrap const &boot) + : Version(boot.version[0], boot.version[1], boot.version[2]) {} + + static Version FromString(char const *str) { + uint32_t maj, min, pat; + if (sscanf(str, "%u.%u.%u", &maj, &min, &pat) != 3 || + maj > 255 || min > 255 || pat > 255) { + return Version(); + } + return Version(maj, min, pat); + } + + constexpr uint32_t AsInt() const { + return static_cast(majver) << 16 | + static_cast(minver) << 8 | + static_cast(patchver); + } + + std::string AsString() const { + return TfStringPrintf("%d.%d.%d", majver, minver, patchver); + } + + bool IsValid() const { return AsInt() != 0; } + + // Return true if fileVer has the same major version as this, and has a + // lesser or same minor version. Patch version irrelevant, since the + // versioning scheme specifies that patch level changes are + // forward-compatible. + bool CanRead(Version const &fileVer) const { + return fileVer.majver == majver && fileVer.minver <= minver; + } + + // Return true if fileVer has the same major version as this, and has a + // lesser minor version, or has the same minor version and a lesser or equal + // patch version. + bool CanWrite(Version const &fileVer) const { + return fileVer.majver == majver && + (fileVer.minver < minver || + (fileVer.minver == minver && fileVer.patchver <= patchver)); + } + +#define LOGIC_OP(op) \ + constexpr bool operator op(Version const &other) const { \ + return AsInt() op other.AsInt(); \ + } + LOGIC_OP(==); LOGIC_OP(!=); + LOGIC_OP(<); LOGIC_OP(>); + LOGIC_OP(<=); LOGIC_OP(>=); +#undef LOGIC_OP +}; + +constexpr CrateFile::Version +_SoftwareVersion { USDC_MAJOR, USDC_MINOR, USDC_PATCH }; + +static CrateFile::Version +_GetVersionForNewlyCreatedFiles() { + // Read the env setting and try to parse a version. If that fails to + // give a version this software is capable of writing, fall back to the + // _SoftwareVersion. + string setting = TfGetEnvSetting(USD_WRITE_NEW_USDC_FILES_AS_VERSION); + auto ver = CrateFile::Version::FromString(setting.c_str()); + if (!ver.IsValid() || !_SoftwareVersion.CanWrite(ver)) { + TF_WARN("Invalid value '%s' for USD_WRITE_NEW_USDC_FILES_AS_VERSION - " + "falling back to default '%s'", + setting.c_str(), DEFAULT_NEW_VERSION); + ver = CrateFile::Version::FromString(DEFAULT_NEW_VERSION); + } + return ver; +} + +static CrateFile::Version +GetVersionForNewlyCreatedFiles() { + static CrateFile::Version ver = _GetVersionForNewlyCreatedFiles(); + return ver; +} constexpr char const *USDC_IDENT = "PXR-USDC"; // 8 chars. -struct _Token : _BitwiseReadWrite { - _Token() {} - explicit _Token(StringIndex si) : stringIndex(si) {} - StringIndex stringIndex; +struct _PathItemHeader_0_0_1 { + _PathItemHeader_0_0_1() {} + _PathItemHeader_0_0_1(PathIndex pi, TokenIndex ti, uint8_t bs) + : index(pi), elementTokenIndex(ti), bits(bs) {} + + // Deriving _BitwiseReadWrite and having members PathIndex and TokenIndex + // that derive _BitwiseReadWrite caused gcc on linux and mac to leave 4 + // bytes at the head of this structure, making the whole thing 16 bytes, + // with the members starting at offset 4. This was revealed in the Windows + // port since MSVC made this struct 12 bytes, as intended. To fix this we + // have two versions of the struct. Version 0.0.1 files read/write this + // structure. Version 0.1.0 and newer read/write the new one. + uint32_t _unused_padding_; + + PathIndex index; + TokenIndex elementTokenIndex; + uint8_t bits; }; +template <> +struct _IsBitwiseReadWrite<_PathItemHeader_0_0_1> : std::true_type {}; -struct _PathItemHeader : _BitwiseReadWrite { +struct _PathItemHeader { _PathItemHeader() {} _PathItemHeader(PathIndex pi, TokenIndex ti, uint8_t bs) : index(pi), elementTokenIndex(ti), bits(bs) {} @@ -227,8 +323,10 @@ struct _PathItemHeader : _BitwiseReadWrite { TokenIndex elementTokenIndex; uint8_t bits; }; +template <> +struct _IsBitwiseReadWrite<_PathItemHeader> : std::true_type {}; -struct _ListOpHeader : _BitwiseReadWrite { +struct _ListOpHeader { enum _Bits { IsExplicitBit = 1 << 0, HasExplicitItemsBit = 1 << 1, HasAddedItemsBit = 1 << 2, @@ -255,6 +353,7 @@ struct _ListOpHeader : _BitwiseReadWrite { uint8_t bits; }; +template <> struct _IsBitwiseReadWrite<_ListOpHeader> : std::true_type {}; struct _MmapStream { explicit _MmapStream(char const *mapStart) @@ -310,8 +409,12 @@ CrateFile::_TableOfContents::GetMinimumSectionStart() const // PackingContext struct CrateFile::_PackingContext { - _PackingContext(CrateFile *crate, FILE *file) - : file(file) { + _PackingContext(CrateFile *crate, FILE *file, std::string const &fileName) + : file(file) + , fileName(fileName) + , writeVersion(crate->_fileName.empty() ? + GetVersionForNewlyCreatedFiles() : + Version(crate->_boot)) { // Populate this context with everything we need from \p crate in order // to do deduplication, etc. WorkArenaDispatcher wd; @@ -394,8 +497,11 @@ struct CrateFile::_PackingContext // Unknown sections we're moving to the new structural area. vector, size_t>> unknownSections; - // File we're writing to. + // File and filename we're writing to. FILE *file; + std::string fileName; + // Version we're writing. + Version writeVersion; // Current position in output file. int64_t outFilePos; }; @@ -977,7 +1083,7 @@ CrateFile::CanRead(string const &fileName) { return false; TfErrorMark m; - _ReadBootStrap(_PreadStream(in.get()), _GetFileSize(in.get())); + _ReadBootStrap(_PreadStream(in.get()), ArchGetFileLength(in.get())); // Clear any issued errors again to avoid propagation, and return true if // there were no errors issued. @@ -1018,7 +1124,7 @@ CrateFile::Open(string const &fileName) return result; } - auto fileSize = _GetFileSize(inputFile.get()); + auto fileSize = ArchGetFileLength(inputFile.get()); if (not TfGetenvBool("USDC_USE_PREAD", false)) { // Map the file. auto mapStart = _MmapFile(fileName.c_str(), inputFile.get()); @@ -1041,16 +1147,14 @@ CrateFile::Open(string const &fileName) TfToken const & CrateFile::GetSoftwareVersionToken() { - static TfToken tok(_GetVersionString(USDC_MAJOR, USDC_MINOR, USDC_PATCH)); + static TfToken tok(_SoftwareVersion.AsString()); return tok; } TfToken CrateFile::GetFileVersionToken() const { - return TfToken( - _GetVersionString( - _boot.version[0], _boot.version[1], _boot.version[2])); + return TfToken(Version(_boot).AsString()); } CrateFile::CrateFile(bool useMmap) @@ -1109,11 +1213,10 @@ CrateFile::StartPacking(string const &fileName) TF_RUNTIME_ERROR("Failed to open '%s' for writing", fileName.c_str()); } else { // Create a packing context so we can start writing. - _packCtx.reset(new _PackingContext(this, out.release())); + _packCtx.reset(new _PackingContext(this, out.release(), fileName)); // Get rid of our local list of specs, if we have one -- the client is // required to repopulate it. vector().swap(_specs); - _fileName = fileName; } return Packer(this); } @@ -1133,6 +1236,10 @@ CrateFile::Packer::Close() // Write contents. bool writeResult = _crate->_Write(); + // If we wrote successfully, store the fileName. + if (writeResult) + _crate->_fileName = _crate->_packCtx->fileName; + // Pull out the file handle and kill the packing context. _UniqueFILE file(fp); _crate->_packCtx.reset(); @@ -1291,9 +1398,20 @@ CrateFile::_Write() _WriteSection( w, _FieldSetsSectionName, toc, [this, &w]() {w.Write(_fieldSets);}); _WriteSection(w, _PathsSectionName, toc, [this, &w]() {_WritePaths(w);}); - _WriteSection(w, _SpecsSectionName, toc, [this, &w]() {w.Write(_specs);}); - _BootStrap boot; + // VERSIONING: If we're writing version 0.0.1, we need to convert to the old + // form. + if (_packCtx->writeVersion == Version(0,0,1)) { + // Copy and write old-structure specs. + vector old(_specs.begin(), _specs.end()); + _WriteSection( + w, _SpecsSectionName, toc, [this, &w, &old]() {w.Write(old);}); + } else { + _WriteSection( + w, _SpecsSectionName, toc, [this, &w]() {w.Write(_specs);}); + } + + _BootStrap boot(_packCtx->writeVersion); // Record TOC location, and write it. boot.tocOffset = w.Tell(); @@ -1397,15 +1515,27 @@ CrateFile::_WritePathTree(_Writer &w, Iter cur, Iter end) auto elementToken = isPrimPropertyPath ? cur->first.GetNameToken() : cur->first.GetElementToken(); - _PathItemHeader header( - cur->second, _GetIndexForToken(elementToken), - static_cast( - (hasChild ? _PathItemHeader::HasChildBit : 0) | - (hasSibling ? _PathItemHeader::HasSiblingBit : 0) | - (isPrimPropertyPath ? - _PathItemHeader::IsPrimPropertyPathBit : 0))); - - w.Write(header); + // VERSIONING: If we're writing version 0.0.1, make sure we use the + // right header type. + if (_packCtx->writeVersion == Version(0,0,1)) { + _PathItemHeader_0_0_1 header( + cur->second, _GetIndexForToken(elementToken), + static_cast( + (hasChild ? _PathItemHeader::HasChildBit : 0) | + (hasSibling ? _PathItemHeader::HasSiblingBit : 0) | + (isPrimPropertyPath ? + _PathItemHeader::IsPrimPropertyPathBit : 0))); + w.Write(header); + } else { + _PathItemHeader header( + cur->second, _GetIndexForToken(elementToken), + static_cast( + (hasChild ? _PathItemHeader::HasChildBit : 0) | + (hasSibling ? _PathItemHeader::HasSiblingBit : 0) | + (isPrimPropertyPath ? + _PathItemHeader::IsPrimPropertyPathBit : 0))); + w.Write(header); + } // If there's both a child and a sibling, make space for the sibling // offset. @@ -1482,13 +1612,11 @@ CrateFile::_ReadBootStrap(ByteStream src, int64_t fileSize) TF_RUNTIME_ERROR("Usd crate bootstrap section corrupt"); } // Check version. - else if (b.version[0] != USDC_MAJOR or b.version[1] > USDC_MINOR) { - char const *type = b.version[0] != USDC_MAJOR ? "major" : "minor"; + else if (!_SoftwareVersion.CanRead(Version(b))) { TF_RUNTIME_ERROR( - "Usd crate file %s version mismatch -- file is %s, " - "software supports %s", type, - _GetVersionString(b.version[0], b.version[1], b.version[2]).c_str(), - GetSoftwareVersionToken().GetText()); + "Usd crate file version mismatch -- file is %s, " + "software supports %s", Version(b).AsString().c_str(), + _SoftwareVersion.AsString().c_str()); } return b; } @@ -1530,7 +1658,14 @@ CrateFile::_ReadSpecs(Reader reader) TfAutoMallocTag tag("_ReadSpecs"); if (auto specsSection = _toc.GetSection(_SpecsSectionName)) { reader.Seek(specsSection->start); - _specs = reader.template Read(); + // VERSIONING: Have to read either old or new style specs. + if (Version(_boot) == Version(0,0,1)) { + vector old = reader.template Read(); + _specs.resize(old.size()); + copy(old.begin(), old.end(), _specs.begin()); + } else { + _specs = reader.template Read(); + } } } @@ -1605,7 +1740,18 @@ CrateFile::_ReadPaths(Reader reader) // Read # of paths. _paths.resize(reader.template Read()); - auto root = reader.template Read<_PathItemHeader>(); + // VERSIONING: PathItemHeader changes size from 0.0.1 to 0.1.0. + Version fileVer(_boot); + _PathItemHeader root; + if (fileVer == Version(0,0,1)) { + auto old = reader.template Read<_PathItemHeader_0_0_1>(); + root.index = old.index; + root.elementTokenIndex = old.elementTokenIndex; + root.bits = old.bits; + } else { + root = reader.template Read<_PathItemHeader>(); + } + _paths[root.index.value] = SdfPath::AbsoluteRootPath(); bool hasChild = root.bits & _PathItemHeader::HasChildBit; @@ -1619,33 +1765,51 @@ CrateFile::_ReadPaths(Reader reader) WorkArenaDispatcher dispatcher; if (root.bits & _PathItemHeader::HasChildBit) { - auto firstChild = reader.template Read<_PathItemHeader>(); - dispatcher.Run( - [this, reader, firstChild, &dispatcher]() { - _ReadPathsRecursively(reader, SdfPath::AbsoluteRootPath(), - firstChild, dispatcher); - }); + if (fileVer == Version(0,0,1)) { + auto firstChild = reader.template Read<_PathItemHeader_0_0_1>(); + dispatcher.Run( + [this, reader, firstChild, &dispatcher]() { + _ReadPathsRecursively(reader, SdfPath::AbsoluteRootPath(), + firstChild, dispatcher); + }); + } else { + auto firstChild = reader.template Read<_PathItemHeader>(); + dispatcher.Run( + [this, reader, firstChild, &dispatcher]() { + _ReadPathsRecursively(reader, SdfPath::AbsoluteRootPath(), + firstChild, dispatcher); + }); + } } if (root.bits & _PathItemHeader::HasSiblingBit) { if (hasChild and hasSibling) reader.Seek(siblingOffset); - auto siblingHeader = reader.template Read<_PathItemHeader>(); - dispatcher.Run( - [this, reader, siblingHeader, &dispatcher]() { - _ReadPathsRecursively( - reader, SdfPath(), siblingHeader, dispatcher); - }); + if (fileVer == Version(0,0,1)) { + auto siblingHeader = reader.template Read<_PathItemHeader_0_0_1>(); + dispatcher.Run( + [this, reader, siblingHeader, &dispatcher]() { + _ReadPathsRecursively( + reader, SdfPath(), siblingHeader, dispatcher); + }); + } else { + auto siblingHeader = reader.template Read<_PathItemHeader>(); + dispatcher.Run( + [this, reader, siblingHeader, &dispatcher]() { + _ReadPathsRecursively( + reader, SdfPath(), siblingHeader, dispatcher); + }); + } } dispatcher.Wait(); } -template +template void CrateFile::_ReadPathsRecursively(Reader reader, const SdfPath &parentPath, - const _PathItemHeader &h, + const Header &h, WorkArenaDispatcher &dispatcher) { // XXX Won't need ANY of these tags when bug #132031 is addressed @@ -1675,15 +1839,14 @@ CrateFile::_ReadPathsRecursively(Reader reader, // than deep. // If this header item has a child, recurse to it. - auto childHeader = - hasChild ? reader.template Read<_PathItemHeader>() : _PathItemHeader(); + auto childHeader = hasChild ? reader.template Read
() : Header(); auto childReader = reader; - auto siblingHeader = _PathItemHeader(); + auto siblingHeader = Header(); if (hasSibling) { if (hasChild) reader.Seek(siblingOffset); - siblingHeader = reader.template Read<_PathItemHeader>(); + siblingHeader = reader.template Read
(); } if (hasSibling) { @@ -2001,14 +2164,22 @@ CrateFile::_Fcloser::operator()(FILE *f) const } } -CrateFile::_BootStrap::_BootStrap() +CrateFile::Spec::Spec(Spec_0_0_1 const &s) + : Spec(s.pathIndex, s.specType, s.fieldSetIndex) {} + +CrateFile::Spec_0_0_1::Spec_0_0_1(Spec const &s) + : Spec_0_0_1(s.pathIndex, s.specType, s.fieldSetIndex) {} + +CrateFile::_BootStrap::_BootStrap() : _BootStrap(_SoftwareVersion) {} + +CrateFile::_BootStrap::_BootStrap(Version const &ver) { memset(this, 0, sizeof(*this)); tocOffset = 0; memcpy(ident, USDC_IDENT, sizeof(ident)); - version[0] = USDC_MAJOR; - version[1] = USDC_MINOR; - version[2] = USDC_PATCH; + version[0] = ver.majver; + version[1] = ver.minver; + version[2] = ver.patchver; } CrateFile::_Section::_Section(char const *inName, int64_t start, int64_t size) @@ -2038,6 +2209,14 @@ operator<<(std::ostream &os, Index const &i) { return os << i.value; } +// Size checks for structures written to/read from disk. +static_assert(sizeof(CrateFile::Field) == 16, ""); +static_assert(sizeof(CrateFile::Spec) == 12, ""); +static_assert(sizeof(CrateFile::Spec_0_0_1) == 16, ""); +static_assert(sizeof(_PathItemHeader) == 12, ""); +static_assert(sizeof(_PathItemHeader_0_0_1) == 16, ""); + } // Usd_CrateFile + diff --git a/pxr/usd/lib/usd/crateFile.h b/pxr/usd/lib/usd/crateFile.h index c66b9887b6..799a4ef046 100644 --- a/pxr/usd/lib/usd/crateFile.h +++ b/pxr/usd/lib/usd/crateFile.h @@ -61,14 +61,11 @@ using std::unordered_map; using std::tuple; using std::vector; -// Forward declaration required here for certain MSVC versions. -struct _PathItemHeader; +// Trait indicating trivially copyable types, a hack since gcc doesn't yet +// implement is_trivially_copyable correctly. +template struct _IsBitwiseReadWrite; -// Tag indicating trivially copyable types, hack since gcc doesn't yet implement -// is_trivially_copyable correctly. -struct _BitwiseReadWrite {}; - -enum class TypeEnum : int; +enum class TypeEnum : int32_t; // Value in file representation. Consists of a 2 bytes of type information // (type enum value, array bit, and inlined-value bit) and 6 bytes of data. @@ -77,7 +74,7 @@ enum class TypeEnum : int; // (zero vectors, identity matrices, etc). For values that aren't stored // inline, the 6 data bytes are the offset from the start of the file to the // value's location. -struct ValueRep : _BitwiseReadWrite { +struct ValueRep { friend class CrateFile; @@ -143,6 +140,7 @@ struct ValueRep : _BitwiseReadWrite { uint64_t data; }; +template <> struct _IsBitwiseReadWrite : std::true_type {}; struct TimeSamples { typedef Usd_Shared> SharedTimes; @@ -211,7 +209,7 @@ enum class TypeEnum { // Index base class. Used to index various tables. Deriving adds some // type-safety so we don't accidentally use one kind of index with the wrong // kind of table. -struct Index : _BitwiseReadWrite { +struct Index { Index() : value(~0) {} explicit Index(uint32_t value) : value(value) {} bool operator==(const Index &other) const { return value == other.value; } @@ -261,6 +259,10 @@ struct _Hasher { class CrateFile { +public: + class Version; + +private: struct _Fcloser { void operator()(FILE *f) const; }; @@ -270,15 +272,16 @@ class CrateFile // _BootStrap structure. Appears at end of file, houses version, file // identifier string and offset to _TableOfContents. - struct _BootStrap : _BitwiseReadWrite { + struct _BootStrap { _BootStrap(); + explicit _BootStrap(Version const &); uint8_t ident[8]; // "PXR-USDC" uint8_t version[8]; // 0: major, 1: minor, 2: patch, rest unused. int64_t tocOffset; int64_t _reserved[8]; }; - struct _Section : _BitwiseReadWrite { + struct _Section { _Section() { memset(this, 0, sizeof(*this)); } _Section(char const *name, int64_t start, int64_t size); char name[_SectionNameMaxLength+1]; @@ -297,7 +300,20 @@ class CrateFile typedef std::pair FieldValuePair; - struct Field : _BitwiseReadWrite { + struct Field { + // This padding field accounts for a bug in an earlier implementation, + // where both this class and its first member derived an empty base + // class. The standard requires that those not have the same address so + // GCC & clang inserted 4 bytes for this class's empty base, causing the + // first member to land at offset 4. Porting to MSVC revealed this, + // since MSVC didn't implement this correctly and the first member + // landed at offset 0. To fix this, we've removed the empty base and + // inserted our own 4 byte padding to ensure the layout comes out the + // same everywhere. This doesn't actually change the overall structure + // size since the first member is 4 bytes and the second is 8. It's + // still 16 bytes however you slice it. + uint32_t _unused_padding_; + Field() {} Field(TokenIndex ti, ValueRep v) : tokenIndex(ti), valueRep(v) {} bool operator==(const Field &other) const { @@ -314,10 +330,13 @@ class CrateFile ValueRep valueRep; }; - struct Spec : _BitwiseReadWrite { + struct Spec_0_0_1; + + struct Spec { Spec() {} Spec(PathIndex pi, SdfSpecType type, FieldSetIndex fsi) : pathIndex(pi), fieldSetIndex(fsi), specType(type) {} + Spec(Spec_0_0_1 const &); bool operator==(const Spec &other) const { return pathIndex == other.pathIndex and fieldSetIndex == other.fieldSetIndex and @@ -338,6 +357,43 @@ class CrateFile SdfSpecType specType; }; + struct Spec_0_0_1 { + // This padding field accounts for a bug in this earlier implementation, + // where both this class and its first member derived an empty base + // class. The standard requires that those not have the same address so + // GCC & clang inserted 4 bytes for this class's empty base, causing the + // first member to land at offset 4. Porting to MSVC revealed this, + // since MSVC didn't implement this correctly and the first member + // landed at offset 0. To fix this, we've removed the empty base and + // inserted our own 4 byte padding to ensure the layout comes out the + // same everywhere. File version 0.1.0 revises this structure to the + // smaller size with no padding. + uint32_t _unused_padding_; + + Spec_0_0_1() {} + Spec_0_0_1(PathIndex pi, SdfSpecType type, FieldSetIndex fsi) + : pathIndex(pi), fieldSetIndex(fsi), specType(type) {} + Spec_0_0_1(Spec const &); + bool operator==(const Spec_0_0_1 &other) const { + return pathIndex == other.pathIndex and + fieldSetIndex == other.fieldSetIndex and + specType == other.specType; + } + bool operator!=(const Spec_0_0_1 &other) const { + return not (*this == other); + } + friend size_t hash_value(Spec_0_0_1 const &s) { + _Hasher h; + size_t result = h(s.pathIndex); + boost::hash_combine(result, s.fieldSetIndex); + boost::hash_combine(result, s.specType); + return result; + } + PathIndex pathIndex; + FieldSetIndex fieldSetIndex; + SdfSpecType specType; + }; + ~CrateFile(); static bool CanRead(string const &fileName); @@ -470,7 +526,6 @@ class CrateFile static ArchConstFileMapping _MmapFile(char const *fileName, FILE *file); class _Writer; - class _ReaderBase; template class _Reader; @@ -511,10 +566,10 @@ class CrateFile template void _ReadStrings(Reader src); template void _ReadTokens(Reader src); template void _ReadPaths(Reader src); - template + template void _ReadPathsRecursively( Reader src, const SdfPath &parentPath, - const _PathItemHeader &h, + const Header &h, WorkArenaDispatcher &dispatcher); void _ReadRawBytes(int64_t start, int64_t size, char *buf) const; @@ -629,6 +684,22 @@ class CrateFile const bool _useMmap; // If true, use mmap for reads, otherwise use pread. }; +template <> +struct _IsBitwiseReadWrite : std::true_type {}; + +template <> +struct _IsBitwiseReadWrite : std::true_type {}; + +template <> +struct _IsBitwiseReadWrite : std::true_type {}; + +template <> +struct _IsBitwiseReadWrite : std::true_type {}; + +template <> +struct _IsBitwiseReadWrite : std::true_type {}; + + } // Usd_CrateFile #endif // USD_CRATEFILE_H From a52ca782d9d1af476caec3861520b3b2c38f2e07 Mon Sep 17 00:00:00 2001 From: jloy Date: Tue, 6 Sep 2016 14:07:31 -0700 Subject: [PATCH 097/380] Tf: replace boost preprocessor and bind in TfPyFunctionFromPython. (Internal change: 1652657) --- pxr/base/lib/tf/pyFunction.h | 138 +++++++++++++++-------------------- 1 file changed, 58 insertions(+), 80 deletions(-) diff --git a/pxr/base/lib/tf/pyFunction.h b/pxr/base/lib/tf/pyFunction.h index a67595c8eb..dee484db9c 100644 --- a/pxr/base/lib/tf/pyFunction.h +++ b/pxr/base/lib/tf/pyFunction.h @@ -21,15 +21,9 @@ // KIND, either express or implied. See the Apache License for the specific // language governing permissions and limitations under the Apache License. // -#ifndef BOOST_PP_IS_ITERATING - #ifndef TF_PYFUNCTION_H #define TF_PYFUNCTION_H -#ifndef TF_MAX_ARITY -# define TF_MAX_ARITY 7 -#endif // TF_MAX_ARITY - #include "pxr/base/tf/pyCall.h" #include "pxr/base/tf/pyLock.h" #include "pxr/base/tf/pyObjWrapper.h" @@ -42,70 +36,63 @@ #include #include -#include #include -#include template struct TfPyFunctionFromPython; -#define BOOST_PP_ITERATION_LIMITS (0, TF_MAX_ARITY) -#define BOOST_PP_FILENAME_1 "pxr/base/tf/pyFunction.h" -#include BOOST_PP_ITERATE() -/* comment needed for scons dependency scanner -#include "pxr/base/tf/pyFunction.h" -*/ - -#endif // TF_PYFUNCTION_H - -#else // BOOST_PP_IS_ITERATING - -#define N BOOST_PP_ITERATION() - -// PLACEHOLDER is used to produce the _1 _2 _3 placeholders for -// boost::bind. -#define PLACEHOLDER(unused, n, unused2) BOOST_PP_CAT(_,BOOST_PP_INC(n)) - -template -struct TfPyFunctionFromPython +template +struct TfPyFunctionFromPython { - typedef boost::function FuncType; - - static Ret Call(TfPyObjWrapper const &callable - BOOST_PP_ENUM_TRAILING_BINARY_PARAMS(N, A, a)) { - TfPyLock lock; - return TfPyCall(callable)(BOOST_PP_ENUM_PARAMS(N, a)); - } + typedef boost::function FuncType; - static Ret CallWeak(TfPyObjWrapper const &weak - BOOST_PP_ENUM_TRAILING_BINARY_PARAMS(N, A, a)) { - using namespace boost::python; - // Attempt to get the referenced callable object. - TfPyLock lock; - object callable(handle<>(borrowed(PyWeakref_GetObject(weak.ptr())))); - if (TfPyIsNone(callable)) { - TF_WARN("Tried to call an expired python callback"); - return Ret(); - } - return TfPyCall(callable)(BOOST_PP_ENUM_PARAMS(N, a)); - } + struct Call + { + TfPyObjWrapper callable; - static Ret CallMethod(TfPyObjWrapper const &func, - TfPyObjWrapper const &weakSelf, - TfPyObjWrapper const &cls - BOOST_PP_ENUM_TRAILING_BINARY_PARAMS(N, A, a)) { - using namespace boost::python; - // Attempt to get the referenced self parameter, then build a new - // instance method and call it. - TfPyLock lock; - PyObject *self = PyWeakref_GetObject(weakSelf.ptr()); - if (self == Py_None) { - TF_WARN("Tried to call a method on an expired python instance"); - return Ret(); + Ret operator()(Args... args) { + TfPyLock lock; + return TfPyCall(callable)(args...); } - object method(handle<>(PyMethod_New(func.ptr(), self, cls.ptr()))); - return TfPyCall(method)(BOOST_PP_ENUM_PARAMS(N, a)); - } + }; + + struct CallWeak + { + TfPyObjWrapper weak; + + Ret operator()(Args... args) { + using namespace boost::python; + // Attempt to get the referenced callable object. + TfPyLock lock; + object callable(handle<>(borrowed(PyWeakref_GetObject(weak.ptr())))); + if (TfPyIsNone(callable)) { + TF_WARN("Tried to call an expired python callback"); + return Ret(); + } + return TfPyCall(callable)(args...); + } + }; + + struct CallMethod + { + TfPyObjWrapper func; + TfPyObjWrapper weakSelf; + TfPyObjWrapper cls; + + Ret operator()(Args... args) { + using namespace boost::python; + // Attempt to get the referenced self parameter, then build a new + // instance method and call it. + TfPyLock lock; + PyObject *self = PyWeakref_GetObject(weakSelf.ptr()); + if (self == Py_None) { + TF_WARN("Tried to call a method on an expired python instance"); + return Ret(); + } + object method(handle<>(PyMethod_New(func.ptr(), self, cls.ptr()))); + return TfPyCall(method)(args...); + } + }; TfPyFunctionFromPython() { using namespace boost::python; @@ -120,7 +107,6 @@ struct TfPyFunctionFromPython static void construct(PyObject *src, boost::python::converter:: rvalue_from_python_stage1_data *data) { using std::string; - using boost::bind; using namespace boost::python; void *storage = ((converter::rvalue_from_python_storage *) @@ -157,31 +143,26 @@ struct TfPyFunctionFromPython object func(handle<>(borrowed(PyMethod_GET_FUNCTION(pyCallable)))); object weakSelf(handle<>(PyWeakref_NewRef(self, NULL))); new (storage) - FuncType(bind(CallMethod, - TfPyObjWrapper(func), - TfPyObjWrapper(weakSelf), - TfPyObjWrapper(cls) - BOOST_PP_ENUM_TRAILING(N, PLACEHOLDER, ~))); + FuncType(CallMethod{ + TfPyObjWrapper(func), + TfPyObjWrapper(weakSelf), + TfPyObjWrapper(cls)}); + } else if (PyObject_HasAttrString(pyCallable, "__name__") and extract(callable.attr("__name__"))() == "") { // Explicitly hold on to strong references to lambdas. - new (storage) - FuncType(bind(Call, TfPyObjWrapper(callable) - BOOST_PP_ENUM_TRAILING(N, PLACEHOLDER, ~))); + new (storage) FuncType(Call{TfPyObjWrapper(callable)}); } else { // Attempt to get a weak reference to the callable. if (PyObject *weakCallable = PyWeakref_NewRef(pyCallable, NULL)) { new (storage) - FuncType(bind(CallWeak, - TfPyObjWrapper(object(handle<>(weakCallable))) - BOOST_PP_ENUM_TRAILING(N, PLACEHOLDER, ~))); + FuncType(CallWeak{ + TfPyObjWrapper(object(handle<>(weakCallable)))}); } else { // Fall back to taking a strong reference. PyErr_Clear(); - new (storage) - FuncType(bind(Call, TfPyObjWrapper(callable) - BOOST_PP_ENUM_TRAILING(N, PLACEHOLDER, ~))); + new (storage) FuncType(Call{TfPyObjWrapper(callable)}); } } @@ -189,7 +170,4 @@ struct TfPyFunctionFromPython } }; -#undef N -#undef PLACEHOLDER - -#endif // BOOST_PP_IS_ITERATING +#endif // TF_PYFUNCTION_H From 05ff1fbe3e5377e9a4ceee875426f5eb306f09dc Mon Sep 17 00:00:00 2001 From: jloy Date: Tue, 6 Sep 2016 17:29:47 -0700 Subject: [PATCH 098/380] Tf: provide from-Python conversion of callables to std::function. TfPyFunctionFromPython now registers conversions for both boost::function and std::function. (Internal change: 1652758) --- pxr/base/lib/tf/pyFunction.h | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/pxr/base/lib/tf/pyFunction.h b/pxr/base/lib/tf/pyFunction.h index dee484db9c..b48754cbf8 100644 --- a/pxr/base/lib/tf/pyFunction.h +++ b/pxr/base/lib/tf/pyFunction.h @@ -38,14 +38,14 @@ #include +#include + template struct TfPyFunctionFromPython; template struct TfPyFunctionFromPython { - typedef boost::function FuncType; - struct Call { TfPyObjWrapper callable; @@ -95,15 +95,23 @@ struct TfPyFunctionFromPython }; TfPyFunctionFromPython() { + RegisterFunctionType>(); + RegisterFunctionType>(); + } + + template + static void + RegisterFunctionType() { using namespace boost::python; converter::registry:: - insert(&convertible, &construct, type_id()); + insert(&convertible, &construct, type_id()); } static void *convertible(PyObject *obj) { return PyCallable_Check(obj) ? obj : 0; } + template static void construct(PyObject *src, boost::python::converter:: rvalue_from_python_stage1_data *data) { using std::string; From b901511d9bb64a47a2712ebd82c26667d6ae8af7 Mon Sep 17 00:00:00 2001 From: c64kernal Date: Tue, 6 Sep 2016 17:29:55 -0700 Subject: [PATCH 099/380] Update documentation to reflect that OS X requires boost 1.61.0. Fixes issue #41. (Internal change: 1652833) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 7a31cfecf3..ddf1aa2c69 100644 --- a/README.md +++ b/README.md @@ -44,7 +44,7 @@ Dependencies | C compiler | GCC 4.8, Clang 3.5, MSVC 14.0(VS 2015) | | [CMake](https://cmake.org/documentation/) | 2.8.8 (Linux/OS X), 3.1.1 (Windows) | | [Python](https://python.org) | 2.7.5 | -| [Boost](https://boost.org) | 1.55 (Linux/OS X), 1.61.0 (Windows) | +| [Boost](https://boost.org) | 1.55 (Linux), 1.61.0 (OS X/Windows) | | [OpenEXR](https://openexr.org) | 2.2.0 | | [DoubleConversion](https://github.com/google/double-conversion) | 1.1.1 | | [Intel TBB](https://www.threadingbuildingblocks.org/) | 4.3.1 | From f60cab2a7ef027d074d54634e348a80106481633 Mon Sep 17 00:00:00 2001 From: sunyab Date: Tue, 6 Sep 2016 17:30:10 -0700 Subject: [PATCH 100/380] Fix for Interpreter window not loading in usdview This regression was introduced by commit 30a04e, where we accidentally called View's base class __init__ twice. We might have missed this because of the uncommon way this had previously been done, so we now use the more idiomatic super() to refer to the base class (Internal change: 1652838) --- .../lib/usdviewq/pythonInterpreter.py | 32 +++++++++---------- 1 file changed, 15 insertions(+), 17 deletions(-) diff --git a/pxr/usdImaging/lib/usdviewq/pythonInterpreter.py b/pxr/usdImaging/lib/usdviewq/pythonInterpreter.py index 21f38285b6..21fd32fb5c 100644 --- a/pxr/usdImaging/lib/usdviewq/pythonInterpreter.py +++ b/pxr/usdImaging/lib/usdviewq/pythonInterpreter.py @@ -220,7 +220,7 @@ def __init__(self, textEdit, initialPrompt, locals = None): """ - QtCore.QObject.__init__(self) + super(Controller, self).__init__() self.interpreter = Interpreter(textEdit, locals) self.interpreter.locals['help'] = _Helper(self, self) @@ -637,9 +637,7 @@ class View(QtGui.QTextEdit): """ def __init__(self, parent=None): - QtGui.QTextEdit.__init__(self, parent) - self.Parent = QtGui.QTextEdit - self.Parent.__init__(self, parent) + super(View, self).__init__(parent) self.promptLength = 0 self.__startOfInput = 0 self.setUndoRedoEnabled(False) @@ -709,7 +707,7 @@ def mousePressEvent(self, e): # instead of duplicating the triple click code completely, we just # pass it along. but we modify the selection that comes out of it # to exclude the prompt, if appropriate - self.Parent.mousePressEvent(self, e) + super(View, self).mousePressEvent(e) if (self._CursorIsInInputArea()): selStart = self.textCursor().selectionStart() @@ -722,10 +720,10 @@ def mousePressEvent(self, e): cursor.setPosition(selEnd, QtGui.QTextCursor.KeepAnchor) self.setTextCursor(cursor) else: - self.Parent.mousePressEvent(self, e) + super(View, self).mousePressEvent(e) def mouseDoubleClickEvent(self, e): - self.Parent.mouseDoubleClickEvent(self, e) + super(View, self).mouseDoubleClickEvent(e) app = QtGui.QApplication.instance() self.tripleClickTimer.start(app.doubleClickInterval(), self) # make a copy here, otherwise tripleClickPoint will always = globalPos @@ -735,7 +733,7 @@ def timerEvent(self, e): if (e.timerId() == self.tripleClickTimer.timerId()): self.tripleClickTimer.stop() else: - self.Parent.timerEvent(self, e) + super(View, self).timerEvent(e) def enterEvent(self, e): self._ignoreKeyPresses = False @@ -745,11 +743,11 @@ def leaveEvent(self, e): def dragEnterEvent(self, e): self._ignoreKeyPresses = False - self.Parent.dragEnterEvent(self, e) + super(View, self).dragEnterEvent(e) def dragLeaveEvent(self, e): self._ignoreKeyPresses = True - self.Parent.dragLeaveEvent(self, e) + super(View, self).dragLeaveEvent(e) def keyPressEvent(self, e): """ @@ -774,18 +772,18 @@ def keyPressEvent(self, e): canEraseSelection = selectionInInput and cursorInInput if key == QtCore.Qt.Key_Backspace: if (canBackspace and not hasSelection) or canEraseSelection: - self.Parent.keyPressEvent(self, e) + super(View, self).keyPressEvent(e) elif key == QtCore.Qt.Key_Delete: if (cursorInInput and not hasSelection) or canEraseSelection: - self.Parent.keyPressEvent(self, e) + super(View, self).keyPressEvent(e) elif key == QtCore.Qt.Key_Left: pos = self._PositionInInputArea(self.textCursor().position()) if pos == 0: e.ignore() else: - self.Parent.keyPressEvent(self, e) + super(View, self).keyPressEvent(e) elif key == QtCore.Qt.Key_Right: - self.Parent.keyPressEvent(self, e) + super(View, self).keyPressEvent(e) elif key == QtCore.Qt.Key_Return or key == QtCore.Qt.Key_Enter: # move cursor to end of line. # emit signal to tell controller enter was pressed. @@ -818,7 +816,7 @@ def keyPressEvent(self, e): self._MoveCursorToEndOfInput(False) e.ignore() else: - self.Parent.keyPressEvent(self, e) + super(View, self).keyPressEvent(e) elif key == QtCore.Qt.Key_Tab: self.AutoComplete() e.accept() @@ -833,12 +831,12 @@ def keyPressEvent(self, e): # just deselect and append keypresses cursor = self.textCursor() self._MoveCursorToEndOfInput() - self.Parent.keyPressEvent(self, e) + super(View, self).keyPressEvent(e) elif not cursorInInput: # Ignore keypresses if we're not in the input area. e.ignore() else: - self.Parent.keyPressEvent(self, e) + super(View, self).keyPressEvent(e) def AutoComplete(self): if self._CursorIsInInputArea(): From a40fa766403c5aa573bbc424efe430843ae21e6c Mon Sep 17 00:00:00 2001 From: mrawde Date: Tue, 6 Sep 2016 23:01:00 -0700 Subject: [PATCH 101/380] Adds shaderAdapter which is an interface that provides shading information. The main motivation of this code is to be able to provide a shader network without having to explicitly have hydra look prims. The previous logic that was in the UsdImagingDelegate is now moved into the UsdImagingDefaultShaderAdapater. New shaderAdapters can be registered for particular paths using AddShaderAdapater(). The function call that normally returns the shader binding in primAdapter was made virtual. This allows a primAdapter to override it to provide a new shaderId for which it can register a shader adapter. (Internal change: 1652894) --- pxr/usdImaging/lib/usdImaging/CMakeLists.txt | 2 + .../lib/usdImaging/defaultShaderAdapter.cpp | 386 +++++++++++++++++ .../lib/usdImaging/defaultShaderAdapter.h | 58 +++ pxr/usdImaging/lib/usdImaging/delegate.cpp | 400 ++++-------------- pxr/usdImaging/lib/usdImaging/delegate.h | 24 ++ .../lib/usdImaging/gprimAdapter.cpp | 39 +- pxr/usdImaging/lib/usdImaging/gprimAdapter.h | 14 +- pxr/usdImaging/lib/usdImaging/primAdapter.h | 8 +- pxr/usdImaging/lib/usdImaging/shaderAdapter.h | 71 ++++ 9 files changed, 662 insertions(+), 340 deletions(-) create mode 100644 pxr/usdImaging/lib/usdImaging/defaultShaderAdapter.cpp create mode 100644 pxr/usdImaging/lib/usdImaging/defaultShaderAdapter.h create mode 100644 pxr/usdImaging/lib/usdImaging/shaderAdapter.h diff --git a/pxr/usdImaging/lib/usdImaging/CMakeLists.txt b/pxr/usdImaging/lib/usdImaging/CMakeLists.txt index fa406dfba8..8384809d05 100644 --- a/pxr/usdImaging/lib/usdImaging/CMakeLists.txt +++ b/pxr/usdImaging/lib/usdImaging/CMakeLists.txt @@ -44,6 +44,7 @@ pxr_shared_library(usdImaging PUBLIC_CLASSES adapterRegistry debugCodes + defaultShaderAdapter delegate engine gl @@ -70,6 +71,7 @@ pxr_shared_library(usdImaging PUBLIC_HEADERS version.h + shaderAdapter.h PRIVATE_CLASSES defaultTaskDelegate diff --git a/pxr/usdImaging/lib/usdImaging/defaultShaderAdapter.cpp b/pxr/usdImaging/lib/usdImaging/defaultShaderAdapter.cpp new file mode 100644 index 0000000000..7bf4489e83 --- /dev/null +++ b/pxr/usdImaging/lib/usdImaging/defaultShaderAdapter.cpp @@ -0,0 +1,386 @@ +// +// 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. +// +#include "pxr/usdImaging/usdImaging/defaultShaderAdapter.h" + +#include "pxr/usdImaging/usdImaging/delegate.h" +#include "pxr/usdImaging/usdImaging/tokens.h" + +#include "pxr/imaging/glf/glslfx.h" +#include "pxr/imaging/glf/ptexTexture.h" + +#include "pxr/imaging/hd/tokens.h" + +#include "pxr/usd/usdHydra/shader.h" +#include "pxr/usd/usdHydra/uvTexture.h" +#include "pxr/usd/usdHydra/primvar.h" +#include "pxr/usd/usdHydra/tokens.h" + +UsdImagingDefaultShaderAdapter::UsdImagingDefaultShaderAdapter(UsdImagingDelegate* delegate) + : _delegate(delegate) +{ +} + +bool +UsdImagingDefaultShaderAdapter::GetSurfaceShaderIsTimeVarying(SdfPath const& usdPath) const +{ + if (UsdPrim p = _delegate->_GetPrim(usdPath)) { + const std::vector &attrs = p.GetAttributes(); + TF_FOR_ALL(attrIter, attrs) { + const UsdAttribute& attr = *attrIter; + if (attr.GetNumTimeSamples()>1){ + return true; + } + } + } + return false; +} + +std::string +UsdImagingDefaultShaderAdapter::GetSurfaceShaderSource(SdfPath const &usdPath) const +{ + std::string const EMPTY; + if (not TF_VERIFY(usdPath != SdfPath())) + return EMPTY; + + UsdPrim prim = _delegate->_GetPrim(usdPath); + + if (not prim) { + return EMPTY; + } + + UsdAttribute srcAttr; + if (UsdShadeShader shader = UsdShadeShader(prim)) { + srcAttr = UsdHydraShader(shader).GetFilenameAttr(); + TF_DEBUG(USDIMAGING_SHADERS).Msg("Loading UsdShade shader: %s\n", + srcAttr.GetPath().GetText()); + } else { + // ------------------------------------------------------------------ // + // Deprecated + // ------------------------------------------------------------------ // + srcAttr = prim.GetAttribute(UsdImagingTokens->infoSource); + if (not srcAttr) { + TF_DEBUG(USDIMAGING_SHADERS).Msg("No shader source attribute: %s\n", + prim.GetPath().GetText()); + return EMPTY; + } + TF_DEBUG(USDIMAGING_SHADERS).Msg("Loading deprecated shader: %s\n", + srcAttr.GetPath().GetText()); + // ------------------------------------------------------------------ // + } + + // PERFORMANCE: We're opening the file on every request currently, but we'd + // like to share this in some sort of registry in the future. + SdfAssetPath asset; + std::string filePath; + if (not srcAttr.Get(&asset)) + return EMPTY; + + filePath = asset.GetResolvedPath(); + + // Fallback to the literal path if it couldn't be resolved. + if (filePath.empty()) + filePath = asset.GetAssetPath(); + + GlfGLSLFX gfx(filePath); + + if (not gfx.IsValid()) + return EMPTY; + + return gfx.GetSurfaceSource(); +} + +TfTokenVector +UsdImagingDefaultShaderAdapter::GetSurfaceShaderParamNames(SdfPath const &usdPath) const +{ + TfTokenVector names; + if (not TF_VERIFY(usdPath != SdfPath())) + return names; + + UsdPrim prim = _delegate->_GetPrim(usdPath); + if (not prim) + return names; + + if (UsdShadeShader shader = UsdShadeShader(prim)) { + TF_DEBUG(USDIMAGING_SHADERS).Msg("Parameters found:\n"); + std::vector params = shader.GetParameters(); + names.reserve(params.size()); + for (UsdShadeParameter const& param : params) { + TF_DEBUG(USDIMAGING_SHADERS).Msg("\t - %s\n", + param.GetAttr().GetName().GetText()); + names.push_back(param.GetAttr().GetName()); + } + } else { + // ------------------------------------------------------------------ // + // Deprecated + // ------------------------------------------------------------------ // + + std::vector const& props = prim.GetProperties(); + TF_DEBUG(USDIMAGING_SHADERS).Msg("Parameters found:\n"); + TF_FOR_ALL(propIt, props) { + if (UsdAttribute attr = propIt->As()) { + if (not attr.GetPath().IsNamespacedPropertyPath()) { + TF_DEBUG(USDIMAGING_SHADERS).Msg("\t - %s\n", + attr.GetName().GetText()); + names.push_back(attr.GetName()); + } + } + } + // ------------------------------------------------------------------ // + } + + return names; +} + +VtValue +UsdImagingDefaultShaderAdapter::GetSurfaceShaderParamValue(SdfPath const &usdPath, + TfToken const ¶mName) const +{ + if (not TF_VERIFY(usdPath != SdfPath())) + return VtValue(); + + UsdPrim prim = _delegate->_GetPrim(usdPath); + if (not TF_VERIFY(prim)) { + // XXX: hydra crashes with empty vt values, should fix + VtFloatArray dummy; + dummy.resize(1); + return VtValue(dummy); + } + + VtValue value; + UsdAttribute attr = prim.GetAttribute(paramName); + if (not TF_VERIFY(attr)) { + // XXX: hydra crashes with empty vt values, should fix + VtFloatArray dummy; + dummy.resize(1); + return VtValue(dummy); + } + + // Reading the value may fail, should we warn here when it does? + attr.Get(&value, _delegate->GetTime()); + return value; +} + +HdShaderParamVector +UsdImagingDefaultShaderAdapter::GetSurfaceShaderParams(SdfPath const &usdPath) const +{ + HdShaderParamVector params; + + if (not TF_VERIFY(usdPath != SdfPath())) + return params; + + UsdPrim prim = _delegate->_GetPrim(usdPath); + if (not prim) + return params; + + std::vector const& props = prim.GetProperties(); + TF_FOR_ALL(propIt, props) { + if (UsdAttribute attr = propIt->As()) { + if (attr.GetPath().IsNamespacedPropertyPath()) + continue; + + TF_DEBUG(USDIMAGING_SHADERS).Msg("Parameter found: %s\n", + attr.GetPath().GetText()); + + VtValue fallbackValue; + SdfPath connection; + TfTokenVector samplerCoords; + bool isPtex = false; + + if (not TF_VERIFY(attr.Get(&fallbackValue), + "No fallback value for: <%s>\n", + attr.GetPath().GetText())) { + continue; + } + + if (UsdShadeShader shader = UsdShadeShader(prim)) { + if (auto usdParam = UsdShadeParameter(attr)) { + TF_DEBUG(USDIMAGING_SHADERS).Msg("Parameter: %s\n", + usdParam.GetAttr().GetName().GetText()); + UsdShadeShader source; + TfToken outputName; + if (usdParam.GetConnectedSource(&source, &outputName)) { + if (UsdAttribute attr = source.GetIdAttr()) { + TfToken id; + if (attr.Get(&id)) { + if (id == UsdHydraTokens->HwUvTexture_1) { + connection = _delegate->GetPathForIndex(source.GetPath()); + TF_DEBUG(USDIMAGING_SHADERS).Msg( + "\t connected to UV texture\n"); + UsdHydraUvTexture tex(source); + UsdShadeParameter uv(tex.GetUvAttr()); + UsdShadeShader uvSource; + if (uv.GetConnectedSource(&uvSource, + &outputName)) { + TfToken map; + UsdHydraPrimvar pv(uvSource); + if (pv.GetVarnameAttr().Get(&map)) { + samplerCoords.push_back(map); + TF_DEBUG(USDIMAGING_SHADERS).Msg( + "\t\t sampler: %s\n", + map.GetText()); + } + } + } else if (id == UsdHydraTokens->HwPtexTexture_1) { + isPtex = true; + TF_DEBUG(USDIMAGING_SHADERS).Msg( + "\t connected to Ptex texture\n"); + connection = _delegate->GetPathForIndex(source.GetPath()); + // Ptex doesn't need explicit sampler params + } else if (id == UsdHydraTokens->HwPrimvar_1) { + connection = SdfPath("primvar." + + source.GetPrim() + .GetName() + .GetString()); + TF_DEBUG(USDIMAGING_SHADERS).Msg( + "\t connected to Primvar\n"); + UsdHydraPrimvar pv(source); + TfToken name; + if (TF_VERIFY(pv.GetVarnameAttr().Get(&name))) { + samplerCoords.push_back(name); + TF_DEBUG(USDIMAGING_SHADERS).Msg( + "\t - %s\n", name.GetText()); + } + } + } + } + } + } + } else { + // ---------------------------------------------------------- // + // Deprecated + // ---------------------------------------------------------- // + if (UsdAttribute texAttr = prim.GetAttribute( + TfToken(attr.GetPath().GetName() + + ":texture"))) { + // XXX: we should use the connection for both texture and + // primvars here. + connection = _delegate->GetPathForIndex(texAttr.GetPath()); + TfToken t; + SdfAssetPath ap; + texAttr.Get(&ap, UsdTimeCode::Default()); + TfToken resolvedPath(ap.GetResolvedPath()); + if (resolvedPath.IsEmpty()) { + resolvedPath = TfToken(ap.GetAssetPath()); + } + isPtex = GlfPtexTexture::IsPtexTexture(resolvedPath); + if (not isPtex) { + TF_VERIFY(texAttr.GetMetadata( + UsdImagingTokens->uvPrimvar, &t), + "<%s>", texAttr.GetPath().GetText()); + samplerCoords.push_back(t); + } + } else if (UsdAttribute pvAttr = prim.GetAttribute( + TfToken(attr.GetPath().GetName() + + ":primvar"))) { + connection = SdfPath("primvar." + + pvAttr.GetName().GetString()); + TfToken t; + pvAttr.Get(&t, UsdTimeCode::Default()); + TF_DEBUG(USDIMAGING_SHADERS).Msg( + "Primvar connection found: %s = %s\n", + pvAttr.GetPath().GetText(), + t.GetText()); + samplerCoords.push_back(t); + } + // ---------------------------------------------------------- // + } + + attr.Get(&fallbackValue); + params.push_back(HdShaderParam(attr.GetName(), + fallbackValue, + connection, + samplerCoords, + isPtex)); + } + } + + return params; +} + +SdfPathVector +UsdImagingDefaultShaderAdapter::GetSurfaceShaderTextures(SdfPath const &usdPath) const +{ + SdfPathVector textureIDs; + + if (not TF_VERIFY(usdPath != SdfPath())) { + return textureIDs; + } + + UsdPrim prim = _delegate->_GetPrim(usdPath); + if (not prim) { + return textureIDs; + } + + if (UsdShadeShader shader = UsdShadeShader(prim)) { + SdfPathVector stack(1, shader.GetPath()); + TfToken t; + while (not stack.empty()) { + SdfPath shaderPath = stack.back(); + stack.pop_back(); + shader = UsdShadeShader(prim.GetStage()->GetPrimAtPath(shaderPath)); + TF_DEBUG(USDIMAGING_TEXTURES).Msg( + " Looking for connected textures at <%s>\n", + shader.GetPath().GetText()); + + if (shader.GetIdAttr().Get(&t) + and (t == UsdHydraTokens->HwUvTexture_1 + or t == UsdHydraTokens->HwPtexTexture_1)) { + TF_DEBUG(USDIMAGING_TEXTURES).Msg( + " found texture: <%s>\n", + shader.GetPath().GetText()); + textureIDs.push_back(_delegate->GetPathForIndex(shader.GetPath())); + } + for (UsdShadeParameter param : shader.GetParameters()) { + UsdShadeShader source; + TfToken outputName; + if (param.GetConnectedSource(&source, &outputName)) { + stack.push_back(source.GetPath()); + } + } + } + } else { + std::vector const& props = prim.GetProperties(); + TF_FOR_ALL(propIt, props) { + if (UsdAttribute attr = propIt->As()) { + if (attr.GetPath().IsNamespacedPropertyPath()) + continue; + + SdfPath connection; + if (UsdAttribute texAttr = prim.GetAttribute( + TfToken(attr.GetPath().GetName() + + ":texture"))) { + connection = texAttr.GetPath(); + textureIDs.push_back(_delegate->GetPathForIndex(connection)); + + TF_DEBUG(USDIMAGING_TEXTURES).Msg( + "Texture connection found: %s\n", + texAttr.GetPath().GetText()); + } + } + } + } + + return textureIDs; +} + diff --git a/pxr/usdImaging/lib/usdImaging/defaultShaderAdapter.h b/pxr/usdImaging/lib/usdImaging/defaultShaderAdapter.h new file mode 100644 index 0000000000..ed77329916 --- /dev/null +++ b/pxr/usdImaging/lib/usdImaging/defaultShaderAdapter.h @@ -0,0 +1,58 @@ +// +// 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 USDIMAGING_DEFAULTSHADERADAPTER_H +#define USDIMAGING_DEFAULTSHADERADAPTER_H + +#include "pxr/usdImaging/usdImaging/shaderAdapter.h" +#include "pxr/usdImaging/usdImaging/delegate.h" + +/// \class UsdImagingDefaultShaderAdapter +/// \brief An implementation of the shader adapter that uses Usd objects to +/// build up a shading network. +/// +/// Currently, in the absence of any other shaderAdapter registered the delegate +/// will default to using this implementation. +class UsdImagingDefaultShaderAdapter : public UsdImagingShaderAdapter +{ +public: + UsdImagingDefaultShaderAdapter(UsdImagingDelegate* delegate); + + /// \brief Traverses the shading prims and if any of the attributes are time + /// varying, returns true. + bool GetSurfaceShaderIsTimeVarying(SdfPath const& usdPath) const override; + + /// \brief Gets the shading source via the \c UsdHydrShader schema. + std::string GetSurfaceShaderSource(SdfPath const& usdPath) const override; + + TfTokenVector GetSurfaceShaderParamNames(SdfPath const& usdPath) const override; + + VtValue GetSurfaceShaderParamValue(SdfPath const& usdPath, TfToken const& paramName) const override; + HdShaderParamVector GetSurfaceShaderParams(SdfPath const& usdPath) const override; + SdfPathVector GetSurfaceShaderTextures(SdfPath const& usdPath) const override; + +private: + UsdImagingDelegate* _delegate; +}; + +#endif // USDIMAGING_DEFAULTSHADERADAPTER_H diff --git a/pxr/usdImaging/lib/usdImaging/delegate.cpp b/pxr/usdImaging/lib/usdImaging/delegate.cpp index ec9872ca30..0424b1c9a8 100644 --- a/pxr/usdImaging/lib/usdImaging/delegate.cpp +++ b/pxr/usdImaging/lib/usdImaging/delegate.cpp @@ -27,12 +27,11 @@ #include "pxr/usdImaging/usdImaging/adapterRegistry.h" #include "pxr/usdImaging/usdImaging/debugCodes.h" +#include "pxr/usdImaging/usdImaging/defaultShaderAdapter.h" #include "pxr/usdImaging/usdImaging/instanceAdapter.h" #include "pxr/usdImaging/usdImaging/primAdapter.h" #include "pxr/usdImaging/usdImaging/tokens.h" -#include "pxr/imaging/glf/glslfx.h" -#include "pxr/imaging/glf/diagnostic.h" #include "pxr/imaging/glf/ptexTexture.h" #include "pxr/imaging/glf/textureRegistry.h" @@ -52,15 +51,8 @@ #include "pxr/usd/usdGeom/tokens.h" -// TODO: Move these to ShaderAdapter -// At the same time, reduce shader traversals to a single pass; currently -// usdImaging will traverse a single shader network multiple times during sync. #include "pxr/usd/usdHydra/shader.h" #include "pxr/usd/usdHydra/uvTexture.h" -#include "pxr/usd/usdHydra/ptexTexture.h" -#include "pxr/usd/usdHydra/primvar.h" -#include "pxr/usd/usdHydra/tokens.h" -// -- #include "pxr/base/work/loops.h" @@ -72,6 +64,10 @@ #include #include +// TODO: +// reduce shader traversals to a single pass; currently usdImaging will traverse +// a single shader network multiple times during sync. + // XXX: Perhaps all interpolation tokens for Hydra should come from Hd and // UsdGeom tokens should be passed through a mapping function. TF_DEFINE_PRIVATE_TOKENS( @@ -97,6 +93,7 @@ UsdImagingDelegate::UsdImagingDelegate() , _xformCache(GetTime(), GetRootCompensation()) , _materialBindingCache(GetTime(), GetRootCompensation()) , _visCache(GetTime(), GetRootCompensation()) + , _defaultShaderAdapter(boost::make_shared(this)) { // this constructor create a new render index. HdChangeTracker &tracker = GetRenderIndex().GetChangeTracker(); @@ -130,6 +127,7 @@ UsdImagingDelegate::UsdImagingDelegate( , _xformCache(GetTime(), GetRootCompensation()) , _materialBindingCache(GetTime(), GetRootCompensation()) , _visCache(GetTime(), GetRootCompensation()) + , _defaultShaderAdapter(boost::make_shared(this)) { HdChangeTracker &tracker = GetRenderIndex().GetChangeTracker(); tracker.AddCollection(UsdImagingCollectionTokens->geometryAndGuides); @@ -256,6 +254,19 @@ UsdImagingDelegate::_AdapterLookupByPath(SdfPath const& usdPath) : NULL_ADAPTER; } + +UsdImagingDelegate::_ShaderAdapterSharedPtr +UsdImagingDelegate::_ShaderAdapterLookup( + SdfPath const& shaderId) const +{ + auto it = _shaderAdapterMap.find(shaderId); + if (it != _shaderAdapterMap.end()) { + return it->second; + } + + return _defaultShaderAdapter; +} + // -------------------------------------------------------------------------- // // Parallel Dispatch // -------------------------------------------------------------------------- // @@ -437,10 +448,14 @@ void UsdImagingIndexProxy::AddDependency(SdfPath const& usdPath, UsdImagingPrimAdapterSharedPtr const& adapter) { - UsdPrim const& prim = _delegate->_GetPrim(usdPath); - UsdImagingPrimAdapterSharedPtr adapterToInsert = - adapter ? adapter : _delegate->_AdapterLookup(prim); - if (not adapter) { + UsdImagingPrimAdapterSharedPtr adapterToInsert; + if (adapter) { + adapterToInsert = adapter; + } + else { + UsdPrim const& prim = _delegate->_GetPrim(usdPath); + adapterToInsert = _delegate->_AdapterLookup(prim); + // When no adapter was provided, look it up based on the type of the // prim. if (not adapterToInsert) { @@ -476,6 +491,17 @@ UsdImagingIndexProxy::AddDependency(SdfPath const& usdPath, _delegate->_pathAdapterMap[usdPath] = adapterToInsert; } +void +UsdImagingIndexProxy::AddShaderAdapter( + SdfPath const& shaderId, + UsdImagingShaderAdapterSharedPtr const& shaderAdapter) +{ + TF_DEBUG(USDIMAGING_SHADERS).Msg( + "Registering shader adapter for %s\n", shaderId.GetText()); + + _delegate->_shaderAdapterMap[shaderId] = shaderAdapter; +} + void UsdImagingIndexProxy::_AddTask(SdfPath const& usdPath) { @@ -544,16 +570,7 @@ UsdImagingIndexProxy::_InsertRprim(SdfPath const& usdPath, // Detect if the shader has any attribute that is time varying // if so we will tag the shader as time varying so we can // invalidate it accordingly - bool isTimeVarying = false; - UsdPrim p = _delegate->_GetPrim(shader); - const std::vector &attrs = p.GetAttributes(); - TF_FOR_ALL(attrIter, attrs) { - const UsdAttribute& attr = *attrIter; - if (attr.GetNumTimeSamples()>1){ - isTimeVarying = true; - break; - } - } + bool isTimeVarying = _delegate->GetSurfaceShaderIsTimeVarying(shader); _delegate->_shaderMap[shader] = isTimeVarying; SdfPathVector textures = @@ -2616,284 +2633,76 @@ UsdImagingDelegate::GetInstancerTransform(SdfPath const &instancerId, return ctm; } +bool +UsdImagingDelegate::GetSurfaceShaderIsTimeVarying(SdfPath const& shaderId) +{ + if (_ShaderAdapterSharedPtr adapter = _ShaderAdapterLookup(shaderId)) { + return adapter->GetSurfaceShaderIsTimeVarying(GetPathForUsd(shaderId)); + } + + TF_CODING_ERROR("Unable to find a shader adapter."); + return false; +} + /*virtual*/ std::string -UsdImagingDelegate::GetSurfaceShaderSource(SdfPath const &id) +UsdImagingDelegate::GetSurfaceShaderSource(SdfPath const &shaderId) { // PERFORMANCE: We should schedule this to be updated during Sync, rather // than pulling values on demand. - - std::string const EMPTY; - if (not TF_VERIFY(id != SdfPath())) - return EMPTY; - - SdfPath usdPath = GetPathForUsd(id); - UsdPrim prim = _GetPrim(usdPath); - if (not prim) { - return EMPTY; + if (_ShaderAdapterSharedPtr adapter = _ShaderAdapterLookup(shaderId)) { + return adapter->GetSurfaceShaderSource(GetPathForUsd(shaderId)); } - UsdAttribute srcAttr; - if (UsdShadeShader shader = UsdShadeShader(prim)) { - srcAttr = UsdHydraShader(shader).GetFilenameAttr(); - TF_DEBUG(USDIMAGING_SHADERS).Msg("Loading UsdShade shader: %s\n", - srcAttr.GetPath().GetText()); - } else { - // ------------------------------------------------------------------ // - // Deprecated - // ------------------------------------------------------------------ // - srcAttr = prim.GetAttribute(UsdImagingTokens->infoSource); - if (not srcAttr) { - TF_DEBUG(USDIMAGING_SHADERS).Msg("No shader source attribute: %s\n", - prim.GetPath().GetText()); - return EMPTY; - } - TF_DEBUG(USDIMAGING_SHADERS).Msg("Loading deprecated shader: %s\n", - srcAttr.GetPath().GetText()); - // ------------------------------------------------------------------ // - } - - // PERFORMANCE: We're opening the file on every request currently, but we'd - // like to share this in some sort of registry in the future. - SdfAssetPath asset; - std::string filePath; - if (not srcAttr.Get(&asset)) - return EMPTY; - - filePath = asset.GetResolvedPath(); - - // Fallback to the literal path if it couldn't be resolved. - if (filePath.empty()) - filePath = asset.GetAssetPath(); - - GlfGLSLFX gfx(filePath); - - if (not gfx.IsValid()) - return EMPTY; - - return gfx.GetSurfaceSource(); + TF_CODING_ERROR("Unable to find a shader adapter."); + return ""; } /*virtual*/ TfTokenVector -UsdImagingDelegate::GetSurfaceShaderParamNames(SdfPath const &id) +UsdImagingDelegate::GetSurfaceShaderParamNames(SdfPath const &shaderId) { // PERFORMANCE: We should schedule this to be updated during Sync, rather // than pulling values on demand. - - TfTokenVector names; - if (not TF_VERIFY(id != SdfPath())) - return names; - SdfPath usdPath = GetPathForUsd(id); - UsdPrim prim = _GetPrim(usdPath); - if (not prim) - return names; - - if (UsdShadeShader shader = UsdShadeShader(prim)) { - TF_DEBUG(USDIMAGING_SHADERS).Msg("Parameters found:\n"); - std::vector params = shader.GetParameters(); - names.reserve(params.size()); - for (UsdShadeParameter const& param : params) { - TF_DEBUG(USDIMAGING_SHADERS).Msg("\t - %s\n", - param.GetAttr().GetName().GetText()); - names.push_back(param.GetAttr().GetName()); - } - } else { - // ------------------------------------------------------------------ // - // Deprecated - // ------------------------------------------------------------------ // - - std::vector const& props = prim.GetProperties(); - TF_DEBUG(USDIMAGING_SHADERS).Msg("Parameters found:\n"); - TF_FOR_ALL(propIt, props) { - if (UsdAttribute attr = propIt->As()) { - if (not attr.GetPath().IsNamespacedPropertyPath()) { - TF_DEBUG(USDIMAGING_SHADERS).Msg("\t - %s\n", - attr.GetName().GetText()); - names.push_back(attr.GetName()); - } - } - } - // ------------------------------------------------------------------ // + if (_ShaderAdapterSharedPtr adapter = _ShaderAdapterLookup(shaderId)) { + return adapter->GetSurfaceShaderParamNames(GetPathForUsd(shaderId)); } + TF_CODING_ERROR("Unable to find a shader adapter."); + TfTokenVector names; return names; } /*virtual*/ VtValue -UsdImagingDelegate::GetSurfaceShaderParamValue(SdfPath const &id, +UsdImagingDelegate::GetSurfaceShaderParamValue(SdfPath const &shaderId, TfToken const ¶mName) { // PERFORMANCE: We should schedule this to be updated during Sync, rather // than pulling values on demand. - - if (not TF_VERIFY(id != SdfPath())) - return VtValue(); - - SdfPath usdPath = GetPathForUsd(id); - UsdPrim prim = _GetPrim(usdPath); - if (not TF_VERIFY(prim)) { - // XXX: hydra crashes with empty vt values, should fix - VtFloatArray dummy; - dummy.resize(1); - return VtValue(dummy); - } - VtValue value; - UsdAttribute attr = prim.GetAttribute(paramName); - if (not TF_VERIFY(attr)) { - // XXX: hydra crashes with empty vt values, should fix - VtFloatArray dummy; - dummy.resize(1); - return VtValue(dummy); + if (_ShaderAdapterSharedPtr adapter = _ShaderAdapterLookup(shaderId)) { + return adapter->GetSurfaceShaderParamValue(GetPathForUsd(shaderId), paramName); } - // Reading the value may fail, should we warn here when it does? - attr.Get(&value, _time); - return value; + TF_CODING_ERROR("Unable to find a shader adapter."); + return VtValue(); } HdShaderParamVector -UsdImagingDelegate::GetSurfaceShaderParams(SdfPath const &id) +UsdImagingDelegate::GetSurfaceShaderParams(SdfPath const &shaderId) { - HdShaderParamVector params; + if (_ShaderAdapterSharedPtr adapter = _ShaderAdapterLookup(shaderId)) { + return adapter->GetSurfaceShaderParams(GetPathForUsd(shaderId)); + } // PERFORMANCE: We should schedule this to be updated during Sync, rather // than pulling values on demand. - - if (not TF_VERIFY(id != SdfPath())) - return params; - - SdfPath usdPath = GetPathForUsd(id); - UsdPrim prim = _GetPrim(usdPath); - if (not prim) - return params; - - std::vector const& props = prim.GetProperties(); - TF_FOR_ALL(propIt, props) { - if (UsdAttribute attr = propIt->As()) { - if (attr.GetPath().IsNamespacedPropertyPath()) - continue; - - TF_DEBUG(USDIMAGING_SHADERS).Msg("Parameter found: %s\n", - attr.GetPath().GetText()); - - VtValue fallbackValue; - SdfPath connection; - TfTokenVector samplerCoords; - bool isPtex = false; - - if (not TF_VERIFY(attr.Get(&fallbackValue), - "No fallback value for: <%s>\n", - attr.GetPath().GetText())) { - continue; - } - - if (UsdShadeShader shader = UsdShadeShader(prim)) { - if (auto usdParam = UsdShadeParameter(attr)) { - TF_DEBUG(USDIMAGING_SHADERS).Msg("Parameter: %s\n", - usdParam.GetAttr().GetName().GetText()); - UsdShadeShader source; - TfToken outputName; - if (usdParam.GetConnectedSource(&source, &outputName)) { - if (UsdAttribute attr = source.GetIdAttr()) { - TfToken id; - if (attr.Get(&id)) { - if (id == UsdHydraTokens->HwUvTexture_1) { - connection = GetPathForIndex(source.GetPath()); - TF_DEBUG(USDIMAGING_SHADERS).Msg( - "\t connected to UV texture\n"); - UsdHydraUvTexture tex(source); - UsdShadeParameter uv(tex.GetUvAttr()); - UsdShadeShader uvSource; - if (uv.GetConnectedSource(&uvSource, - &outputName)) { - TfToken map; - UsdHydraPrimvar pv(uvSource); - if (pv.GetVarnameAttr().Get(&map)) { - samplerCoords.push_back(map); - TF_DEBUG(USDIMAGING_SHADERS).Msg( - "\t\t sampler: %s\n", - map.GetText()); - } - } - } else if (id == UsdHydraTokens->HwPtexTexture_1) { - isPtex = true; - TF_DEBUG(USDIMAGING_SHADERS).Msg( - "\t connected to Ptex texture\n"); - connection = GetPathForIndex(source.GetPath()); - // Ptex doesn't need explicit sampler params - } else if (id == UsdHydraTokens->HwPrimvar_1) { - connection = SdfPath("primvar." - + source.GetPrim() - .GetName() - .GetString()); - TF_DEBUG(USDIMAGING_SHADERS).Msg( - "\t connected to Primvar\n"); - UsdHydraPrimvar pv(source); - TfToken name; - if (TF_VERIFY(pv.GetVarnameAttr().Get(&name))) { - samplerCoords.push_back(name); - TF_DEBUG(USDIMAGING_SHADERS).Msg( - "\t - %s\n", name.GetText()); - } - } - } - } - } - } - } else { - // ---------------------------------------------------------- // - // Deprecated - // ---------------------------------------------------------- // - if (UsdAttribute texAttr = prim.GetAttribute( - TfToken(attr.GetPath().GetName() - + ":texture"))) { - // XXX: we should use the connection for both texture and - // primvars here. - connection = GetPathForIndex(texAttr.GetPath()); - TfToken t; - SdfAssetPath ap; - texAttr.Get(&ap, UsdTimeCode::Default()); - TfToken resolvedPath(ap.GetResolvedPath()); - if (resolvedPath.IsEmpty()) { - resolvedPath = TfToken(ap.GetAssetPath()); - } - isPtex = GlfPtexTexture::IsPtexTexture(resolvedPath); - if (not isPtex) { - TF_VERIFY(texAttr.GetMetadata( - UsdImagingTokens->uvPrimvar, &t), - "<%s>", texAttr.GetPath().GetText()); - samplerCoords.push_back(t); - } - } else if (UsdAttribute pvAttr = prim.GetAttribute( - TfToken(attr.GetPath().GetName() - + ":primvar"))) { - connection = SdfPath("primvar." - + pvAttr.GetName().GetString()); - TfToken t; - pvAttr.Get(&t, UsdTimeCode::Default()); - TF_DEBUG(USDIMAGING_SHADERS).Msg( - "Primvar connection found: %s = %s\n", - pvAttr.GetPath().GetText(), - t.GetText()); - samplerCoords.push_back(t); - } - // ---------------------------------------------------------- // - } - - attr.Get(&fallbackValue); - params.push_back(HdShaderParam(attr.GetName(), - fallbackValue, - connection, - samplerCoords, - isPtex)); - } - } + TF_CODING_ERROR("Unable to find a shader adapter."); + HdShaderParamVector params; return params; } @@ -2901,70 +2710,15 @@ UsdImagingDelegate::GetSurfaceShaderParams(SdfPath const &id) SdfPathVector UsdImagingDelegate::GetSurfaceShaderTextures(SdfPath const &shaderId) { - SdfPathVector textureIDs; + if (_ShaderAdapterSharedPtr adapter = _ShaderAdapterLookup(shaderId)) { + return adapter->GetSurfaceShaderTextures(GetPathForUsd(shaderId)); + } // PERFORMANCE: We should schedule this to be updated during Sync, rather // than pulling values on demand. - - if (not TF_VERIFY(shaderId != SdfPath())) { - return textureIDs; - } - - SdfPath usdPath = GetPathForUsd(shaderId); - UsdPrim prim = _GetPrim(usdPath); - if (not prim) { - return textureIDs; - } - - if (UsdShadeShader shader = UsdShadeShader(prim)) { - SdfPathVector stack(1, shader.GetPath()); - TfToken t; - while (not stack.empty()) { - SdfPath shaderPath = stack.back(); - stack.pop_back(); - shader = UsdShadeShader(prim.GetStage()->GetPrimAtPath(shaderPath)); - TF_DEBUG(USDIMAGING_TEXTURES).Msg( - " Looking for connected textures at <%s>\n", - shader.GetPath().GetText()); - - if (shader.GetIdAttr().Get(&t) - and (t == UsdHydraTokens->HwUvTexture_1 - or t == UsdHydraTokens->HwPtexTexture_1)) { - TF_DEBUG(USDIMAGING_TEXTURES).Msg( - " found texture: <%s>\n", - shader.GetPath().GetText()); - textureIDs.push_back(GetPathForIndex(shader.GetPath())); - } - for (UsdShadeParameter param : shader.GetParameters()) { - UsdShadeShader source; - TfToken outputName; - if (param.GetConnectedSource(&source, &outputName)) { - stack.push_back(source.GetPath()); - } - } - } - } else { - std::vector const& props = prim.GetProperties(); - TF_FOR_ALL(propIt, props) { - if (UsdAttribute attr = propIt->As()) { - if (attr.GetPath().IsNamespacedPropertyPath()) - continue; - - SdfPath connection; - if (UsdAttribute texAttr = prim.GetAttribute( - TfToken(attr.GetPath().GetName() - + ":texture"))) { - connection = texAttr.GetPath(); - textureIDs.push_back(GetPathForIndex(connection)); - TF_DEBUG(USDIMAGING_TEXTURES).Msg( - "Texture connection found: %s\n", - texAttr.GetPath().GetText()); - } - } - } - } - + TF_CODING_ERROR("Unable to find a shader adapter."); + SdfPathVector textureIDs; return textureIDs; } diff --git a/pxr/usdImaging/lib/usdImaging/delegate.h b/pxr/usdImaging/lib/usdImaging/delegate.h index 7a3af27d5f..b8819710d3 100644 --- a/pxr/usdImaging/lib/usdImaging/delegate.h +++ b/pxr/usdImaging/lib/usdImaging/delegate.h @@ -27,6 +27,7 @@ #include "pxr/usdImaging/usdImaging/valueCache.h" #include "pxr/usdImaging/usdImaging/inheritedCache.h" #include "pxr/usdImaging/usdImaging/instancerContext.h" +#include "pxr/usdImaging/usdImaging/shaderAdapter.h" #include "pxr/imaging/hd/sceneDelegate.h" #include "pxr/imaging/hd/surfaceShader.h" @@ -63,9 +64,12 @@ typedef std::vector UsdPrimVector; class UsdImagingPrimAdapter; class UsdImagingIndexProxy; class UsdImagingInstancerContext; +class UsdImagingDefaultShaderAdapter; typedef boost::shared_ptr UsdImagingPrimAdapterSharedPtr; +typedef boost::shared_ptr UsdImagingShaderAdapterSharedPtr ; + /// \class UsdImagingDelegate /// /// The primary translation layer between the Hydra (Hd) core and the Usd @@ -283,6 +287,7 @@ class UsdImagingDelegate : public HdSceneDelegate, public TfWeakBase { SdfPath const &prototypeId); // Shader Support + virtual bool GetSurfaceShaderIsTimeVarying(SdfPath const& id); virtual std::string GetSurfaceShaderSource(SdfPath const &id); virtual TfTokenVector GetSurfaceShaderParamNames(SdfPath const &id); virtual VtValue GetSurfaceShaderParamValue(SdfPath const &id, @@ -388,6 +393,9 @@ class UsdImagingDelegate : public HdSceneDelegate, public TfWeakBase { friend class UsdImagingIndexProxy; friend class UsdImagingPrimAdapter; + // UsdImagingDefaultShaderAdapter needs access to _GetPrim. We should + // consider making it public. + friend class UsdImagingDefaultShaderAdapter; bool _ValidateRefineLevel(int level) { if (not (0 <= level and level <= 8)) { @@ -509,6 +517,15 @@ class UsdImagingDelegate : public HdSceneDelegate, public TfWeakBase { typedef SdfPathTable<_AdapterSharedPtr> _PathAdapterMap; _PathAdapterMap _pathAdapterMap; + typedef UsdImagingShaderAdapterSharedPtr _ShaderAdapterSharedPtr; + typedef SdfPathTable<_ShaderAdapterSharedPtr> _ShaderAdapterMap; + _ShaderAdapterMap _shaderAdapterMap; + + // This method looks up a shader adapter based on the \p shaderId. + // This will never return a nullptr. If there is no registered shader + // adapter, it will return the "default". + _ShaderAdapterSharedPtr _ShaderAdapterLookup(SdfPath const& shaderId) const; + // XXX: These maps could be store as individual member paths on the Rprim // itself, which seems like a much nicer way of maintaining the mapping. tbb::spin_rw_mutex _indexToUsdPathMapMutex; @@ -583,6 +600,9 @@ class UsdImagingDelegate : public HdSceneDelegate, public TfWeakBase { // Collection CollectionMap _collectionMap; + + // default shader adapter + boost::shared_ptr _defaultShaderAdapter; }; /// \class UsdImagingIndexProxy @@ -600,6 +620,10 @@ class UsdImagingIndexProxy { UsdImagingPrimAdapterSharedPtr const& adapter = UsdImagingPrimAdapterSharedPtr()); + /// \brief Register a \p shaderAdapter to handle the shader at \p shaderId. + void AddShaderAdapter(SdfPath const& shaderId, + UsdImagingShaderAdapterSharedPtr const& shaderAdapter); + SdfPath InsertMesh(SdfPath const& usdPath, SdfPath const& shaderBinding, UsdImagingInstancerContext const* instancerContext); diff --git a/pxr/usdImaging/lib/usdImaging/gprimAdapter.cpp b/pxr/usdImaging/lib/usdImaging/gprimAdapter.cpp index 8e7450b975..ea7567c7e6 100644 --- a/pxr/usdImaging/lib/usdImaging/gprimAdapter.cpp +++ b/pxr/usdImaging/lib/usdImaging/gprimAdapter.cpp @@ -182,7 +182,29 @@ UsdImagingGprimAdapter::UpdateForTimePrep(UsdPrim const& prim, } void -UsdImagingGprimAdapter::_DiscoverPrimvars(UsdGeomGprim const& gprim, +UsdImagingGprimAdapter::_DiscoverPrimvars( + UsdGeomGprim const& gprim, + SdfPath const& cachePath, + SdfPath const& shaderPath, + UsdTimeCode time, + UsdImagingValueCache* valueCache) +{ + // Check if each parameter is bound to a texture or primvar, if so, + // collect that primvar from this gprim. + // XXX: Should move this into ShaderAdapter + if (UsdPrim const& shaderPrim = + gprim.GetPrim().GetStage()->GetPrimAtPath(shaderPath)) { + if (UsdShadeShader s = UsdShadeShader(shaderPrim)) { + _DiscoverPrimvarsFromShaderNetwork(gprim, cachePath, s, time, valueCache); + } else { + _DiscoverPrimvarsDeprecated(gprim, cachePath, + shaderPrim, time, valueCache); + } + } +} + +void +UsdImagingGprimAdapter::_DiscoverPrimvarsFromShaderNetwork(UsdGeomGprim const& gprim, SdfPath const& cachePath, UsdShadeShader const& shader, UsdTimeCode time, @@ -233,7 +255,7 @@ UsdImagingGprimAdapter::_DiscoverPrimvars(UsdGeomGprim const& gprim, } } else { // Recursively look for more primvars - _DiscoverPrimvars(gprim, cachePath, source, time, valueCache); + _DiscoverPrimvarsFromShaderNetwork(gprim, cachePath, source, time, valueCache); } } } @@ -358,18 +380,7 @@ UsdImagingGprimAdapter::UpdateForTime(UsdPrim const& prim, prim.GetPath().GetText(), usdShaderPath.GetText()); if (not usdShaderPath.IsEmpty()) { - // Check if each parameter is bound to a texture or primvar, if so, - // collect that primvar from this gprim. - // XXX: Should move this into ShaderAdapter - UsdPrim const& shaderPrim = - prim.GetStage()->GetPrimAtPath(usdShaderPath); - - if (UsdShadeShader s = UsdShadeShader(shaderPrim)) { - _DiscoverPrimvars(gprim, cachePath, s, time, valueCache); - } else { - _DiscoverPrimvarsDeprecated(gprim, cachePath, - shaderPrim, time, valueCache); - } + _DiscoverPrimvars(gprim, cachePath, usdShaderPath, time, valueCache); } } diff --git a/pxr/usdImaging/lib/usdImaging/gprimAdapter.h b/pxr/usdImaging/lib/usdImaging/gprimAdapter.h index 328566dc0e..854e8e16d3 100644 --- a/pxr/usdImaging/lib/usdImaging/gprimAdapter.h +++ b/pxr/usdImaging/lib/usdImaging/gprimAdapter.h @@ -96,10 +96,22 @@ class UsdImagingGprimAdapter : public UsdImagingPrimAdapter { UsdImagingValueCache::PrimvarInfo* primvarInfo, UsdTimeCode time); +protected: + + /// This function can be overridden if the gprim adapter wants to have + /// control over the primvar discovery. + virtual void _DiscoverPrimvars( + UsdGeomGprim const& gprim, + SdfPath const& cachePath, + SdfPath const& shaderPath, + UsdTimeCode time, + UsdImagingValueCache* valueCache); + private: + /// Discover required primvars by searching for primvar inputs connected to /// the shader network. - void _DiscoverPrimvars(UsdGeomGprim const& gprim, + void _DiscoverPrimvarsFromShaderNetwork(UsdGeomGprim const& gprim, SdfPath const& cachePath, UsdShadeShader const& shader, UsdTimeCode time, diff --git a/pxr/usdImaging/lib/usdImaging/primAdapter.h b/pxr/usdImaging/lib/usdImaging/primAdapter.h index e387acce1c..381b158dde 100644 --- a/pxr/usdImaging/lib/usdImaging/primAdapter.h +++ b/pxr/usdImaging/lib/usdImaging/primAdapter.h @@ -188,8 +188,12 @@ class UsdImagingPrimAdapter bool ignoreRootTransform = false); /// Gets the shader binding for the given prim, walking up namespace if - /// necessary. - SdfPath GetShaderBinding(UsdPrim const& prim); + /// necessary. + /// + /// This returns a usdPath to a shaderPrim. If you want to override the + /// default shaderAdapter, use UsdImagingIndexProxy::AddShaderAdapter to + /// register a new adapter for the path returned here. + virtual SdfPath GetShaderBinding(UsdPrim const& prim); /// Gets the instancer ID for the given prim and instancerContext. SdfPath GetInstancerBinding(UsdPrim const& prim, diff --git a/pxr/usdImaging/lib/usdImaging/shaderAdapter.h b/pxr/usdImaging/lib/usdImaging/shaderAdapter.h new file mode 100644 index 0000000000..669b5b5a1f --- /dev/null +++ b/pxr/usdImaging/lib/usdImaging/shaderAdapter.h @@ -0,0 +1,71 @@ +// +// 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 USDIMAGING_SHADERADAPTER_H +#define USDIMAGING_SHADERADAPTER_H + +#include "pxr/imaging/hd/shaderParam.h" + +/// \class UsdImagingShaderAdapter +/// \brief Interface that provides information that can be used to generate a +/// surface shader in hydra. +/// +/// Shaders are identified by a \p shaderPath which is a usd stage path.. All +/// the pure virtual methods in this interface will likely need to be +/// coordinated. For example, \c GetSurfaceShaderParams declares all the +/// parameters that the shader uses. Hydra will later query the \c +/// UsdImagingShaderAdapter for the values (\c +/// UsdImagingShaderAdapater::GetSurfaceShaderParamValue). +/// +/// \sa UsdImagingIndexProxy::AddShaderAdapter +/// \sa UsdImagingDefaultShaderAdapter +class UsdImagingShaderAdapter +{ +public: + /// \brief Return true if \p usdPath is time varying. + virtual bool GetSurfaceShaderIsTimeVarying(SdfPath const& usdPath) const = 0; + + /// \brief Returns the glsl source string for the shader at \p usdPath. + virtual std::string GetSurfaceShaderSource(SdfPath const& usdPath) const = 0; + + /// \brief Returns the parameter names for \p usdPath. + /// \deprecated This is now replaced by UsdImagingShaderAdapter::GetSurfaceShaderParams + virtual TfTokenVector GetSurfaceShaderParamNames(SdfPath const& usdPath) const = 0; + + /// \brief Returns the value of param \p paramName for \p usdPath. + virtual VtValue GetSurfaceShaderParamValue(SdfPath const& usdPath, TfToken const& paramName) const = 0; + + /// \brief Returns the parameters that \p usdPath users. Hydra will built + /// the appropriate internal data structures so that these values are + /// available in the shader. + /// + /// \sa HdShaderParam + virtual HdShaderParamVector GetSurfaceShaderParams(SdfPath const& usdPath) const = 0; + + /// \brief Returns the textures (identified by \c SdfPath objects) that \p + /// usdPath users. + virtual SdfPathVector GetSurfaceShaderTextures(SdfPath const& usdPath) const = 0; + +}; + +#endif // USDIMAGING_SHADERADAPTER_H From 1037c0d78b4ddff7050f060762be6d258fab92d3 Mon Sep 17 00:00:00 2001 From: sunyab Date: Tue, 6 Sep 2016 23:03:29 -0700 Subject: [PATCH 102/380] Update Travis config to use sudo when installing The USD build will install to /usr/local by default, which requires sudo to write to. (Internal change: 1652900) --- .travis.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index f4f461c795..cd3a4cb2fb 100644 --- a/.travis.yml +++ b/.travis.yml @@ -154,4 +154,5 @@ script: # This is fixed in commit 880b04. - make -j4 cameraUtil - make -j4 - - make install + # Default install location is /usr/local; we need sudo access to write there. + - sudo make install From 973e023a871f5b0f33addd3f3d0b90ea9648b1ee Mon Sep 17 00:00:00 2001 From: takahito-tejima Date: Thu, 8 Sep 2016 11:21:32 -0700 Subject: [PATCH 103/380] [Hd, Hdx] move camera and light from Hd to Hdx motivation: HdLight is a specific implementation of GlfSimpleLight, which we wanted to move out of hd. Same thing for HdCamera. fix: We introduce new type for the base class of non-renderable prims, HdSprim (state prim). The decendants of this class will be used for communicating scene delegate and cache data with change tracking. They don't provide drawItems, thus not to be displayed. HdxCamera and HdxLight inherit from HdSprim and do the same job as before. other changes: - move DirtyBits for camera and light to Hdx as well. - move Tokens for camera and light to Hdx as well. - update DebugCodes accordingly. - testHdCameraAndLight is moved to testHdxCameraAndLight. - hd no longer depends on cameraUtil - add API guards for plugin compatibility. todo: - HdxSimpleLightTask and HdxShadowTask have dynamic_cast to check if a sprim is HdxLight or not. this doesn't scale well. We continue to discuss to improve this (by VtValue, schema or type registration etc). (Internal change: 1653086) --- pxr/imaging/lib/hd/CMakeLists.txt | 4 +- pxr/imaging/lib/hd/changeTracker.cpp | 81 ++------ pxr/imaging/lib/hd/changeTracker.h | 74 +++---- pxr/imaging/lib/hd/debugCodes.cpp | 3 + pxr/imaging/lib/hd/debugCodes.h | 6 +- pxr/imaging/lib/hd/drawTarget.cpp | 16 +- pxr/imaging/lib/hd/drawTarget.h | 4 +- pxr/imaging/lib/hd/engine.cpp | 7 +- pxr/imaging/lib/hd/light.cpp | 109 ----------- pxr/imaging/lib/hd/light.h | 97 ---------- pxr/imaging/lib/hd/renderIndex.cpp | 183 +++++++----------- pxr/imaging/lib/hd/renderIndex.h | 94 +++------ pxr/imaging/lib/hd/sprim.cpp | 37 ++++ pxr/imaging/lib/hd/{camera.h => sprim.h} | 53 ++--- pxr/imaging/lib/hd/tokens.h | 13 +- pxr/imaging/lib/hd/unitTestDelegate.cpp | 33 +--- pxr/imaging/lib/hd/unitTestDelegate.h | 4 - pxr/imaging/lib/hd/version.h | 3 +- pxr/imaging/lib/hdx/CMakeLists.txt | 2 + pxr/imaging/lib/{hd => hdx}/camera.cpp | 59 +++--- pxr/imaging/lib/hdx/camera.h | 82 ++++++++ pxr/imaging/lib/hdx/drawTargetTask.cpp | 15 +- pxr/imaging/lib/hdx/light.cpp | 121 ++++++++++++ pxr/imaging/lib/hdx/light.h | 83 ++++++++ pxr/imaging/lib/hdx/renderSetupTask.cpp | 17 +- pxr/imaging/lib/hdx/renderSetupTask.h | 4 +- pxr/imaging/lib/hdx/renderTask.cpp | 2 +- pxr/imaging/lib/hdx/selectionTask.cpp | 1 - pxr/imaging/lib/hdx/shadowTask.cpp | 35 +++- pxr/imaging/lib/hdx/simpleLightBypassTask.cpp | 8 +- pxr/imaging/lib/hdx/simpleLightBypassTask.h | 2 +- pxr/imaging/lib/hdx/simpleLightTask.cpp | 73 ++++--- pxr/imaging/lib/hdx/simpleLightTask.h | 24 +-- pxr/imaging/lib/hdx/tokens.h | 2 + pxr/imaging/lib/hdx/unitTestDelegate.cpp | 56 ++++-- pxr/imaging/lib/hdx/unitTestDelegate.h | 3 + pxr/imaging/lib/hdx/version.h | 3 +- .../lib/usdImaging/defaultTaskDelegate.cpp | 49 ++--- .../lib/usdImaging/defaultTaskDelegate.h | 2 +- .../maya/lib/pxrUsdMayaGL/batchRenderer.cpp | 49 +++++ 40 files changed, 786 insertions(+), 727 deletions(-) delete mode 100644 pxr/imaging/lib/hd/light.cpp delete mode 100644 pxr/imaging/lib/hd/light.h create mode 100644 pxr/imaging/lib/hd/sprim.cpp rename pxr/imaging/lib/hd/{camera.h => sprim.h} (53%) rename pxr/imaging/lib/{hd => hdx}/camera.cpp (69%) create mode 100644 pxr/imaging/lib/hdx/camera.h create mode 100644 pxr/imaging/lib/hdx/light.cpp create mode 100644 pxr/imaging/lib/hdx/light.h diff --git a/pxr/imaging/lib/hd/CMakeLists.txt b/pxr/imaging/lib/hd/CMakeLists.txt index abe4e3cb7c..b34cc63429 100644 --- a/pxr/imaging/lib/hd/CMakeLists.txt +++ b/pxr/imaging/lib/hd/CMakeLists.txt @@ -21,7 +21,6 @@ pxr_shared_library(hd vt work sdf - cameraUtil glf garch pxOsd @@ -45,7 +44,6 @@ pxr_shared_library(hd bufferResource bufferSource bufferSpec - camera changeTracker codeGen commandBuffer @@ -74,7 +72,6 @@ pxr_shared_library(hd instancer instanceRegistry interleavedMemoryManager - light lightingShader mesh meshTopology @@ -99,6 +96,7 @@ pxr_shared_library(hd shader shaderKey shaderParam + sprim surfaceShader strategyBase task diff --git a/pxr/imaging/lib/hd/changeTracker.cpp b/pxr/imaging/lib/hd/changeTracker.cpp index f183d183cd..054ac51f1c 100644 --- a/pxr/imaging/lib/hd/changeTracker.cpp +++ b/pxr/imaging/lib/hd/changeTracker.cpp @@ -389,95 +389,48 @@ HdChangeTracker::MarkInstancerClean(SdfPath const& id, DirtyBits newBits) } // -------------------------------------------------------------------------- // -/// \name Camera Object Tracking +/// \name Sprim Tracking (camera, light...) // -------------------------------------------------------------------------- // void -HdChangeTracker::CameraInserted(SdfPath const& id) +HdChangeTracker::SprimInserted(SdfPath const& id, int initialDirtyState) { - TF_DEBUG(HD_CAMERA_ADDED).Msg("Camera Added: %s\n", id.GetText()); - _cameraState[id] = AllDirty; + TF_DEBUG(HD_SPRIM_ADDED).Msg("Sprim Added: %s\n", id.GetText()); + _sprimState[id] = initialDirtyState; } void -HdChangeTracker::CameraRemoved(SdfPath const& id) +HdChangeTracker::SprimRemoved(SdfPath const& id) { - TF_DEBUG(HD_CAMERA_REMOVED).Msg("Camera Removed: %s\n", id.GetText()); - _cameraState.erase(id); + TF_DEBUG(HD_SPRIM_REMOVED).Msg("Sprim Removed: %s\n", id.GetText()); + _sprimState.erase(id); } HdChangeTracker::DirtyBits -HdChangeTracker::GetCameraDirtyBits(SdfPath const& id) +HdChangeTracker::GetSprimDirtyBits(SdfPath const& id) { - _IDStateMap::iterator it = _cameraState.find(id); - if (not TF_VERIFY(it != _cameraState.end())) + _IDStateMap::iterator it = _sprimState.find(id); + if (not TF_VERIFY(it != _sprimState.end())) return Clean; return it->second; } void -HdChangeTracker::MarkCameraDirty(SdfPath const& id, DirtyBits bits) +HdChangeTracker::MarkSprimDirty(SdfPath const& id, DirtyBits bits) { - _IDStateMap::iterator it = _cameraState.find(id); - if (not TF_VERIFY(it != _cameraState.end())) + _IDStateMap::iterator it = _sprimState.find(id); + if (not TF_VERIFY(it != _sprimState.end())) return; it->second = it->second | bits; } void -HdChangeTracker::MarkCameraClean(SdfPath const& id, DirtyBits newBits) +HdChangeTracker::MarkSprimClean(SdfPath const& id, DirtyBits newBits) { - _IDStateMap::iterator it = _cameraState.find(id); - if (not TF_VERIFY(it != _cameraState.end())) + _IDStateMap::iterator it = _sprimState.find(id); + if (not TF_VERIFY(it != _sprimState.end())) return; - // preserve the variability bit - it->second = (it->second & Varying) | newBits; -} - -// -------------------------------------------------------------------------- // -/// \name Light Object Tracking -// -------------------------------------------------------------------------- // - -void -HdChangeTracker::LightInserted(SdfPath const& id) -{ - TF_DEBUG(HD_LIGHT_ADDED).Msg("Light Added: %s\n", id.GetText()); - _lightState[id] = AllDirty; -} - -void -HdChangeTracker::LightRemoved(SdfPath const& id) -{ - TF_DEBUG(HD_LIGHT_REMOVED).Msg("Light Removed: %s\n", id.GetText()); - _lightState.erase(id); -} - -HdChangeTracker::DirtyBits -HdChangeTracker::GetLightDirtyBits(SdfPath const& id) -{ - _IDStateMap::iterator it = _lightState.find(id); - if (not TF_VERIFY(it != _lightState.end())) - return Clean; - return it->second; -} - -void -HdChangeTracker::MarkLightDirty(SdfPath const& id, DirtyBits bits) -{ - _IDStateMap::iterator it = _lightState.find(id); - if (not TF_VERIFY(it != _lightState.end())) - return; - it->second = it->second | bits; -} - -void -HdChangeTracker::MarkLightClean(SdfPath const& id, DirtyBits newBits) -{ - _IDStateMap::iterator it = _lightState.find(id); - if (not TF_VERIFY(it != _lightState.end())) - return; - // preserve the variability bit - it->second = (it->second & Varying) | newBits; + it->second = newBits; } // -------------------------------------------------------------------------- // diff --git a/pxr/imaging/lib/hd/changeTracker.h b/pxr/imaging/lib/hd/changeTracker.h index 036b5ac9cb..871a5aa92d 100644 --- a/pxr/imaging/lib/hd/changeTracker.h +++ b/pxr/imaging/lib/hd/changeTracker.h @@ -79,16 +79,14 @@ class HdChangeTracker : public boost::noncopyable { CustomBitsEnd = 1 << 30, }; + // Dirty bits for Tasks, Textures enum NonRprimDirtyBits { //Varying = 1 << 0, DirtyType = 1 << 1, DirtyChildren = 1 << 2, DirtyParams = 1 << 3, - DirtyShadowParams = 1 << 4, - DirtyCollection = 1 << 5, - DirtyWindowPolicy = 1 << 6, - DirtyTexture = 1 << 7, - DirtyClipPlanes = 1 << 8, + DirtyCollection = 1 << 4, + DirtyTexture = 1 << 5, }; @@ -346,48 +344,6 @@ class HdChangeTracker : public boost::noncopyable { /// Clean the specified dirty bits for the instancer with \p id. void MarkInstancerClean(SdfPath const& id, DirtyBits newBits=Clean); - // ---------------------------------------------------------------------- // - /// @} - /// \name Camera Object Tracking - /// @{ - // ---------------------------------------------------------------------- // - - /// Start tracking Camera with the given \p id. - void CameraInserted(SdfPath const& id); - - /// Stop tracking Camera with the given \p id. - void CameraRemoved(SdfPath const& id); - - /// Get the dirty bits for Camera with the given \p id. - DirtyBits GetCameraDirtyBits(SdfPath const& id); - - /// Set the dirty flags to \p bits. - void MarkCameraDirty(SdfPath const& id, DirtyBits bits=AllDirty); - - /// Set the dirty flags to \p newBits. - void MarkCameraClean(SdfPath const& id, DirtyBits newBits=Clean); - - // ---------------------------------------------------------------------- // - /// @} - /// \name Light Object Tracking - /// @{ - // ---------------------------------------------------------------------- // - - /// Start tracking Light with the given \p id. - void LightInserted(SdfPath const& id); - - /// Stop tracking Light with the given \p id. - void LightRemoved(SdfPath const& id); - - /// Get the dirty bits for Light with the given \p id. - DirtyBits GetLightDirtyBits(SdfPath const& id); - - /// Set the dirty flags to \p bits. - void MarkLightDirty(SdfPath const& id, DirtyBits bits=AllDirty); - - /// Set the dirty flags to \p newBits. - void MarkLightClean(SdfPath const& id, DirtyBits newBits=Clean); - // ---------------------------------------------------------------------- // /// @} /// \name Draw Target Object Tracking @@ -413,6 +369,27 @@ class HdChangeTracker : public boost::noncopyable { /// draw targets has changed. unsigned GetDrawTargetSetVersion(); + // ---------------------------------------------------------------------- // + /// @} + /// \name Sprim (scene state prim: camera, light, ...) state Tracking + /// @{ + // ---------------------------------------------------------------------- // + + /// Start tracking sprim with the given \p id. + void SprimInserted(SdfPath const& id, int initialDirtyState); + + /// Stop tracking sprim with the given \p id. + void SprimRemoved(SdfPath const& id); + + /// Get the dirty bits for sprim with the given \p id. + DirtyBits GetSprimDirtyBits(SdfPath const& id); + + /// Set the dirty flags to \p bits. + void MarkSprimDirty(SdfPath const& id, DirtyBits bits); + + /// Set the dirty flags to \p newBits. + void MarkSprimClean(SdfPath const& id, DirtyBits newBits=Clean); + // ---------------------------------------------------------------------- // /// @} /// \name GarbageCollection Tracking @@ -503,9 +480,8 @@ class HdChangeTracker : public boost::noncopyable { _IDStateMap _shaderState; _IDStateMap _taskState; _IDStateMap _textureState; - _IDStateMap _cameraState; - _IDStateMap _lightState; _IDStateMap _drawTargetState; + _IDStateMap _sprimState; // Collection versions / state. _CollectionStateMap _collectionState; diff --git a/pxr/imaging/lib/hd/debugCodes.cpp b/pxr/imaging/lib/hd/debugCodes.cpp index 5f01e0a00f..517dad053d 100644 --- a/pxr/imaging/lib/hd/debugCodes.cpp +++ b/pxr/imaging/lib/hd/debugCodes.cpp @@ -75,6 +75,9 @@ TF_REGISTRY_FUNCTION(TfDebug) TF_DEBUG_ENVIRONMENT_SYMBOL(HD_SAFE_MODE, "Enable additional security checks"); + TF_DEBUG_ENVIRONMENT_SYMBOL(HD_SPRIM_ADDED, "Report when sprims are added"); + TF_DEBUG_ENVIRONMENT_SYMBOL(HD_SPRIM_REMOVED, "Report when sprims are removed") +; TF_DEBUG_ENVIRONMENT_SYMBOL(HD_SHADER_ADDED, "Report when shaders are added"); TF_DEBUG_ENVIRONMENT_SYMBOL(HD_SHADER_REMOVED, "Report when shaders are removed"); diff --git a/pxr/imaging/lib/hd/debugCodes.h b/pxr/imaging/lib/hd/debugCodes.h index a0eb4133cf..dca9a61f26 100644 --- a/pxr/imaging/lib/hd/debugCodes.h +++ b/pxr/imaging/lib/hd/debugCodes.h @@ -33,10 +33,6 @@ TF_DEBUG_CODES( HD_BUFFER_ARRAY_RANGE_CLEANED, HD_CACHE_HITS, HD_CACHE_MISSES, - HD_CAMERA_ADDED, - HD_CAMERA_REMOVED, - HD_LIGHT_ADDED, - HD_LIGHT_REMOVED, HD_COLLECTION_CHANGED, HD_COUNTER_CHANGED, HD_DIRTY_LIST, @@ -64,6 +60,8 @@ TF_DEBUG_CODES( HD_SAFE_MODE, HD_SHADER_ADDED, HD_SHADER_REMOVED, + HD_SPRIM_ADDED, + HD_SPRIM_REMOVED, HD_TASK_ADDED, HD_TASK_REMOVED, HD_TEXTURE_ADDED, diff --git a/pxr/imaging/lib/hd/drawTarget.cpp b/pxr/imaging/lib/hd/drawTarget.cpp index 08090eb7df..fd87897382 100644 --- a/pxr/imaging/lib/hd/drawTarget.cpp +++ b/pxr/imaging/lib/hd/drawTarget.cpp @@ -23,18 +23,16 @@ // #include "pxr/imaging/hd/drawTarget.h" +#include "pxr/imaging/hd/conversions.h" +#include "pxr/imaging/hd/drawTargetAttachmentDescArray.h" #include "pxr/imaging/hd/perfLog.h" #include "pxr/imaging/hd/sceneDelegate.h" -#include "pxr/imaging/hd/conversions.h" -#include "pxr/imaging/hd/camera.h" +#include "pxr/imaging/hd/sprim.h" -#include "pxr/imaging/hd/drawTargetAttachmentDescArray.h" +#include "pxr/imaging/glf/glContext.h" #include "pxr/base/tf/stl.h" - -#include "pxr/imaging/glf/glContext.h" - static const std::string DEPTH_ATTACHMENT_NAME = "depth"; HdDrawTarget::HdDrawTarget(HdSceneDelegate *delegate, SdfPath const &id) @@ -171,7 +169,7 @@ HdDrawTarget::WriteToFile(const std::string &attachment, return false; } - HdCameraSharedPtr camera = _GetCamera(); + HdSprimSharedPtr camera = _GetCamera(); if (!camera) { TF_WARN("Missing camera\n"); return false; @@ -259,10 +257,10 @@ HdDrawTarget::_SetAttachments(const HdDrawTargetAttachmentDescArray &attachments } -HdCameraSharedPtr +HdSprimSharedPtr HdDrawTarget::_GetCamera() const { - return _delegate->GetRenderIndex().GetCamera(_cameraId); + return _delegate->GetRenderIndex().GetSprim(_cameraId); } void diff --git a/pxr/imaging/lib/hd/drawTarget.h b/pxr/imaging/lib/hd/drawTarget.h index 851f8705ad..abe9467e4f 100644 --- a/pxr/imaging/lib/hd/drawTarget.h +++ b/pxr/imaging/lib/hd/drawTarget.h @@ -40,7 +40,7 @@ class HdSceneDelegate; class HdDrawTargetAttachmentDescArray; typedef boost::shared_ptr HdDrawTargetSharedPtr; -typedef boost::shared_ptr HdCameraSharedPtr; +typedef boost::shared_ptr HdSprimSharedPtr; typedef boost::shared_ptr GlfGLContextSharedPtr; typedef std::vector HdDrawTargetSharedPtrVector; @@ -107,7 +107,7 @@ class HdDrawTarget final { void _SetAttachments(const HdDrawTargetAttachmentDescArray &attachments); void _SetCamera(const SdfPath &cameraPath); - HdCameraSharedPtr _GetCamera() const; + HdSprimSharedPtr _GetCamera() const; void _ResizeDrawTarget(); diff --git a/pxr/imaging/lib/hd/engine.cpp b/pxr/imaging/lib/hd/engine.cpp index 2559ed3b5e..399d8f24f0 100644 --- a/pxr/imaging/lib/hd/engine.cpp +++ b/pxr/imaging/lib/hd/engine.cpp @@ -134,11 +134,8 @@ HdEngine::Execute(HdRenderIndex& index, HdTaskSharedPtrVector const &tasks) _InitCaps(); - // Sync the cameras - index.SyncCameras(); - - // Sync the lights - index.SyncLights(); + // Sync the scene state prims + index.SyncSprims(); // Sync the draw targets index.SyncDrawTargets(); diff --git a/pxr/imaging/lib/hd/light.cpp b/pxr/imaging/lib/hd/light.cpp deleted file mode 100644 index 0bb5901047..0000000000 --- a/pxr/imaging/lib/hd/light.cpp +++ /dev/null @@ -1,109 +0,0 @@ -// -// 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. -// -#include "pxr/imaging/hd/light.h" - -#include "pxr/imaging/hd/perfLog.h" -#include "pxr/imaging/hd/sceneDelegate.h" - -#include "pxr/base/tf/stl.h" - -HdLight::HdLight(HdSceneDelegate *delegate, SdfPath const &id) - : _delegate(delegate) - , _id(id) - , _transform(1.0) - , _params() - , _shadowParams() - , _shadowCollection() -{ -} - -HdLight::~HdLight() -{ -} - -void -HdLight::Sync() -{ - HD_TRACE_FUNCTION(); - HD_MALLOC_TAG_FUNCTION(); - - if (not TF_VERIFY(_delegate)) { - return; - } - - // HdLight communicates to the scene graph and caches all interesting - // values within this class. - - // later on Get() is called from TaskState (RenderPass) to perform - // aggregation/pre-computation, in order to make the shader execution - // efficient. - - HdChangeTracker& changeTracker = - _delegate->GetRenderIndex().GetChangeTracker(); - HdChangeTracker::DirtyBits bits = changeTracker.GetLightDirtyBits(_id); - - if (bits & HdChangeTracker::DirtyTransform) { - VtValue vtTransform = _delegate->Get(_id, HdTokens->lightTransform); - - // Optional - if (vtTransform.IsHolding()) { - _transform = vtTransform.UncheckedGet(); - } else { - _transform.SetIdentity(); - } - } - - if (bits & HdChangeTracker::DirtyParams) { - VtValue vtLightParams = _delegate->Get(_id, HdTokens->lightParams); - - if (TF_VERIFY(vtLightParams.IsHolding())) { - _params = vtLightParams.UncheckedGet(); - } else { - _params = GlfSimpleLight(); - } - } - - if (bits & HdChangeTracker::DirtyShadowParams) { - _shadowParams = _delegate->Get(_id, HdTokens->lightShadowParams); - } - - if (bits & HdChangeTracker::DirtyCollection) { - VtValue vtShadowCollection = - _delegate->Get(_id, HdTokens->lightShadowCollection); - - // Optional - if (vtShadowCollection.IsHolding()) { - HdRprimCollection newCollection = - vtShadowCollection.UncheckedGet(); - - if (_shadowCollection != newCollection) { - _shadowCollection = newCollection; - changeTracker.MarkCollectionDirty(_shadowCollection.GetName()); - } - - } else { - _shadowCollection = HdRprimCollection(); - } - } -} diff --git a/pxr/imaging/lib/hd/light.h b/pxr/imaging/lib/hd/light.h deleted file mode 100644 index 0a77932b0e..0000000000 --- a/pxr/imaging/lib/hd/light.h +++ /dev/null @@ -1,97 +0,0 @@ -// -// 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 HD_LIGHT_H -#define HD_LIGHT_H - -#include "pxr/imaging/hd/version.h" -#include "pxr/imaging/hd/rprimCollection.h" - -#include "pxr/imaging/glf/simpleLight.h" - -#include "pxr/base/gf/matrix4d.h" -#include "pxr/base/vt/value.h" - -#include - -#include - -class HdSceneDelegate; -typedef boost::shared_ptr HdLightSharedPtr; -typedef std::vector HdLightSharedPtrVector; - -/// \class HdLight -/// -/// A light model, used in conjunction with HdRenderPass. -/// -class HdLight { -public: - HdLight(HdSceneDelegate* delegate, SdfPath const & id); - ~HdLight(); // note: not virtual (for now) - - /// Returns the HdSceneDelegate which backs this texture. - HdSceneDelegate* GetDelegate() const { return _delegate; } - - /// Returns the identifer by which this light is known. This - /// identifier is a common associative key used by the SceneDelegate, - /// RenderIndex, and for binding to the light - SdfPath const& GetID() const { return _id; } - - /// Synchronizes state from the delegate to Hydra, for example, allocating - /// parameters into GPU memory. - void Sync(); - - // ---------------------------------------------------------------------- // - /// \name Light API - // ---------------------------------------------------------------------- // - - /// Returns the transform for the light. - const GfMatrix4d &GetTransform() const { return _transform; } - - /// Returns the light parameters - const GlfSimpleLight &GetParams() const { return _params; } - - /// Returns shadow parameters for the light as a VtValue. - // XXX: Promote shadow to Hd (maybe even first class citizen in Hd?) - const VtValue &GetShadowParams() const { return _shadowParams; } - - /// Returns the collection of prims that cast a shadow using this light - const HdRprimCollection &GetShadowCollection() const - { - return _shadowCollection; - } - -private: - HdSceneDelegate* _delegate; - SdfPath _id; - - GfMatrix4d _transform; - GlfSimpleLight _params; - - // XXX: Promote shadow to Hd (maybe even first class citizen in Hd?) - VtValue _shadowParams; - HdRprimCollection _shadowCollection; - -}; - -#endif // HD_LIGHT_H diff --git a/pxr/imaging/lib/hd/renderIndex.cpp b/pxr/imaging/lib/hd/renderIndex.cpp index 01feb7facf..d23233489e 100644 --- a/pxr/imaging/lib/hd/renderIndex.cpp +++ b/pxr/imaging/lib/hd/renderIndex.cpp @@ -23,9 +23,7 @@ // #include "pxr/imaging/hd/renderIndex.h" -#include "pxr/imaging/hd/light.h" #include "pxr/imaging/hd/basisCurves.h" -#include "pxr/imaging/hd/camera.h" #include "pxr/imaging/hd/dirtyList.h" #include "pxr/imaging/hd/drawItem.h" #include "pxr/imaging/hd/drawTarget.h" @@ -40,6 +38,7 @@ #include "pxr/imaging/hd/rprimCollection.h" #include "pxr/imaging/hd/mesh.h" #include "pxr/imaging/hd/sceneDelegate.h" +#include "pxr/imaging/hd/sprim.h" #include "pxr/imaging/hd/surfaceShader.h" #include "pxr/imaging/hd/texture.h" #include "pxr/imaging/hd/tokens.h" @@ -214,6 +213,10 @@ HdRenderIndex::Clear() _rprimMap.clear(); _delegateRprimMap.clear(); + // Clear Sprims + _sprimIDSet.clear(); + _sprimMap.clear(); + // Clear instancers. TF_FOR_ALL(it, _instancerMap) { _tracker.InstancerRemoved(it->first); @@ -417,84 +420,6 @@ HdRenderIndex::RemoveTexture(SdfPath const& id) _textureMap.erase(it); } -// -------------------------------------------------------------------------- // -/// \name Camera Support -// -------------------------------------------------------------------------- // - -void -HdRenderIndex::_TrackDelegateCamera(HdSceneDelegate* delegate, - SdfPath const& cameraId, - HdCameraSharedPtr const& camera) -{ - if (cameraId == SdfPath()) - return; - _tracker.CameraInserted(cameraId); - _cameraMap.insert(std::make_pair(cameraId, camera)); -} - -HdCameraSharedPtr const& -HdRenderIndex::GetCamera(SdfPath const& id) const { - _CameraMap::const_iterator it = _cameraMap.find(id); - if (it != _cameraMap.end()) - return it->second; - - static HdCameraSharedPtr EMPTY; - return EMPTY; -} - -void -HdRenderIndex::RemoveCamera(SdfPath const& id) -{ - HD_TRACE_FUNCTION(); - HD_MALLOC_TAG_FUNCTION(); - - _CameraMap::iterator it = _cameraMap.find(id); - if (it == _cameraMap.end()) - return; - - _tracker.CameraRemoved(id); - _cameraMap.erase(it); -} - -// -------------------------------------------------------------------------- // -/// \name Light Support -// -------------------------------------------------------------------------- // - -void -HdRenderIndex::_TrackDelegateLight(HdSceneDelegate* delegate, - SdfPath const& lightId, - HdLightSharedPtr const& light) -{ - if (lightId == SdfPath()) - return; - _tracker.LightInserted(lightId); - _lightMap.insert(std::make_pair(lightId, light)); -} - -HdLightSharedPtr const& -HdRenderIndex::GetLight(SdfPath const& id) const { - _LightMap::const_iterator it = _lightMap.find(id); - if (it != _lightMap.end()) - return it->second; - - static HdLightSharedPtr EMPTY; - return EMPTY; -} - -void -HdRenderIndex::RemoveLight(SdfPath const& id) -{ - HD_TRACE_FUNCTION(); - HD_MALLOC_TAG_FUNCTION(); - - _LightMap::iterator it = _lightMap.find(id); - if (it == _lightMap.end()) - return; - - _tracker.LightRemoved(id); - _lightMap.erase(it); -} - // -------------------------------------------------------------------------- // /// \name Draw Target Support // -------------------------------------------------------------------------- // @@ -538,6 +463,67 @@ HdRenderIndex::GetDrawTarget(SdfPath const& id) const return EMPTY; } +// -------------------------------------------------------------------------- // +/// \name Sprim Support (scene state prim: light, camera...) +// -------------------------------------------------------------------------- // + +void +HdRenderIndex::_TrackDelegateSprim(HdSceneDelegate* delegate, + SdfPath const& id, + HdSprimSharedPtr const& sprim, + int initialDirtyState) +{ + if (id == SdfPath()) { + return; + } + _tracker.SprimInserted(id, initialDirtyState); + _sprimIDSet.insert(id); + _sprimMap.insert(std::make_pair(id, sprim)); +} + +HdSprimSharedPtr const& +HdRenderIndex::GetSprim(SdfPath const& id) const +{ + _SprimMap::const_iterator it = _sprimMap.find(id); + if (it != _sprimMap.end()) { + return it->second; + } + + static HdSprimSharedPtr EMPTY; + return EMPTY; +} + +void +HdRenderIndex::RemoveSprim(SdfPath const& id) +{ + HD_TRACE_FUNCTION(); + HD_MALLOC_TAG_FUNCTION(); + + _SprimMap::iterator it = _sprimMap.find(id); + if (it == _sprimMap.end()) { + return; + } + + _tracker.SprimRemoved(id); + _sprimMap.erase(it); + _sprimIDSet.erase(id); +} + +SdfPathVector +HdRenderIndex::GetSprimSubtree(SdfPath const& rootPath) const +{ + HD_TRACE_FUNCTION(); + HD_MALLOC_TAG_FUNCTION(); + + SdfPathVector paths; + paths.reserve(1024); + for (auto p = _sprimIDSet.lower_bound(rootPath); + p != _sprimIDSet.end() and p->HasPrefix(rootPath); ++p) + { + paths.push_back(*p); + } + return paths; +} // -------------------------------------------------------------------------- // /// \name Draw Item Handling @@ -696,22 +682,6 @@ HdRenderIndex::GetDrawItems(HdRprimCollection const& collection) return finalResult; } -HdRenderIndex::HdLightView -HdRenderIndex::GetLights() -{ - HD_TRACE_FUNCTION(); - - HdLightView result; - result.reserve(_lightMap.size()); - - TF_FOR_ALL (it, _lightMap) { - // XXX We could support collections here -> IsInCollection - result.push_back(it->second); - } - - return result; -} - HdRenderIndex::HdDrawTargetView HdRenderIndex::GetDrawTargets() { @@ -1064,26 +1034,13 @@ HdRenderIndex::SyncAll() } void -HdRenderIndex::SyncCameras() -{ - TF_FOR_ALL(it, _cameraMap) { - if (HdChangeTracker::IsDirty(_tracker.GetCameraDirtyBits(it->first))) { - it->second->Sync(); - - _tracker.MarkCameraClean(it->first); - } - - } -} - -void -HdRenderIndex::SyncLights() +HdRenderIndex::SyncSprims() { - TF_FOR_ALL(it, _lightMap) { - if (HdChangeTracker::IsDirty(_tracker.GetLightDirtyBits(it->first))) { + TF_FOR_ALL(it, _sprimMap) { + if (HdChangeTracker::IsDirty(_tracker.GetSprimDirtyBits(it->first))) { it->second->Sync(); - _tracker.MarkLightClean(it->first); + _tracker.MarkSprimClean(it->first); } } diff --git a/pxr/imaging/lib/hd/renderIndex.h b/pxr/imaging/lib/hd/renderIndex.h index 96fb3a9c8f..7beff1d2c6 100644 --- a/pxr/imaging/lib/hd/renderIndex.h +++ b/pxr/imaging/lib/hd/renderIndex.h @@ -42,16 +42,16 @@ class HdDrawItem; class HdRprimCollection; class HdSceneDelegate; -typedef boost::shared_ptr HdLightSharedPtr; typedef boost::shared_ptr HdDrawTargetSharedPtr; -typedef boost::shared_ptr HdCameraSharedPtr; typedef boost::shared_ptr HdDirtyListSharedPtr; typedef boost::shared_ptr HdRprimSharedPtr; typedef boost::shared_ptr HdRprimConstSharedPtr; +typedef boost::shared_ptr HdSprimSharedPtr; typedef boost::shared_ptr HdInstancerSharedPtr; typedef boost::shared_ptr HdSurfaceShaderSharedPtr; typedef boost::shared_ptr HdTaskSharedPtr; typedef boost::shared_ptr HdTextureSharedPtr; +typedef std::vector HdSprimSharedPtrVector; /// \class HdRenderIndex /// @@ -67,7 +67,6 @@ class HdRenderIndex : public boost::noncopyable { // XXX: These should return iterator ranges, not vectors; // they also shouldn't be pointers. typedef std::vector HdDrawItemView; - typedef std::vector HdLightView; typedef std::vector HdDrawTargetView; HdRenderIndex(); @@ -87,8 +86,6 @@ class HdRenderIndex : public boost::noncopyable { HdDrawItemView GetDrawItems(HdRprimCollection const& collection); - HdLightView GetLights(); - /// Returns a list of all draw targets in the render index. HdDrawTargetView GetDrawTargets(); @@ -98,15 +95,11 @@ class HdRenderIndex : public boost::noncopyable { /// Processes all pending dirty lists void SyncAll(); - /// Synchronize all cameras in the render index - void SyncCameras(); - - /// Synchronize all lights in the render index - void SyncLights(); - /// Synchronize all draw targets in the render index void SyncDrawTargets(); + /// Synchronize all scene states in the render index + void SyncSprims(); /// Returns a vector of Rprim IDs that are bound to the given DelegateID. SdfPathVector const& GetDelegateRprimIDs(SdfPath const& delegateID) const; @@ -240,34 +233,18 @@ class HdRenderIndex : public boost::noncopyable { HdTextureSharedPtr const& GetTexture(SdfPath const& id) const; // ---------------------------------------------------------------------- // - /// \name Camera Support - // ---------------------------------------------------------------------- // - - /// Inserts a new camera into the RenderIndex with an identifier of \p id. - template - void - InsertCamera(HdSceneDelegate* delegate, SdfPath const& id); - - /// Removes the given camera from the RenderIndex. - void RemoveCamera(SdfPath const& id); - - /// Returns the camera for the given \p id. - HdCameraSharedPtr const& GetCamera(SdfPath const& id) const; - - // ---------------------------------------------------------------------- // - /// \name Light Support + /// \name Scene state prims (e.g. camera, light) // ---------------------------------------------------------------------- // - - /// Inserts a new light into the RenderIndex with an identifier of \p id. template void - InsertLight(HdSceneDelegate* delegate, SdfPath const& id); + InsertSprim(HdSceneDelegate* delegate, SdfPath const &id); + + void RemoveSprim(SdfPath const &id); - /// Removes the given light from the RenderIndex. - void RemoveLight(SdfPath const& id); + HdSprimSharedPtr const &GetSprim(SdfPath const &id) const; - /// Returns the light for the given \p id. - HdLightSharedPtr const& GetLight(SdfPath const& id) const; + /// Returns the subtree rooted under the given path. + SdfPathVector GetSprimSubtree(SdfPath const& root) const; // ---------------------------------------------------------------------- // /// \name Draw Target Support @@ -316,21 +293,17 @@ class HdRenderIndex : public boost::noncopyable { SdfPath const& textureId, HdTextureSharedPtr const& texture); - // Inserts the camera into the index and updates tracking state. - void _TrackDelegateCamera(HdSceneDelegate* delegate, - SdfPath const& cameraId, - HdCameraSharedPtr const& camera); - - // Inserts the light into the index and updates tracking state. - void _TrackDelegateLight(HdSceneDelegate* delegate, - SdfPath const& lightId, - HdLightSharedPtr const& light); - // Inserts the draw target into the index and updates tracking state. void _TrackDelegateDrawTarget(HdSceneDelegate* delegate, SdfPath const& drawTargetId, HdDrawTargetSharedPtr const& drawTarget); + // Inserts the scene state prim into the index and updates tracking state. + void _TrackDelegateSprim(HdSceneDelegate* delegate, + SdfPath const& id, + HdSprimSharedPtr const& state, + int initialDirtyState); + // ---------------------------------------------------------------------- // // Index State @@ -340,17 +313,17 @@ class HdRenderIndex : public boost::noncopyable { size_t childIndex; HdRprimSharedPtr rprim; }; - + typedef TfHashMap _ShaderMap; typedef TfHashMap _TaskMap; typedef TfHashMap _TextureMap; typedef TfHashMap _RprimMap; typedef TfHashMap _DelegateRprimMap; - typedef TfHashMap _CameraMap; - typedef TfHashMap _LightMap; typedef TfHashMap _DrawTargetMap; + typedef TfHashMap _SprimMap; typedef std::set _RprimIDSet; + typedef std::set _SprimIDSet; typedef std::map _RprimPrimIDMap; _DelegateRprimMap _delegateRprimMap; @@ -362,10 +335,11 @@ class HdRenderIndex : public boost::noncopyable { _ShaderMap _shaderMap; _TaskMap _taskMap; _TextureMap _textureMap; - _CameraMap _cameraMap; - _LightMap _lightMap; _DrawTargetMap _drawTargetMap; + _SprimMap _sprimMap; + _SprimIDSet _sprimIDSet; + HdChangeTracker _tracker; int32_t _nextPrimId; @@ -437,34 +411,24 @@ HdRenderIndex::InsertTexture(HdSceneDelegate* delegate, SdfPath const& id) template void -HdRenderIndex::InsertCamera(HdSceneDelegate* delegate, SdfPath const& id) +HdRenderIndex::InsertDrawTarget(HdSceneDelegate* delegate, SdfPath const& id) { HD_TRACE_FUNCTION(); HD_MALLOC_TAG_FUNCTION(); - boost::shared_ptr camera = boost::make_shared(delegate, id); - _TrackDelegateCamera(delegate, id, camera); + boost::shared_ptr drawTarget = boost::make_shared(delegate, id); + _TrackDelegateDrawTarget(delegate, id, drawTarget); } template void -HdRenderIndex::InsertLight(HdSceneDelegate* delegate, SdfPath const& id) +HdRenderIndex::InsertSprim(HdSceneDelegate* delegate, SdfPath const& id) { HD_TRACE_FUNCTION(); HD_MALLOC_TAG_FUNCTION(); - boost::shared_ptr light = boost::make_shared(delegate, id); - _TrackDelegateLight(delegate, id, light); + boost::shared_ptr sprim = boost::make_shared(delegate, id); + _TrackDelegateSprim(delegate, id, sprim, T::AllDirty); } -template -void -HdRenderIndex::InsertDrawTarget(HdSceneDelegate* delegate, SdfPath const& id) -{ - HD_TRACE_FUNCTION(); - HD_MALLOC_TAG_FUNCTION(); - - boost::shared_ptr drawTarget = boost::make_shared(delegate, id); - _TrackDelegateDrawTarget(delegate, id, drawTarget); -} #endif //HD_RENDER_INDEX_H diff --git a/pxr/imaging/lib/hd/sprim.cpp b/pxr/imaging/lib/hd/sprim.cpp new file mode 100644 index 0000000000..29c389e5ac --- /dev/null +++ b/pxr/imaging/lib/hd/sprim.cpp @@ -0,0 +1,37 @@ +// +// 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. +// +#include "pxr/imaging/hd/sprim.h" + +#include "pxr/imaging/hd/perfLog.h" +#include "pxr/imaging/hd/sceneDelegate.h" + +HdSprim::HdSprim(HdSceneDelegate *delegate, SdfPath const &id) + : _delegate(delegate) + , _id(id) +{ +} + +HdSprim::~HdSprim() +{ +} diff --git a/pxr/imaging/lib/hd/camera.h b/pxr/imaging/lib/hd/sprim.h similarity index 53% rename from pxr/imaging/lib/hd/camera.h rename to pxr/imaging/lib/hd/sprim.h index d2ac0efab3..4484e1e1c3 100644 --- a/pxr/imaging/lib/hd/camera.h +++ b/pxr/imaging/lib/hd/sprim.h @@ -21,54 +21,55 @@ // KIND, either express or implied. See the Apache License for the specific // language governing permissions and limitations under the Apache License. // -#ifndef HD_CAMERA_H -#define HD_CAMERA_H +#ifndef HD_SPRIM_H +#define HD_SPRIM_H #include "pxr/imaging/hd/version.h" #include "pxr/usd/sdf/path.h" -#include "pxr/base/tf/hashmap.h" -#include "pxr/base/vt/dictionary.h" +#include "pxr/base/vt/value.h" #include class HdSceneDelegate; -typedef boost::shared_ptr HdCameraSharedPtr; +typedef boost::shared_ptr HdSprimSharedPtr; +typedef std::vector HdSprimSharedPtrVector; -/// \class HdCamera +/// \class HdSprim /// -/// A camera model, used in conjunction with HdRenderPass. +/// Sprim (state prim) is a base class of managing state for non-drawable +/// scene entity (e.g. camera, light). Similar to Rprim, Sprim communicates +/// scene delegate and tracks the changes through change tracker, then updates +/// data cached in Hd (either on CPU or GPU). /// -class HdCamera { +/// Unlike Rprim, Sprim doesn't produce draw items. The data cached in HdSprim +/// may be used by HdTask or by HdShader. +/// +/// The lifetime of HdSprim is owned by HdRenderIndex. +/// +class HdSprim { public: - typedef std::vector ClipPlanesVector; - - HdCamera(HdSceneDelegate* delegate, SdfPath const & id); - ~HdCamera(); // note: not virtual (for now) + HdSprim(HdSceneDelegate* delegate, SdfPath const & id); + virtual ~HdSprim(); - /// Returns the HdSceneDelegate which backs this texture. + /// Returns the HdSceneDelegate which backs this state HdSceneDelegate* GetDelegate() const { return _delegate; } - /// Returns the identifer by which this light is known. This + /// Returns the identifer by which this state is known. This /// identifier is a common associative key used by the SceneDelegate, - /// RenderIndex, and for binding to the light + /// RenderIndex, and for binding to the state (e.g. camera, light) SdfPath const& GetID() const { return _id; } - /// Synchronizes state from the delegate to Hydra, for example, allocating - /// parameters into GPU memory. - void Sync(); + /// Synchronizes state from the delegate to this object. + virtual void Sync() = 0; - // ---------------------------------------------------------------------- // - /// \name Camera API - // ---------------------------------------------------------------------- // - - VtValue Get(TfToken const &name); + /// Accessor for tasks to get the parameter cached in this sprim object. + /// Don't communicate back to scene delegate within this function. + virtual VtValue Get(TfToken const &token) const = 0; private: HdSceneDelegate* _delegate; SdfPath _id; - - TfHashMap _cameraValues; }; -#endif //HD_CAMERA_H +#endif // HD_SPRIM_H diff --git a/pxr/imaging/lib/hd/tokens.h b/pxr/imaging/lib/hd/tokens.h index a32f729c51..f0bcbea5e7 100644 --- a/pxr/imaging/lib/hd/tokens.h +++ b/pxr/imaging/lib/hd/tokens.h @@ -36,10 +36,8 @@ (bezier) \ (bSpline) \ (camera) \ - (cameraFrustum) \ (catmullRom) \ (children) \ - (clipPlanes) \ (color) \ (collection) \ (computeShader) \ @@ -77,12 +75,6 @@ (isFlipped) \ (itemsDrawn) \ (layout) \ - (lightingContext) \ - (lightingShader) \ - (lightParams) \ - (lightShadowCollection) \ - (lightShadowParams) \ - (lightTransform) \ (leftHanded) \ (linear) \ (nonperiodic) \ @@ -119,9 +111,8 @@ (visibility) \ (widths) \ (wire) \ - (wireOnSurf) \ - (windowPolicy) - + (wireOnSurf) + #define HD_PERF_TOKENS \ (basisCurvesTopology) \ (bufferSourcesResolved) \ diff --git a/pxr/imaging/lib/hd/unitTestDelegate.cpp b/pxr/imaging/lib/hd/unitTestDelegate.cpp index 5e722563c4..86de5f9b54 100644 --- a/pxr/imaging/lib/hd/unitTestDelegate.cpp +++ b/pxr/imaging/lib/hd/unitTestDelegate.cpp @@ -24,8 +24,7 @@ #include "pxr/imaging/hd/unitTestDelegate.h" #include "pxr/imaging/hd/basisCurves.h" -#include "pxr/imaging/hd/camera.h" -#include "pxr/imaging/hd/light.h" +#include "pxr/imaging/hd/sprim.h" #include "pxr/imaging/hd/mesh.h" #include "pxr/imaging/hd/meshTopology.h" #include "pxr/imaging/hd/points.h" @@ -259,28 +258,6 @@ Hd_UnitTestDelegate::AddTexture(SdfPath const& id, _textures[id] = _Texture(texture); } -void -Hd_UnitTestDelegate::AddCamera(SdfPath const &id) -{ - HdRenderIndex& index = GetRenderIndex(); - index.InsertCamera(this, id); - _cameras[id].params[HdShaderTokens->worldToViewMatrix] - = VtValue(GfMatrix4d(1)); - _cameras[id].params[HdShaderTokens->projectionMatrix] - = VtValue(GfMatrix4d(1)); -} - -void -Hd_UnitTestDelegate::AddLight(SdfPath const &id) -{ - HdRenderIndex& index = GetRenderIndex(); - index.InsertLight(this, id); - _lights[id].params[HdTokens->lightParams] - = VtValue(GlfSimpleLight()); - _lights[id].params[HdTokens->lightShadowCollection] - = VtValue(HdRprimCollection(HdTokens->geometry, HdTokens->hull)); -} - void Hd_UnitTestDelegate::HideRprim(SdfPath const& id) { @@ -416,14 +393,6 @@ Hd_UnitTestDelegate::UpdateCamera(SdfPath const &id, _cameras[id].params[key] = value; } -void -Hd_UnitTestDelegate::UpdateLight(SdfPath const &id, - TfToken const &key, - VtValue value) -{ - _lights[id].params[key] = value; -} - /*virtual*/ bool Hd_UnitTestDelegate::IsInCollection(SdfPath const& id, diff --git a/pxr/imaging/lib/hd/unitTestDelegate.h b/pxr/imaging/lib/hd/unitTestDelegate.h index 36ed61ed41..a582533197 100644 --- a/pxr/imaging/lib/hd/unitTestDelegate.h +++ b/pxr/imaging/lib/hd/unitTestDelegate.h @@ -179,9 +179,6 @@ class Hd_UnitTestDelegate : public HdSceneDelegate { /// Camera void AddCamera(SdfPath const &id); - /// Light - void AddLight(SdfPath const &id); - /// Remove a prim void Remove(SdfPath const &id); @@ -209,7 +206,6 @@ class Hd_UnitTestDelegate : public HdSceneDelegate { void UpdateInstancerPrototypes(float time); void UpdateCamera(SdfPath const &id, TfToken const &key, VtValue value); - void UpdateLight(SdfPath const &id, TfToken const &key, VtValue value); void BindSurfaceShader(SdfPath const &rprimId, SdfPath const &shaderId) { diff --git a/pxr/imaging/lib/hd/version.h b/pxr/imaging/lib/hd/version.h index 88acc226ea..22fae5e182 100644 --- a/pxr/imaging/lib/hd/version.h +++ b/pxr/imaging/lib/hd/version.h @@ -32,7 +32,8 @@ // 22 -> 23: remove ID render API // 23 -> 24: GetPathForInstanceIndex returns absolute instance index. // 24 -> 25: move simpleLightingShader to Hdx. -#define HD_API 25 +// 25 -> 26: move camera and light to Hdx. +#define HD_API 26 // 1 -> 2: SimpleLighting -> FallbackLighting #define HD_SHADER_API 2 diff --git a/pxr/imaging/lib/hdx/CMakeLists.txt b/pxr/imaging/lib/hdx/CMakeLists.txt index ac6e6f24f5..de1ce8ebd4 100644 --- a/pxr/imaging/lib/hdx/CMakeLists.txt +++ b/pxr/imaging/lib/hdx/CMakeLists.txt @@ -19,9 +19,11 @@ pxr_shared_library(hdx ${GLEW_INCLUDE_DIR} PUBLIC_CLASSES + camera debugCodes drawTargetTask intersector + light package renderTask renderSetupTask diff --git a/pxr/imaging/lib/hd/camera.cpp b/pxr/imaging/lib/hdx/camera.cpp similarity index 69% rename from pxr/imaging/lib/hd/camera.cpp rename to pxr/imaging/lib/hdx/camera.cpp index 636e289a00..64578aba2e 100644 --- a/pxr/imaging/lib/hd/camera.cpp +++ b/pxr/imaging/lib/hdx/camera.cpp @@ -21,7 +21,8 @@ // KIND, either express or implied. See the Apache License for the specific // language governing permissions and limitations under the Apache License. // -#include "pxr/imaging/hd/camera.h" +#include "pxr/imaging/hdx/camera.h" + #include "pxr/imaging/hd/perfLog.h" #include "pxr/imaging/hd/sceneDelegate.h" @@ -29,37 +30,40 @@ #include "pxr/base/gf/frustum.h" -HdCamera::HdCamera(HdSceneDelegate *delegate, SdfPath const &id) - : _delegate(delegate) - , _id(id) +TF_DEFINE_PUBLIC_TOKENS(HdxCameraTokens, HDX_CAMERA_TOKENS); + +HdxCamera::HdxCamera(HdSceneDelegate *delegate, SdfPath const &id) + : HdSprim(delegate, id) { } -HdCamera::~HdCamera() +HdxCamera::~HdxCamera() { } void -HdCamera::Sync() +HdxCamera::Sync() { HD_TRACE_FUNCTION(); HD_MALLOC_TAG_FUNCTION(); - if (not TF_VERIFY(_delegate)) { + SdfPath const &id = GetID(); + HdSceneDelegate *delegate = GetDelegate(); + if (not TF_VERIFY(delegate)) { return; } - // HdCamera communicates to the scene graph and caches all interesting + // HdxCamera communicates to the scene graph and caches all interesting // values within this class. // later on Get() is called from TaskState (RenderPass) to perform // aggregation/pre-computation, in order to make the shader execution // efficient. HdChangeTracker& changeTracker = - _delegate->GetRenderIndex().GetChangeTracker(); - HdChangeTracker::DirtyBits bits = changeTracker.GetCameraDirtyBits(_id); + delegate->GetRenderIndex().GetChangeTracker(); + HdChangeTracker::DirtyBits bits = changeTracker.GetSprimDirtyBits(id); - if (bits & HdChangeTracker::DirtyParams) { + if (bits & DirtyParams) { GfMatrix4d worldToViewMatrix; GfMatrix4d worldToViewInverseMatrix; GfMatrix4d projectionMatrix; @@ -70,7 +74,7 @@ HdCamera::Sync() // XXX: we will soon remove the GfFrustum interface and // use view/projection matrices from Phd too. - VtValue vfrustum = _delegate->Get(_id, HdTokens->cameraFrustum); + VtValue vfrustum = delegate->Get(id, HdxCameraTokens->cameraFrustum); if (not vfrustum.IsEmpty()) { // XXX This branch can be removed once we only support // camera matrices @@ -83,53 +87,54 @@ HdCamera::Sync() // Storing the camera frustum in the render index so we can // recalculate it later to fit specific windows - _cameraValues[HdTokens->cameraFrustum] = frustum; + _cameraValues[HdxCameraTokens->cameraFrustum] = frustum; } else { // XXX Line below to be removed when we only support matrices - _cameraValues[HdTokens->cameraFrustum] = VtValue(); + _cameraValues[HdxCameraTokens->cameraFrustum] = VtValue(); // view/projection matrices VtValue vViewMatrix - = _delegate->Get(_id, HdShaderTokens->worldToViewMatrix); + = delegate->Get(id, HdxCameraTokens->worldToViewMatrix); VtValue vProjMatrix - = _delegate->Get(_id, HdShaderTokens->projectionMatrix); + = delegate->Get(id, HdxCameraTokens->projectionMatrix); TF_VERIFY(vViewMatrix.IsHolding() and vProjMatrix.IsHolding()); - + worldToViewMatrix = vViewMatrix.Get(); worldToViewInverseMatrix = worldToViewMatrix.GetInverse(); projectionMatrix = vProjMatrix.Get(); } - _cameraValues[HdShaderTokens->worldToViewMatrix] = + _cameraValues[HdxCameraTokens->worldToViewMatrix] = VtValue(worldToViewMatrix); - _cameraValues[HdShaderTokens->worldToViewInverseMatrix] = + _cameraValues[HdxCameraTokens->worldToViewInverseMatrix] = VtValue(worldToViewInverseMatrix); - _cameraValues[HdShaderTokens->projectionMatrix] = + _cameraValues[HdxCameraTokens->projectionMatrix] = VtValue(projectionMatrix); } - if (bits & HdChangeTracker::DirtyWindowPolicy) { - VtValue vWindowPolicy = _delegate->Get(_id, HdTokens->windowPolicy); + if (bits & DirtyWindowPolicy) { + VtValue vWindowPolicy = delegate->Get(id, HdxCameraTokens->windowPolicy); if (vWindowPolicy.IsHolding()) { - _cameraValues[HdTokens->windowPolicy] = + _cameraValues[HdxCameraTokens->windowPolicy] = vWindowPolicy.UncheckedGet(); } } - if (bits & HdChangeTracker::DirtyClipPlanes) { - _cameraValues[HdTokens->clipPlanes] = _delegate->GetClipPlanes(_id); + if (bits & DirtyClipPlanes) { + _cameraValues[HdxCameraTokens->clipPlanes] = delegate->GetClipPlanes(id); } } +/* virtual */ VtValue -HdCamera::Get(TfToken const &name) +HdxCamera::Get(TfToken const &name) const { VtValue r; TF_VERIFY(TfMapLookup(_cameraValues, name, &r), - "HdCamera - Unknown %s\n", + "HdxCamera - Unknown %s\n", name.GetText()); return r; diff --git a/pxr/imaging/lib/hdx/camera.h b/pxr/imaging/lib/hdx/camera.h new file mode 100644 index 0000000000..dee9404768 --- /dev/null +++ b/pxr/imaging/lib/hdx/camera.h @@ -0,0 +1,82 @@ +// +// 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 HDX_CAMERA_H +#define HDX_CAMERA_H + +#include "pxr/imaging/hd/version.h" +#include "pxr/imaging/hd/sprim.h" + +#include "pxr/usd/sdf/path.h" +#include "pxr/base/tf/hashmap.h" +#include "pxr/base/tf/staticTokens.h" +#include "pxr/base/vt/dictionary.h" + +#include + +#define HDX_CAMERA_TOKENS \ + (clipPlanes) \ + (cameraFrustum) \ + (worldToViewMatrix) \ + (worldToViewInverseMatrix) \ + (projectionMatrix) \ + (windowPolicy) + +TF_DECLARE_PUBLIC_TOKENS(HdxCameraTokens, HDX_CAMERA_TOKENS); + +class HdSceneDelegate; +typedef boost::shared_ptr HdxCameraSharedPtr; + +/// \class HdxCamera +/// +/// A camera model, used in conjunction with HdRenderPass. +/// +class HdxCamera : public HdSprim { +public: + typedef std::vector ClipPlanesVector; + + HdxCamera(HdSceneDelegate* delegate, SdfPath const & id); + ~HdxCamera(); // note: not virtual (for now) + + // change tracking for HdxLight + enum DirtyBits { + Clean = 0, + DirtyParams = 1 << 0, + DirtyWindowPolicy = 1 << 1, + DirtyClipPlanes = 1 << 2, + AllDirty = (DirtyParams + |DirtyWindowPolicy + |DirtyClipPlanes) + }; + + /// Synchronizes state from the delegate to this object. + virtual void Sync(); + + /// Accessor for tasks to get the parameters cached in this object. + virtual VtValue Get(TfToken const &token) const; + +private: + TfHashMap _cameraValues; +}; + +#endif //HDX_CAMERA_H diff --git a/pxr/imaging/lib/hdx/drawTargetTask.cpp b/pxr/imaging/lib/hdx/drawTargetTask.cpp index b6633f37ce..f7b562994c 100644 --- a/pxr/imaging/lib/hdx/drawTargetTask.cpp +++ b/pxr/imaging/lib/hdx/drawTargetTask.cpp @@ -23,15 +23,16 @@ // #include "pxr/imaging/glf/glew.h" +#include "pxr/imaging/hdx/camera.h" #include "pxr/imaging/hdx/drawTargetTask.h" #include "pxr/imaging/hdx/simpleLightingShader.h" #include "pxr/imaging/hdx/tokens.h" #include "pxr/imaging/hdx/debugCodes.h" -#include "pxr/imaging/hd/camera.h" #include "pxr/imaging/hd/drawTarget.h" #include "pxr/imaging/hd/drawTargetRenderPass.h" #include "pxr/imaging/hd/renderPassState.h" +#include "pxr/imaging/hd/sprim.h" #include "pxr/imaging/glf/drawTarget.h" @@ -169,7 +170,7 @@ HdxDrawTargetTask::_Sync(HdTaskContext* ctx) // lighting context GlfSimpleLightingContextRefPtr lightingContext; - _GetTaskContextData(ctx, HdTokens->lightingContext, &lightingContext); + _GetTaskContextData(ctx, HdxTokens->lightingContext, &lightingContext); size_t numRenderPasses = _renderPasses.size(); for (size_t renderPassIdx = 0; @@ -185,8 +186,8 @@ HdxDrawTargetTask::_Sync(HdTaskContext* ctx) // XXX: Need to detect when camera changes and only update if // needed - HdCameraSharedPtr camera - = GetDelegate()->GetRenderIndex().GetCamera(cameraId); + HdSprimSharedPtr camera + = GetDelegate()->GetRenderIndex().GetSprim(cameraId); if (!camera) { // Render pass should not have been added to task list. @@ -195,13 +196,13 @@ HdxDrawTargetTask::_Sync(HdTaskContext* ctx) return; } - VtValue viewMatrixVt = camera->Get(HdShaderTokens->worldToViewMatrix); - VtValue projMatrixVt = camera->Get(HdShaderTokens->projectionMatrix); + VtValue viewMatrixVt = camera->Get(HdxCameraTokens->worldToViewMatrix); + VtValue projMatrixVt = camera->Get(HdxCameraTokens->projectionMatrix); GfMatrix4d viewMatrix = viewMatrixVt.Get(); const GfMatrix4d &projMatrix = projMatrixVt.Get(); GfMatrix4d projectionMatrix = projMatrix * yflip; - const VtValue &vClipPlanes = camera->Get(HdTokens->clipPlanes); + const VtValue &vClipPlanes = camera->Get(HdxCameraTokens->clipPlanes); const HdRenderPassState::ClipPlanesVector &clipPlanes = vClipPlanes.Get(); diff --git a/pxr/imaging/lib/hdx/light.cpp b/pxr/imaging/lib/hdx/light.cpp new file mode 100644 index 0000000000..7536325f8c --- /dev/null +++ b/pxr/imaging/lib/hdx/light.cpp @@ -0,0 +1,121 @@ +// +// 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. +// +#include "pxr/imaging/hdx/light.h" + +#include "pxr/imaging/hd/perfLog.h" +#include "pxr/imaging/hd/sceneDelegate.h" +#include "pxr/imaging/hd/rprimCollection.h" + +#include "pxr/imaging/glf/simpleLight.h" +#include "pxr/base/gf/matrix4d.h" + +TF_DEFINE_PUBLIC_TOKENS(HdxLightTokens, HDX_LIGHT_TOKENS); + +HdxLight::HdxLight(HdSceneDelegate *delegate, SdfPath const &id) + : HdSprim(delegate, id) +{ +} + +HdxLight::~HdxLight() +{ +} + +/* virtual */ +void +HdxLight::Sync() +{ + HD_TRACE_FUNCTION(); + HD_MALLOC_TAG_FUNCTION(); + + SdfPath const &id = GetID(); + HdSceneDelegate *delegate = GetDelegate(); + + if (not TF_VERIFY(delegate)) { + return; + } + + // HdxLight communicates to the scene graph and caches all interesting + // values within this class. + + // later on Get() is called from TaskState (RenderPass) to perform + // aggregation/pre-computation, in order to make the shader execution + // efficient. + + HdChangeTracker& changeTracker = + delegate->GetRenderIndex().GetChangeTracker(); + HdChangeTracker::DirtyBits bits = changeTracker.GetSprimDirtyBits(id); + + // Change tracking + + // Transform + if (bits & DirtyTransform) { + VtValue transform = delegate->Get(id, HdxLightTokens->transform); + if (transform.IsHolding()) { + _params[HdxLightTokens->transform] = transform; + } else { + _params[HdxLightTokens->transform] = GfMatrix4d(1); + } + } + + // Lighting Params + if (bits & DirtyParams) { + _params[HdxLightTokens->params] = + delegate->Get(id, HdxLightTokens->params); + } + + // Shadow Params + if (bits & DirtyShadowParams) { + _params[HdxLightTokens->shadowParams] = + delegate->Get(id, HdxLightTokens->shadowParams); + } + + // Shadow Collection + if (bits & DirtyCollection) { + VtValue vtShadowCollection = + delegate->Get(id, HdxLightTokens->shadowCollection); + + // Optional + if (vtShadowCollection.IsHolding()) { + HdRprimCollection newCollection = + vtShadowCollection.UncheckedGet(); + + if (_params[HdxLightTokens->shadowCollection] != newCollection) { + _params[HdxLightTokens->shadowCollection] = newCollection; + changeTracker.MarkCollectionDirty(newCollection.GetName()); + } + + } else { + _params[HdxLightTokens->shadowCollection] = HdRprimCollection(); + } + } +} + +/* virtual */ +VtValue +HdxLight::Get(TfToken const &token) const +{ + VtValue val; + TfMapLookup(_params, token, &val); + return val; +} diff --git a/pxr/imaging/lib/hdx/light.h b/pxr/imaging/lib/hdx/light.h new file mode 100644 index 0000000000..593b78ab41 --- /dev/null +++ b/pxr/imaging/lib/hdx/light.h @@ -0,0 +1,83 @@ +// +// 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 HDX_LIGHT_H +#define HDX_LIGHT_H + +#include "pxr/imaging/hd/version.h" +#include "pxr/imaging/hd/sprim.h" + +#include "pxr/base/tf/staticTokens.h" +#include "pxr/base/vt/dictionary.h" +#include "pxr/base/vt/value.h" + +#include + +#include + +#define HDX_LIGHT_TOKENS \ + (params) \ + (shadowCollection) \ + (shadowParams) \ + (transform) + +TF_DECLARE_PUBLIC_TOKENS(HdxLightTokens, HDX_LIGHT_TOKENS); + +class HdSceneDelegate; +typedef boost::shared_ptr HdxLightSharedPtr; +typedef std::vector HdxLightSharedPtrVector; + +/// \class HdxLight +/// +/// A light model, used in conjunction with HdRenderPass. +/// +class HdxLight : public HdSprim { +public: + HdxLight(HdSceneDelegate* delegate, SdfPath const & id); + virtual ~HdxLight(); + + // change tracking for HdxLight + enum DirtyBits { + Clean = 0, + DirtyTransform = 1 << 0, + DirtyParams = 1 << 1, + DirtyShadowParams = 1 << 2, + DirtyCollection = 1 << 3, + AllDirty = (DirtyTransform + |DirtyParams + |DirtyShadowParams + |DirtyCollection) + }; + + /// Synchronizes state from the delegate to this object. + virtual void Sync(); + + /// Accessor for tasks to get the parameters cached in this object. + virtual VtValue Get(TfToken const &token) const; + +private: + // cached states + TfHashMap _params; +}; + +#endif // HDX_LIGHT_H diff --git a/pxr/imaging/lib/hdx/renderSetupTask.cpp b/pxr/imaging/lib/hdx/renderSetupTask.cpp index b44253e334..6f9eaa985f 100644 --- a/pxr/imaging/lib/hdx/renderSetupTask.cpp +++ b/pxr/imaging/lib/hdx/renderSetupTask.cpp @@ -22,16 +22,17 @@ // language governing permissions and limitations under the Apache License. // #include "pxr/imaging/hdx/renderSetupTask.h" +#include "pxr/imaging/hdx/camera.h" #include "pxr/imaging/hdx/package.h" #include "pxr/imaging/hdx/tokens.h" #include "pxr/imaging/hdx/debugCodes.h" -#include "pxr/imaging/hd/camera.h" #include "pxr/imaging/hd/changeTracker.h" #include "pxr/imaging/hd/renderIndex.h" #include "pxr/imaging/hd/renderPassShader.h" #include "pxr/imaging/hd/renderPassState.h" #include "pxr/imaging/hd/sceneDelegate.h" +#include "pxr/imaging/hd/sprim.h" #include "pxr/imaging/hd/surfaceShader.h" #include "pxr/imaging/cameraUtil/conformWindow.h" @@ -129,7 +130,7 @@ HdxRenderSetupTask::Sync(HdxRenderTaskParams const ¶ms) _viewport = params.viewport; - _camera = GetDelegate()->GetRenderIndex().GetCamera(params.camera); + _camera = GetDelegate()->GetRenderIndex().GetSprim(params.camera); } void @@ -140,12 +141,12 @@ HdxRenderSetupTask::SyncCamera() // XXX This code will be removed when we drop support for // storing frustum in the render index - VtValue frustumVt = _camera->Get(HdTokens->cameraFrustum); + VtValue frustumVt = _camera->Get(HdxCameraTokens->cameraFrustum); if(frustumVt.IsHolding()) { // Extract the window policy to adjust the frustum correctly - VtValue windowPolicy = _camera->Get(HdTokens->windowPolicy); + VtValue windowPolicy = _camera->Get(HdxCameraTokens->windowPolicy); if (not TF_VERIFY(windowPolicy.IsHolding())) { return; } @@ -165,14 +166,16 @@ HdxRenderSetupTask::SyncCamera() modelViewMatrix = frustum.ComputeViewMatrix();; projectionMatrix = frustum.ComputeProjectionMatrix(); } else { - VtValue modelViewMatrixVt = _camera->Get(HdShaderTokens->worldToViewMatrix); - VtValue projectionMatrixVt = _camera->Get(HdShaderTokens->projectionMatrix); + VtValue modelViewMatrixVt + = _camera->Get(HdxCameraTokens->worldToViewMatrix); + VtValue projectionMatrixVt + = _camera->Get(HdxCameraTokens->projectionMatrix); modelViewMatrix = modelViewMatrixVt.Get(); projectionMatrix = projectionMatrixVt.Get(); } - const VtValue &vClipPlanes = _camera->Get(HdTokens->clipPlanes); + const VtValue &vClipPlanes = _camera->Get(HdxCameraTokens->clipPlanes); const HdRenderPassState::ClipPlanesVector &clipPlanes = vClipPlanes.Get(); diff --git a/pxr/imaging/lib/hdx/renderSetupTask.h b/pxr/imaging/lib/hdx/renderSetupTask.h index 62680c2d08..fb8be32454 100644 --- a/pxr/imaging/lib/hdx/renderSetupTask.h +++ b/pxr/imaging/lib/hdx/renderSetupTask.h @@ -34,9 +34,9 @@ #include -typedef boost::shared_ptr HdCameraSharedPtr; typedef boost::shared_ptr HdRenderPassShaderSharedPtr; typedef boost::shared_ptr HdRenderPassStateSharedPtr; +typedef boost::shared_ptr HdSprimSharedPtr; typedef boost::shared_ptr HdxRenderSetupTaskSharedPtr; struct HdxRenderTaskParams; @@ -69,7 +69,7 @@ class HdxRenderSetupTask : public HdSceneTask HdRenderPassShaderSharedPtr _colorRenderPassShader; HdRenderPassShaderSharedPtr _idRenderPassShader; GfVec4d _viewport; - HdCameraSharedPtr _camera; + HdSprimSharedPtr _camera; }; /// \class HdxRenderTaskParams diff --git a/pxr/imaging/lib/hdx/renderTask.cpp b/pxr/imaging/lib/hdx/renderTask.cpp index 56cac9b44b..d85ff31723 100644 --- a/pxr/imaging/lib/hdx/renderTask.cpp +++ b/pxr/imaging/lib/hdx/renderTask.cpp @@ -61,7 +61,7 @@ HdxRenderTask::_Execute(HdTaskContext* ctx) // Can't use GetTaskContextData because the lightingShader // is optional. - VtValue lightingShader = (*ctx)[HdTokens->lightingShader]; + VtValue lightingShader = (*ctx)[HdxTokens->lightingShader]; // it's possible to not set lighting shader to HdRenderPassState. // Hd_DefaultLightingShader will be used in that case. diff --git a/pxr/imaging/lib/hdx/selectionTask.cpp b/pxr/imaging/lib/hdx/selectionTask.cpp index 3fe04d3797..1f99ccf8a1 100644 --- a/pxr/imaging/lib/hdx/selectionTask.cpp +++ b/pxr/imaging/lib/hdx/selectionTask.cpp @@ -28,7 +28,6 @@ #include "pxr/imaging/hdx/selectionTracker.h" #include "pxr/imaging/hdx/tokens.h" -#include "pxr/imaging/hd/camera.h" #include "pxr/imaging/hd/perfLog.h" #include "pxr/imaging/hd/renderIndex.h" #include "pxr/imaging/hd/resourceRegistry.h" diff --git a/pxr/imaging/lib/hdx/shadowTask.cpp b/pxr/imaging/lib/hdx/shadowTask.cpp index 3d1b0feeb0..0737b5332c 100644 --- a/pxr/imaging/lib/hdx/shadowTask.cpp +++ b/pxr/imaging/lib/hdx/shadowTask.cpp @@ -24,11 +24,10 @@ #include "pxr/imaging/glf/glew.h" #include "pxr/imaging/hdx/shadowTask.h" -#include "pxr/imaging/hdx/tokens.h" +#include "pxr/imaging/hdx/light.h" #include "pxr/imaging/hdx/simpleLightTask.h" +#include "pxr/imaging/hdx/tokens.h" -#include "pxr/imaging/hd/light.h" -#include "pxr/imaging/hd/camera.h" #include "pxr/imaging/hd/changeTracker.h" #include "pxr/imaging/hd/perfLog.h" #include "pxr/imaging/hd/renderIndex.h" @@ -36,6 +35,7 @@ #include "pxr/imaging/hd/renderPassState.h" #include "pxr/imaging/hd/resourceRegistry.h" #include "pxr/imaging/hd/sceneDelegate.h" +#include "pxr/imaging/hd/sprim.h" #include "pxr/imaging/hd/lightingShader.h" #include "pxr/imaging/glf/simpleLightingContext.h" @@ -65,7 +65,7 @@ HdxShadowTask::_Execute(HdTaskContext* ctx) // Extract the lighting context information from the task context GlfSimpleLightingContextRefPtr lightingContext; - if (not _GetTaskContextData(ctx, HdTokens->lightingContext, &lightingContext)) { + if (not _GetTaskContextData(ctx, HdxTokens->lightingContext, &lightingContext)) { return; } @@ -120,7 +120,7 @@ HdxShadowTask::_Sync(HdTaskContext* ctx) // Extract the lighting context information from the task context GlfSimpleLightingContextRefPtr lightingContext; - if (not _GetTaskContextData(ctx, HdTokens->lightingContext, &lightingContext)) { + if (not _GetTaskContextData(ctx, HdxTokens->lightingContext, &lightingContext)) { return; } GlfSimpleShadowArrayRefPtr const shadows = lightingContext->GetShadows(); @@ -170,12 +170,26 @@ HdxShadowTask::_Sync(HdTaskContext* ctx) // task context, we will use them to find out what // lights are dirty and if we need to update the // collection for shadows mapping - HdLightSharedPtrVector lights = - _ComputeIncludedLights( - delegate->GetRenderIndex().GetLights(), + + // XXX: This is inefficient, need to be optimized + SdfPathVector sprimPaths = delegate->GetRenderIndex().GetSprimSubtree( + SdfPath::AbsoluteRootPath()); + SdfPathVector lightPaths = + HdxSimpleLightTask::ComputeIncludedLights( + sprimPaths, params.lightIncludePaths, params.lightExcludePaths); + HdSprimSharedPtrVector lights; + TF_FOR_ALL (it, lightPaths) { + HdSprimSharedPtr const &sprim = delegate->GetRenderIndex().GetSprim(*it); + // XXX: or we could say instead of downcast, + // sprim->Has(HdxLightInterface) ? + if (boost::dynamic_pointer_cast(sprim)) { + lights.push_back(sprim); + } + } + GlfSimpleLightVector const glfLights = lightingContext->GetLights(); TF_VERIFY(lights.size() == glfLights.size()); @@ -191,8 +205,11 @@ HdxShadowTask::_Sync(HdTaskContext* ctx) } // Extract the collection from the HD light + VtValue vtShadowCollection = + lights[lightId]->Get(HdxLightTokens->shadowCollection); const HdRprimCollection &col = - lights[lightId]->GetShadowCollection(); + vtShadowCollection.IsHolding() ? + vtShadowCollection.Get() : HdRprimCollection(); // Creates a pass with the right geometry that will be // use during Execute phase to draw the maps diff --git a/pxr/imaging/lib/hdx/simpleLightBypassTask.cpp b/pxr/imaging/lib/hdx/simpleLightBypassTask.cpp index 0e322051bf..431441bd7e 100644 --- a/pxr/imaging/lib/hdx/simpleLightBypassTask.cpp +++ b/pxr/imaging/lib/hdx/simpleLightBypassTask.cpp @@ -26,10 +26,10 @@ #include "pxr/imaging/hdx/simpleLightingShader.h" #include "pxr/imaging/hdx/tokens.h" -#include "pxr/imaging/hd/camera.h" #include "pxr/imaging/hd/perfLog.h" #include "pxr/imaging/hd/renderIndex.h" #include "pxr/imaging/hd/sceneDelegate.h" +#include "pxr/imaging/hd/sprim.h" // -------------------------------------------------------------------------- // @@ -62,7 +62,7 @@ HdxSimpleLightBypassTask::_Sync(HdTaskContext* ctx) } _simpleLightingContext = params.simpleLightingContext; - _camera = GetDelegate()->GetRenderIndex().GetCamera(params.cameraPath); + _camera = GetDelegate()->GetRenderIndex().GetSprim(params.cameraPath); } if (_simpleLightingContext) { @@ -92,8 +92,8 @@ HdxSimpleLightBypassTask::_Sync(HdTaskContext* ctx) // Done at end, because the lighting context can be changed above. // Also we want the context in the shader as it's only a partial copy // of the context we own. - (*ctx)[HdTokens->lightingShader] = boost::dynamic_pointer_cast(_lightingShader); - (*ctx)[HdTokens->lightingContext] = _lightingShader->GetLightingContext(); + (*ctx)[HdxTokens->lightingShader] = boost::dynamic_pointer_cast(_lightingShader); + (*ctx)[HdxTokens->lightingContext] = _lightingShader->GetLightingContext(); } diff --git a/pxr/imaging/lib/hdx/simpleLightBypassTask.h b/pxr/imaging/lib/hdx/simpleLightBypassTask.h index 9f0987c782..f8e76057c3 100644 --- a/pxr/imaging/lib/hdx/simpleLightBypassTask.h +++ b/pxr/imaging/lib/hdx/simpleLightBypassTask.h @@ -58,7 +58,7 @@ class HdxSimpleLightBypassTask : public HdSceneTask { virtual void _Sync(HdTaskContext* ctx); private: - HdCameraSharedPtr _camera; + HdSprimSharedPtr _camera; HdxSimpleLightingShaderSharedPtr _lightingShader; GlfSimpleLightingContextRefPtr _simpleLightingContext; diff --git a/pxr/imaging/lib/hdx/simpleLightTask.cpp b/pxr/imaging/lib/hdx/simpleLightTask.cpp index 12ef948c2d..becd037265 100644 --- a/pxr/imaging/lib/hdx/simpleLightTask.cpp +++ b/pxr/imaging/lib/hdx/simpleLightTask.cpp @@ -24,12 +24,12 @@ #include "pxr/imaging/glf/glew.h" #include "pxr/imaging/hdx/simpleLightTask.h" -#include "pxr/imaging/hdx/tokens.h" -#include "pxr/imaging/hdx/simpleLightingShader.h" +#include "pxr/imaging/hdx/camera.h" +#include "pxr/imaging/hdx/light.h" #include "pxr/imaging/hdx/shadowMatrixComputation.h" +#include "pxr/imaging/hdx/simpleLightingShader.h" +#include "pxr/imaging/hdx/tokens.h" -#include "pxr/imaging/hd/camera.h" -#include "pxr/imaging/hd/light.h" #include "pxr/imaging/hd/perfLog.h" #include "pxr/imaging/hd/renderIndex.h" #include "pxr/imaging/hd/renderPass.h" @@ -76,7 +76,7 @@ HdxSimpleLightTask::_Sync(HdTaskContext* ctx) // Store the lighting context in the task context // so later on other tasks can use this information // draw shadows or other purposes - (*ctx)[HdTokens->lightingShader] = + (*ctx)[HdxTokens->lightingShader] = boost::dynamic_pointer_cast(_lightingShader); _TaskDirtyState dirtyState; @@ -99,10 +99,25 @@ HdxSimpleLightTask::_Sync(HdTaskContext* ctx) } HdSceneDelegate* delegate = GetDelegate(); - _camera = delegate->GetRenderIndex().GetCamera(params.cameraPath); - _lights = _ComputeIncludedLights(delegate->GetRenderIndex().GetLights(), - params.lightIncludePaths, - params.lightExcludePaths); + _camera = delegate->GetRenderIndex().GetSprim(params.cameraPath); + + // XXX: This is inefficient, need to be optimized + SdfPathVector sprimPaths = delegate->GetRenderIndex().GetSprimSubtree( + SdfPath::AbsoluteRootPath()); + SdfPathVector lights = ComputeIncludedLights(sprimPaths, + params.lightIncludePaths, + params.lightExcludePaths); + _lights.clear(); + _lights.reserve(lights.size()); + TF_FOR_ALL (it, lights) { + HdSprimSharedPtr const &sprim = delegate->GetRenderIndex().GetSprim(*it); + // XXX: or we could say instead of downcast, + // if sprim->Has(HdxLightInterface) ? + if (boost::dynamic_pointer_cast(sprim)) { + _lights.push_back(sprim); + } + } + _enableShadows = params.enableShadows; // XXX: compatibility hack for passing some unit tests until we have @@ -124,7 +139,7 @@ HdxSimpleLightTask::_Sync(HdTaskContext* ctx) } // Place lighting context in task context - (*ctx)[HdTokens->lightingContext] = lightingContext; + (*ctx)[HdxTokens->lightingContext] = lightingContext; VtValue modelViewMatrix = _camera->Get(HdShaderTokens->worldToViewMatrix); TF_VERIFY(modelViewMatrix.IsHolding()); @@ -159,7 +174,14 @@ HdxSimpleLightTask::_Sync(HdTaskContext* ctx) for (size_t lightId = 0; lightId < numLights; ++lightId) { // Take a copy of the simple light into our temporary array and // update it with viewer-dependant values. - _glfSimpleLights.push_back(_lights[lightId]->GetParams()); + VtValue vtLightParams = _lights[lightId]->Get(HdxLightTokens->params); + + if (TF_VERIFY(vtLightParams.IsHolding())) { + _glfSimpleLights.push_back( + vtLightParams.UncheckedGet()); + } else { + _glfSimpleLights.push_back(GlfSimpleLight()); + } // Get a reference to the light, so we can patch it. GlfSimpleLight &glfl = _glfSimpleLights.back(); @@ -172,7 +194,9 @@ HdxSimpleLightTask::_Sync(HdTaskContext* ctx) // the position and spot direction to the right // space if (glfl.IsCameraSpaceLight()) { - const GfMatrix4d &lightXform = _lights[lightId]->GetTransform(); + VtValue vtXform = _lights[lightId]->Get(HdxLightTokens->transform); + const GfMatrix4d &lightXform = + vtXform.IsHolding() ? vtXform.Get() : GfMatrix4d(1); GfVec4f lightPos(lightXform.GetRow(2)); lightPos[3] = 0.0f; @@ -180,8 +204,8 @@ HdxSimpleLightTask::_Sync(HdTaskContext* ctx) glfl.SetPosition(lightPos * invCamXform); glfl.SetSpotDirection(GfVec3f(invCamXform.TransformDir(lightDir))); } - - VtValue vLightShadowParams = _lights[lightId]->GetShadowParams(); + + VtValue vLightShadowParams = _lights[lightId]->Get(HdxLightTokens->shadowParams); TF_VERIFY(vLightShadowParams.IsHolding()); HdxShadowParams lightShadowParams = vLightShadowParams.GetWithDefault(HdxShadowParams()); @@ -198,7 +222,7 @@ HdxSimpleLightTask::_Sync(HdTaskContext* ctx) // to calculate shadows if (glfl.HasShadow()) { // Extract the window policy to adjust the frustum correctly - VtValue windowPolicy = _camera->Get(HdTokens->windowPolicy); + VtValue windowPolicy = _camera->Get(HdxCameraTokens->windowPolicy); if (not TF_VERIFY(windowPolicy.IsHolding())) { return; } @@ -241,7 +265,7 @@ HdxSimpleLightTask::_Sync(HdTaskContext* ctx) continue; } - VtValue vLightShadowParams = _lights[lightId]->GetShadowParams(); + VtValue vLightShadowParams = _lights[lightId]->Get(HdxLightTokens->shadowParams); TF_VERIFY(vLightShadowParams.IsHolding()); HdxShadowParams lightShadowParams = vLightShadowParams.GetWithDefault( @@ -258,25 +282,26 @@ HdxSimpleLightTask::_Sync(HdTaskContext* ctx) lightingContext->SetShadows(_shadows); } -HdLightSharedPtrVector -_ComputeIncludedLights( - HdLightSharedPtrVector const & allLights, +/* static */ +SdfPathVector +HdxSimpleLightTask::ComputeIncludedLights( + SdfPathVector const & allLightPaths, SdfPathVector const & includedPaths, SdfPathVector const & excludedPaths) { HD_TRACE_FUNCTION(); - HdLightSharedPtrVector result; + SdfPathVector result; // In practice, the include and exclude containers will either // be empty or have just one element. So, the complexity of this method // should be dominated by the number of lights, which should also // be small. The TRACE_FUNCTION above will help catch when this is // no longer the case. - TF_FOR_ALL(lightIt, allLights) { + TF_FOR_ALL(lightPathIt, allLightPaths) { bool included = false; TF_FOR_ALL(includePathIt, includedPaths) { - if ((*lightIt)->GetID().HasPrefix(*includePathIt)) { + if (lightPathIt->HasPrefix(*includePathIt)) { included = true; break; } @@ -285,13 +310,13 @@ _ComputeIncludedLights( continue; } TF_FOR_ALL(excludePathIt, excludedPaths) { - if ((*lightIt)->GetID().HasPrefix(*excludePathIt)) { + if (lightPathIt->HasPrefix(*excludePathIt)) { included = false; break; } } if (included) { - result.push_back(*lightIt); + result.push_back(*lightPathIt); } } diff --git a/pxr/imaging/lib/hdx/simpleLightTask.h b/pxr/imaging/lib/hdx/simpleLightTask.h index 9e3244f85f..8886a47ccc 100644 --- a/pxr/imaging/lib/hdx/simpleLightTask.h +++ b/pxr/imaging/lib/hdx/simpleLightTask.h @@ -25,15 +25,17 @@ #define HDX_SIMPLE_LIGHT_TASK_H #include "pxr/imaging/hdx/version.h" +#include "pxr/imaging/hdx/light.h" + #include "pxr/imaging/hd/changeTracker.h" -#include "pxr/imaging/hd/light.h" #include "pxr/imaging/hd/rprimCollection.h" #include "pxr/imaging/hd/task.h" +#include "pxr/imaging/glf/simpleLight.h" +#include "pxr/imaging/glf/simpleMaterial.h" + #include "pxr/base/gf/matrix4d.h" #include "pxr/base/gf/vec3f.h" -#include "pxr/imaging/glf/simpleMaterial.h" -#include "pxr/imaging/glf/simpleLight.h" #include @@ -51,6 +53,11 @@ class HdxSimpleLightTask : public HdSceneTask { public: HdxSimpleLightTask(HdSceneDelegate* delegate, SdfPath const& id); + static SdfPathVector ComputeIncludedLights( + SdfPathVector const & allLightPaths, + SdfPathVector const & includedPaths, + SdfPathVector const & excludedPaths); + protected: /// Execute render pass task virtual void _Execute(HdTaskContext* ctx); @@ -60,8 +67,8 @@ class HdxSimpleLightTask : public HdSceneTask { private: // Should be weak ptrs - HdCameraSharedPtr _camera; - HdLightSharedPtrVector _lights; + HdSprimSharedPtr _camera; + HdSprimSharedPtrVector _lights; HdxSimpleLightingShaderSharedPtr _lightingShader; int _collectionVersion; bool _enableShadows; @@ -78,13 +85,6 @@ class HdxSimpleLightTask : public HdSceneTask { GlfSimpleLightVector _glfSimpleLights; }; -HdLightSharedPtrVector -_ComputeIncludedLights( - HdLightSharedPtrVector const & allLights, - SdfPathVector const & includedPaths, - SdfPathVector const & excludedPaths); - - struct HdxSimpleLightTaskParams { HdxSimpleLightTaskParams() diff --git a/pxr/imaging/lib/hdx/tokens.h b/pxr/imaging/lib/hdx/tokens.h index 70c33ac09f..1685c650ea 100644 --- a/pxr/imaging/lib/hdx/tokens.h +++ b/pxr/imaging/lib/hdx/tokens.h @@ -30,6 +30,8 @@ #define HDX_TOKENS \ (hdxSelectionBuffer) \ (imagerVersion) \ + (lightingContext) \ + (lightingShader) \ (renderPassState) \ (renderIndexVersion) \ (selection) \ diff --git a/pxr/imaging/lib/hdx/unitTestDelegate.cpp b/pxr/imaging/lib/hdx/unitTestDelegate.cpp index 46ec4b0336..cd87f7b408 100644 --- a/pxr/imaging/lib/hdx/unitTestDelegate.cpp +++ b/pxr/imaging/lib/hdx/unitTestDelegate.cpp @@ -23,9 +23,11 @@ // #include "pxr/imaging/hdx/unitTestDelegate.h" -#include "pxr/imaging/hd/camera.h" #include "pxr/imaging/hd/engine.h" #include "pxr/imaging/hd/mesh.h" +#include "pxr/imaging/hd/sprim.h" +#include "pxr/imaging/hdx/camera.h" +#include "pxr/imaging/hdx/light.h" #include "pxr/imaging/hdx/renderTask.h" #include "pxr/imaging/hdx/selectionTask.h" #include "pxr/imaging/hdx/simpleLightTask.h" @@ -117,7 +119,7 @@ Hdx_UnitTestDelegate::Hdx_UnitTestDelegate(HdRenderIndexSharedPtr const &index) { // add camera _cameraId = SdfPath("/camera"); - GetRenderIndex().InsertCamera(this, _cameraId); + GetRenderIndex().InsertSprim(this, _cameraId); GfFrustum frustum; frustum.SetPosition(GfVec3d(0, 0, 3)); SetCamera(frustum.ComputeViewMatrix(), frustum.ComputeProjectionMatrix()); @@ -140,20 +142,42 @@ void Hdx_UnitTestDelegate::SetCamera(GfMatrix4d const &viewMatrix, GfMatrix4d const &projMatrix) { - _ValueCache &cache = _valueCacheMap[_cameraId]; - cache[HdTokens->cameraFrustum] = VtValue(); - cache[HdTokens->windowPolicy] = VtValue(CameraUtilFit); - cache[HdShaderTokens->worldToViewMatrix] = VtValue(viewMatrix); - cache[HdShaderTokens->projectionMatrix] = VtValue(projMatrix); + SetCamera(_cameraId, viewMatrix, projMatrix); +} + +void +Hdx_UnitTestDelegate::SetCamera(SdfPath const &cameraId, + GfMatrix4d const &viewMatrix, + GfMatrix4d const &projMatrix) +{ + _ValueCache &cache = _valueCacheMap[cameraId]; + cache[HdxCameraTokens->cameraFrustum] = VtValue(); + cache[HdxCameraTokens->windowPolicy] = VtValue(CameraUtilFit); + cache[HdxCameraTokens->worldToViewMatrix] = VtValue(viewMatrix); + cache[HdxCameraTokens->projectionMatrix] = VtValue(projMatrix); + + GetRenderIndex().GetChangeTracker().MarkSprimDirty(cameraId, + HdxCamera::AllDirty); +} + +void +Hdx_UnitTestDelegate::AddCamera(SdfPath const &id) +{ + // add a camera + GetRenderIndex().InsertSprim(this, id); + _ValueCache &cache = _valueCacheMap[id]; - GetRenderIndex().GetChangeTracker().MarkCameraDirty(_cameraId); + cache[HdxCameraTokens->cameraFrustum] = VtValue(); + cache[HdxCameraTokens->windowPolicy] = VtValue(CameraUtilFit); + cache[HdxCameraTokens->worldToViewMatrix] = VtValue(GfMatrix4d(1)); + cache[HdxCameraTokens->projectionMatrix] = VtValue(GfMatrix4d(1)); } void Hdx_UnitTestDelegate::AddLight(SdfPath const &id, GlfSimpleLight const &light) { // add light - GetRenderIndex().InsertLight(this, id); + GetRenderIndex().InsertSprim(this, id); _ValueCache &cache = _valueCacheMap[id]; HdxShadowParams shadowParams; @@ -164,12 +188,20 @@ Hdx_UnitTestDelegate::AddLight(SdfPath const &id, GlfSimpleLight const &light) shadowParams.bias = -0.001; shadowParams.blur = 0.1; - cache[HdTokens->lightParams] = light; - cache[HdTokens->lightShadowParams] = shadowParams; - cache[HdTokens->lightShadowCollection] + cache[HdxLightTokens->params] = light; + cache[HdxLightTokens->shadowParams] = shadowParams; + cache[HdxLightTokens->shadowCollection] = HdRprimCollection(HdTokens->geometry, HdTokens->refined); } +void +Hdx_UnitTestDelegate::SetLight(SdfPath const &id, TfToken const &key, + VtValue value) +{ + _ValueCache &cache = _valueCacheMap[id]; + cache[key] = value; +} + void Hdx_UnitTestDelegate::AddRenderTask(SdfPath const &id) { diff --git a/pxr/imaging/lib/hdx/unitTestDelegate.h b/pxr/imaging/lib/hdx/unitTestDelegate.h index 6644b05471..e346474617 100644 --- a/pxr/imaging/lib/hdx/unitTestDelegate.h +++ b/pxr/imaging/lib/hdx/unitTestDelegate.h @@ -52,9 +52,12 @@ class Hdx_UnitTestDelegate : public HdSceneDelegate // camera void SetCamera(GfMatrix4d const &viewMatrix, GfMatrix4d const &projMatrix); + void SetCamera(SdfPath const &id, GfMatrix4d const &viewMatrix, GfMatrix4d const &projMatrix); + void AddCamera(SdfPath const &id); // light void AddLight(SdfPath const &id, GlfSimpleLight const &light); + void SetLight(SdfPath const &id, TfToken const &key, VtValue value); // tasks void AddRenderTask(SdfPath const &id); diff --git a/pxr/imaging/lib/hdx/version.h b/pxr/imaging/lib/hdx/version.h index 5cf965d2d2..f4956448dc 100644 --- a/pxr/imaging/lib/hdx/version.h +++ b/pxr/imaging/lib/hdx/version.h @@ -26,6 +26,7 @@ // 1 -> 2 : split HdxRenderSetupTask out of HdxRenderTask // 2 -> 3 : move simpleLightingShader to Hdx. -#define HDX_API 3 +// 3 -> 4: move camera and light to Hdx. +#define HDX_API 4 #endif // HDX_VERSION_H diff --git a/pxr/usdImaging/lib/usdImaging/defaultTaskDelegate.cpp b/pxr/usdImaging/lib/usdImaging/defaultTaskDelegate.cpp index 73b180b4e9..abbe654a6f 100644 --- a/pxr/usdImaging/lib/usdImaging/defaultTaskDelegate.cpp +++ b/pxr/usdImaging/lib/usdImaging/defaultTaskDelegate.cpp @@ -24,10 +24,10 @@ #include "pxr/usdImaging/usdImaging/defaultTaskDelegate.h" #include "pxr/imaging/hd/version.h" -#include "pxr/imaging/hd/camera.h" -#include "pxr/imaging/hd/light.h" #include "pxr/imaging/hd/tokens.h" +#include "pxr/imaging/hdx/camera.h" +#include "pxr/imaging/hdx/light.h" #include "pxr/imaging/hdx/renderTask.h" #include "pxr/imaging/hdx/selectionTask.h" #include "pxr/imaging/hdx/simpleLightTask.h" @@ -90,12 +90,12 @@ UsdImaging_DefaultTaskDelegate::UsdImaging_DefaultTaskDelegate( // camera { - renderIndex.InsertCamera(this, _cameraId); + renderIndex.InsertSprim(this, _cameraId); _ValueCache &cache = _valueCacheMap[_cameraId]; - cache[HdShaderTokens->worldToViewMatrix] = VtValue(GfMatrix4d(1)); - cache[HdShaderTokens->projectionMatrix] = VtValue(GfMatrix4d(1)); - cache[HdTokens->cameraFrustum] = VtValue(); // we don't use GfFrustum. - cache[HdTokens->windowPolicy] = VtValue(); // we don't use window policy. + cache[HdxCameraTokens->worldToViewMatrix] = VtValue(GfMatrix4d(1)); + cache[HdxCameraTokens->projectionMatrix] = VtValue(GfMatrix4d(1)); + cache[HdxCameraTokens->cameraFrustum] = VtValue(); // we don't use GfFrustum. + cache[HdxCameraTokens->windowPolicy] = VtValue(); // we don't use window policy. } // selection task @@ -152,7 +152,7 @@ UsdImaging_DefaultTaskDelegate::~UsdImaging_DefaultTaskDelegate() { // remove the render graph entities from the renderIndex HdRenderIndex &renderIndex = GetRenderIndex(); - renderIndex.RemoveCamera(_cameraId); + renderIndex.RemoveSprim(_cameraId); renderIndex.RemoveTask(_selectionTaskId); renderIndex.RemoveTask(_simpleLightTaskId); renderIndex.RemoveTask(_simpleLightBypassTaskId); @@ -160,7 +160,7 @@ UsdImaging_DefaultTaskDelegate::~UsdImaging_DefaultTaskDelegate() renderIndex.RemoveTask(_idRenderTaskId); TF_FOR_ALL (id, _lightIds) { - renderIndex.RemoveLight(*id); + renderIndex.RemoveSprim(*id); } } @@ -386,8 +386,8 @@ UsdImaging_DefaultTaskDelegate::_UpdateRenderParams( } if (renderParams.clipPlanes != oldRenderParams.clipPlanes) { - GetRenderIndex().GetChangeTracker().MarkCameraDirty( - _cameraId, HdChangeTracker::DirtyClipPlanes); + GetRenderIndex().GetChangeTracker().MarkSprimDirty( + _cameraId, HdxCamera::DirtyClipPlanes); } @@ -417,12 +417,12 @@ UsdImaging_DefaultTaskDelegate::SetLightingState( (int)_lightIds.size())); _lightIds.push_back(lightId); - GetRenderIndex().InsertLight(this, lightId); + GetRenderIndex().InsertSprim(this, lightId); hasNumLightsChanged = true; } // Remove unused light Ids from HdRenderIndex while (_lightIds.size() > lights.size()) { - GetRenderIndex().RemoveLight(_lightIds.back()); + GetRenderIndex().RemoveSprim(_lightIds.back()); _lightIds.pop_back(); hasNumLightsChanged = true; } @@ -431,17 +431,17 @@ UsdImaging_DefaultTaskDelegate::SetLightingState( for (size_t i = 0; i < lights.size(); ++i) { _ValueCache &cache = _valueCacheMap[_lightIds[i]]; // store GlfSimpleLight directly. - cache[HdTokens->lightParams] = VtValue(lights[i]); - cache[HdTokens->lightTransform] = VtValue(); - cache[HdTokens->lightShadowParams] = VtValue(HdxShadowParams()); - cache[HdTokens->lightShadowCollection] = VtValue(); + cache[HdxLightTokens->params] = VtValue(lights[i]); + cache[HdxLightTokens->transform] = VtValue(); + cache[HdxLightTokens->shadowParams] = VtValue(HdxShadowParams()); + cache[HdxLightTokens->shadowCollection] = VtValue(); // Only mark as dirty the parameters to avoid unnecessary invalidation // specially marking as dirty lightShadowCollection will trigger // a collection dirty on geometry and we don't want that to happen // always - GetRenderIndex().GetChangeTracker().MarkLightDirty( - _lightIds[i], HdChangeTracker::DirtyParams); + GetRenderIndex().GetChangeTracker().MarkSprimDirty( + _lightIds[i], HdxLight::DirtyParams); } // sadly the material also comes from lighting context right now... @@ -488,13 +488,14 @@ UsdImaging_DefaultTaskDelegate::SetCameraState( { // cache the camera matrices _ValueCache &cache = _valueCacheMap[_cameraId]; - cache[HdShaderTokens->worldToViewMatrix] = VtValue(viewMatrix); - cache[HdShaderTokens->projectionMatrix] = VtValue(projectionMatrix); - cache[HdTokens->cameraFrustum] = VtValue(); // we don't use GfFrustum. - cache[HdTokens->windowPolicy] = VtValue(); // we don't use window policy. + cache[HdxCameraTokens->worldToViewMatrix] = VtValue(viewMatrix); + cache[HdxCameraTokens->projectionMatrix] = VtValue(projectionMatrix); + cache[HdxCameraTokens->cameraFrustum] = VtValue(); // we don't use GfFrustum. + cache[HdxCameraTokens->windowPolicy] = VtValue(); // we don't use window policy. // invalidate the camera to be synced - GetRenderIndex().GetChangeTracker().MarkCameraDirty(_cameraId); + GetRenderIndex().GetChangeTracker().MarkSprimDirty(_cameraId, + HdxCamera::AllDirty); if (_viewport != viewport) { // viewport is also read by HdxRenderTaskParam. invalidate it. diff --git a/pxr/usdImaging/lib/usdImaging/defaultTaskDelegate.h b/pxr/usdImaging/lib/usdImaging/defaultTaskDelegate.h index 76584b0133..644c35c21a 100644 --- a/pxr/usdImaging/lib/usdImaging/defaultTaskDelegate.h +++ b/pxr/usdImaging/lib/usdImaging/defaultTaskDelegate.h @@ -61,7 +61,7 @@ class UsdImaging_DefaultTaskDelegate : public UsdImagingTaskDelegate { // bypasses the lighting context down to HdxRenderTask (transitional method) void SetBypassedLightingState(const GlfSimpleLightingContextPtr &src); - // set the camera matrices for the HdCamera injected in the render graph + // set the camera matrices for the HdxCamera injected in the render graph virtual void SetCameraState(const GfMatrix4d& viewMatrix, const GfMatrix4d& projectionMatrix, const GfVec4d& viewport); diff --git a/third_party/maya/lib/pxrUsdMayaGL/batchRenderer.cpp b/third_party/maya/lib/pxrUsdMayaGL/batchRenderer.cpp index 16e255b9f5..72a704ff62 100644 --- a/third_party/maya/lib/pxrUsdMayaGL/batchRenderer.cpp +++ b/third_party/maya/lib/pxrUsdMayaGL/batchRenderer.cpp @@ -26,8 +26,15 @@ #include "pxr/usd/sdf/types.h" #include "pxr/imaging/glf/glew.h" + +#include "pxr/imaging/hd/version.h" +#if defined(HD_API) && HD_API > 25 +#include "pxr/imaging/hdx/camera.h" +#include "pxr/imaging/hdx/light.h" +#else #include "pxr/imaging/hd/camera.h" #include "pxr/imaging/hd/light.h" +#endif #include "pxr/imaging/hdx/renderTask.h" #include "pxr/imaging/hdx/selectionTask.h" #include "pxr/imaging/hdx/simpleLightTask.h" @@ -480,12 +487,21 @@ UsdMayaGLBatchRenderer::TaskDelegate::TaskDelegate( // camera { +#if defined(HD_API) && HD_API > 25 + renderIndex->InsertSprim(this, _cameraId); + _ValueCache &cache = _valueCacheMap[_cameraId]; + cache[HdxCameraTokens->worldToViewMatrix] = VtValue(GfMatrix4d(1)); + cache[HdxCameraTokens->projectionMatrix] = VtValue(GfMatrix4d(1)); + cache[HdxCameraTokens->cameraFrustum] = VtValue(); // we don't use GfFrustum. + cache[HdxCameraTokens->windowPolicy] = VtValue(); // we don't use window policy. +#else renderIndex->InsertCamera(this, _cameraId); _ValueCache &cache = _valueCacheMap[_cameraId]; cache[HdShaderTokens->worldToViewMatrix] = VtValue(GfMatrix4d(1)); cache[HdShaderTokens->projectionMatrix] = VtValue(GfMatrix4d(1)); cache[HdTokens->cameraFrustum] = VtValue(); // we don't use GfFrustum. cache[HdTokens->windowPolicy] = VtValue(); // we don't use window policy. +#endif } // simple lighting task (for Hydra native) @@ -539,6 +555,16 @@ UsdMayaGLBatchRenderer::TaskDelegate::SetCameraState( { // cache the camera matrices _ValueCache &cache = _valueCacheMap[_cameraId]; +#if defined(HD_API) && HD_API > 25 + cache[HdxCameraTokens->worldToViewMatrix] = VtValue(viewMatrix); + cache[HdxCameraTokens->projectionMatrix] = VtValue(projectionMatrix); + cache[HdxCameraTokens->cameraFrustum] = VtValue(); // we don't use GfFrustum. + cache[HdxCameraTokens->windowPolicy] = VtValue(); // we don't use window policy. + + // invalidate the camera to be synced + GetRenderIndex().GetChangeTracker().MarkSprimDirty(_cameraId, + HdxCamera::AllDirty); +#else cache[HdShaderTokens->worldToViewMatrix] = VtValue(viewMatrix); cache[HdShaderTokens->projectionMatrix] = VtValue(projectionMatrix); cache[HdTokens->cameraFrustum] = VtValue(); // we don't use GfFrustum. @@ -546,6 +572,7 @@ UsdMayaGLBatchRenderer::TaskDelegate::SetCameraState( // invalidate the camera to be synced GetRenderIndex().GetChangeTracker().MarkCameraDirty(_cameraId); +#endif if( _viewport != viewport ) { @@ -605,13 +632,21 @@ UsdMayaGLBatchRenderer::TaskDelegate::SetLightingStateFromOpenGL(const MMatrix& (int)_lightIds.size())); _lightIds.push_back(lightId); +#if defined(HD_API) && HD_API > 25 + GetRenderIndex().InsertSprim(this, lightId); +#else GetRenderIndex().InsertLight(this, lightId); +#endif hasNumLightsChanged = true; } // Remove unused light Ids from HdRenderIndex while( _lightIds.size() > lights.size() ) { +#if defined(HD_API) && HD_API > 25 + GetRenderIndex().RemoveSprim(_lightIds.back()); +#else GetRenderIndex().RemoveLight(_lightIds.back()); +#endif _lightIds.pop_back(); hasNumLightsChanged = true; } @@ -621,6 +656,19 @@ UsdMayaGLBatchRenderer::TaskDelegate::SetLightingStateFromOpenGL(const MMatrix& { _ValueCache &cache = _valueCacheMap[_lightIds[i]]; // store GlfSimpleLight directly. +#if defined(HD_API) && HD_API > 25 + cache[HdxLightTokens->params] = VtValue(lights[i]); + cache[HdxLightTokens->transform] = VtValue(); + cache[HdxLightTokens->shadowParams] = VtValue(HdxShadowParams()); + cache[HdxLightTokens->shadowCollection] = VtValue(); + + // Only mark as dirty the parameters to avoid unnecessary invalidation + // specially marking as dirty lightShadowCollection will trigger + // a collection dirty on geometry and we don't want that to happen + // always + GetRenderIndex().GetChangeTracker().MarkSprimDirty( + _lightIds[i], HdxLight::AllDirty); +#else cache[HdTokens->lightParams] = VtValue(lights[i]); cache[HdTokens->lightTransform] = VtValue(); cache[HdTokens->lightShadowParams] = VtValue(HdxShadowParams()); @@ -632,6 +680,7 @@ UsdMayaGLBatchRenderer::TaskDelegate::SetLightingStateFromOpenGL(const MMatrix& // always GetRenderIndex().GetChangeTracker().MarkLightDirty( _lightIds[i], HdChangeTracker::DirtyParams); +#endif } // sadly the material also comes from lighting context right now... From 99e6daea9bbce35db82fe5901610949cee175a42 Mon Sep 17 00:00:00 2001 From: takahito-tejima Date: Thu, 8 Sep 2016 11:22:55 -0700 Subject: [PATCH 104/380] [Hd] a workaround of crashing glCopyBufferSubData Adding HD_ENABLE_COPY_BUFFER (default to 1) envvar to be able to avoid calling glCopyBufferSubData (and its DSA version), which apparently crashes in 361.28 when the available GPU memory is very limited. also, reduce the default VBO maximum aggregation size to 256M. (Internal change: 1653093) --- pxr/imaging/lib/hd/glUtils.cpp | 62 ++++++++++++------- pxr/imaging/lib/hd/renderContextCaps.cpp | 12 ++++ pxr/imaging/lib/hd/renderContextCaps.h | 3 + pxr/imaging/lib/hd/vboSimpleMemoryManager.cpp | 26 +++++--- 4 files changed, 72 insertions(+), 31 deletions(-) diff --git a/pxr/imaging/lib/hd/glUtils.cpp b/pxr/imaging/lib/hd/glUtils.cpp index 67c9148b30..470cdb71a9 100644 --- a/pxr/imaging/lib/hd/glUtils.cpp +++ b/pxr/imaging/lib/hd/glUtils.cpp @@ -224,32 +224,48 @@ HdGLBufferRelocator::Commit() { HdRenderContextCaps const &caps = HdRenderContextCaps::GetInstance(); - if (not caps.directStateAccessEnabled) { - glBindBuffer(GL_COPY_READ_BUFFER, _srcBuffer); - glBindBuffer(GL_COPY_WRITE_BUFFER, _dstBuffer); - } + if (caps.copyBufferEnabled) { + // glCopyBuffer + if (not caps.directStateAccessEnabled) { + glBindBuffer(GL_COPY_READ_BUFFER, _srcBuffer); + glBindBuffer(GL_COPY_WRITE_BUFFER, _dstBuffer); + } - TF_FOR_ALL (it, _queue) { - if (ARCH_LIKELY(caps.directStateAccessEnabled)) { - glNamedCopyBufferSubDataEXT(_srcBuffer, - _dstBuffer, - it->readOffset, - it->writeOffset, - it->copySize); - } else { - glCopyBufferSubData(GL_COPY_READ_BUFFER, - GL_COPY_WRITE_BUFFER, - it->readOffset, - it->writeOffset, - it->copySize); + TF_FOR_ALL (it, _queue) { + if (ARCH_LIKELY(caps.directStateAccessEnabled)) { + glNamedCopyBufferSubDataEXT(_srcBuffer, + _dstBuffer, + it->readOffset, + it->writeOffset, + it->copySize); + } else { + glCopyBufferSubData(GL_COPY_READ_BUFFER, + GL_COPY_WRITE_BUFFER, + it->readOffset, + it->writeOffset, + it->copySize); + } } - } - HD_PERF_COUNTER_ADD(HdPerfTokens->glCopyBufferSubData, - (double)_queue.size()); + HD_PERF_COUNTER_ADD(HdPerfTokens->glCopyBufferSubData, + (double)_queue.size()); - if (not caps.directStateAccessEnabled) { - glBindBuffer(GL_COPY_READ_BUFFER, 0); - glBindBuffer(GL_COPY_WRITE_BUFFER, 0); + if (not caps.directStateAccessEnabled) { + glBindBuffer(GL_COPY_READ_BUFFER, 0); + glBindBuffer(GL_COPY_WRITE_BUFFER, 0); + } + } else { + // read back to CPU and send it to GPU again + // (workaround for a driver crash) + TF_FOR_ALL (it, _queue) { + std::vector data(it->copySize); + glBindBuffer(GL_ARRAY_BUFFER, _srcBuffer); + glGetBufferSubData(GL_ARRAY_BUFFER, it->readOffset, it->copySize, + &data[0]); + glBindBuffer(GL_ARRAY_BUFFER, _dstBuffer); + glBufferSubData(GL_ARRAY_BUFFER, it->writeOffset, it->copySize, + &data[0]); + } + glBindBuffer(GL_ARRAY_BUFFER, 0); } _queue.clear(); diff --git a/pxr/imaging/lib/hd/renderContextCaps.cpp b/pxr/imaging/lib/hd/renderContextCaps.cpp index 3afa39c018..9c7cf42285 100644 --- a/pxr/imaging/lib/hd/renderContextCaps.cpp +++ b/pxr/imaging/lib/hd/renderContextCaps.cpp @@ -44,6 +44,8 @@ TF_DEFINE_ENV_SETTING(HD_ENABLE_MULTI_DRAW_INDIRECT, true, "Use GL mult draw indirect extention"); TF_DEFINE_ENV_SETTING(HD_ENABLE_DIRECT_STATE_ACCESS, true, "Use GL direct state access extention"); +TF_DEFINE_ENV_SETTING(HD_ENABLE_COPY_BUFFER, true, + "Use GL copy buffer data"); TF_DEFINE_ENV_SETTING(HD_GLSL_VERSION, 0, "GLSL version"); @@ -63,6 +65,7 @@ HdRenderContextCaps::HdRenderContextCaps() , glslVersion(400) , explicitUniformLocation(false) , shadingLanguage420pack(false) + , copyBufferEnabled(true) { } @@ -208,6 +211,11 @@ HdRenderContextCaps::_LoadCaps() shadingLanguage420pack &= (glslVersion >= 420); } + // For driver issues workaround + if (not TfGetEnvSetting(HD_ENABLE_COPY_BUFFER)) { + copyBufferEnabled = false; + } + if (TfDebug::IsEnabled(HD_RENDER_CONTEXT_CAPS)) { std::cout << "HdRenderContextCaps: \n" @@ -238,6 +246,10 @@ HdRenderContextCaps::_LoadCaps() << " NV_shader_buffer_load = " << bindlessBufferEnabled << "\n" ; + + if (not copyBufferEnabled) { + std::cout << " CopyBuffer : disabled\n"; + } } } diff --git a/pxr/imaging/lib/hd/renderContextCaps.h b/pxr/imaging/lib/hd/renderContextCaps.h index c86b04fd80..8b7a22585c 100644 --- a/pxr/imaging/lib/hd/renderContextCaps.h +++ b/pxr/imaging/lib/hd/renderContextCaps.h @@ -75,6 +75,9 @@ class HdRenderContextCaps : boost::noncopyable { bool explicitUniformLocation; // ARB_explicit_uniform_location (4.3) bool shadingLanguage420pack; // ARB_shading_language_420pack (4.2) + // workarounds for driver issues + bool copyBufferEnabled; + private: void _LoadCaps(); HdRenderContextCaps(); diff --git a/pxr/imaging/lib/hd/vboSimpleMemoryManager.cpp b/pxr/imaging/lib/hd/vboSimpleMemoryManager.cpp index cfbad91225..bbc1e2507d 100644 --- a/pxr/imaging/lib/hd/vboSimpleMemoryManager.cpp +++ b/pxr/imaging/lib/hd/vboSimpleMemoryManager.cpp @@ -238,15 +238,25 @@ HdVBOSimpleMemoryManager::_SimpleBufferArray::Reallocate( if (copySize > 0) { HD_PERF_COUNTER_INCR(HdPerfTokens->glCopyBufferSubData); - if (ARCH_LIKELY(caps.directStateAccessEnabled)) { - glNamedCopyBufferSubDataEXT(oldId, newId, 0, 0, copySize); + if (caps.copyBufferEnabled) { + if (ARCH_LIKELY(caps.directStateAccessEnabled)) { + glNamedCopyBufferSubDataEXT(oldId, newId, 0, 0, copySize); + } else { + glBindBuffer(GL_COPY_READ_BUFFER, oldId); + glBindBuffer(GL_COPY_WRITE_BUFFER, newId); + glCopyBufferSubData(GL_COPY_READ_BUFFER, + GL_COPY_WRITE_BUFFER, 0, 0, copySize); + glBindBuffer(GL_COPY_READ_BUFFER, 0); + glBindBuffer(GL_COPY_WRITE_BUFFER, 0); + } } else { - glBindBuffer(GL_COPY_READ_BUFFER, oldId); - glBindBuffer(GL_COPY_WRITE_BUFFER, newId); - glCopyBufferSubData(GL_COPY_READ_BUFFER, - GL_COPY_WRITE_BUFFER, 0, 0, copySize); - glBindBuffer(GL_COPY_READ_BUFFER, 0); - glBindBuffer(GL_COPY_WRITE_BUFFER, 0); + // driver issues workaround + std::vector data(copySize); + glBindBuffer(GL_ARRAY_BUFFER, oldId); + glGetBufferSubData(GL_ARRAY_BUFFER, 0, copySize, &data[0]); + glBindBuffer(GL_ARRAY_BUFFER, newId); + glBufferSubData(GL_ARRAY_BUFFER, 0, copySize, &data[0]); + glBindBuffer(GL_ARRAY_BUFFER, 0); } } From f1aaf771b912cd0fbe4a0d8c0409ac3904e180c5 Mon Sep 17 00:00:00 2001 From: gitamohr Date: Thu, 8 Sep 2016 11:23:24 -0700 Subject: [PATCH 105/380] tf: Use tbb::concurrent_hash_map in TfFlyweight. (Internal change: 1653111) --- pxr/base/lib/tf/flyweight.cpp | 26 +++---- pxr/base/lib/tf/flyweight.h | 132 +++++++++++++--------------------- 2 files changed, 60 insertions(+), 98 deletions(-) diff --git a/pxr/base/lib/tf/flyweight.cpp b/pxr/base/lib/tf/flyweight.cpp index 48cbce1b3d..ddfbd7acdd 100644 --- a/pxr/base/lib/tf/flyweight.cpp +++ b/pxr/base/lib/tf/flyweight.cpp @@ -23,34 +23,26 @@ // #include "pxr/base/tf/flyweight.h" -#include "pxr/base/tf/hash.h" -#include "pxr/base/tf/hashmap.h" #include #include -using std::string; -using std::make_pair; - // Flyweight pools must be globally unique across the whole system. We can't // just put static data members in the template, since there may be one instance // per shared library. Instead, the global data is all stored here, in this one // translation unit, which ensures that there will be one unique pool for each // flyweight type. -typedef TfHashMap DataHashMap; - Tf_FlyweightDataBase * -Tf_TrySetFlyweightData(string const &poolName, Tf_FlyweightDataBase *data) +Tf_TrySetFlyweightData(std::string const &poolName, Tf_FlyweightDataBase *data) { - static tbb::spin_mutex _globalDataMutex; + using std::string; + using std::make_pair; + using DataHashMap = tbb::concurrent_hash_map< + string, Tf_FlyweightDataBase *>; + static DataHashMap _globalDataMap; - tbb::spin_mutex::scoped_lock lock(_globalDataMutex); - DataHashMap::iterator i = _globalDataMap.find(poolName); - if (i != _globalDataMap.end()) - return i->second; - _globalDataMap.insert(make_pair(poolName, data)); - return data; + DataHashMap::accessor acc; + _globalDataMap.insert(acc, make_pair(poolName, data)); + return acc->second; } - - diff --git a/pxr/base/lib/tf/flyweight.h b/pxr/base/lib/tf/flyweight.h index 18bc3bdf94..009fc281d0 100644 --- a/pxr/base/lib/tf/flyweight.h +++ b/pxr/base/lib/tf/flyweight.h @@ -27,25 +27,21 @@ /// \file tf/flyweight.h /// An implementation of the "flyweight pattern". +#include "pxr/base/arch/demangle.h" #include "pxr/base/tf/diagnostic.h" #include "pxr/base/tf/mallocTag.h" -#include "pxr/base/arch/demangle.h" - -#include #include -#include -#include "pxr/base/tf/hashmap.h" - -#include +#include #include -#include +#include // Set this to 1 to enable stats. #define TF_FLYWEIGHT_STATS 0 #if TF_FLYWEIGHT_STATS +#include #define TF_FLYWEIGHT_INC_STAT(name) ++_GetData()-> name #else #define TF_FLYWEIGHT_INC_STAT(name) @@ -93,9 +89,7 @@ struct Tf_FlyweightData : public Tf_FlyweightDataBase { HashMap pool; // A pointer to the default object. - std::atomic defaultPtr; - - tbb::spin_mutex poolMutex, createDefaultMutex; + std::atomic defaultPtr; #if TF_FLYWEIGHT_STATS size_t findOrCreateCalls; @@ -153,34 +147,30 @@ Tf_TrySetFlyweightData(std::string const &poolName, Tf_FlyweightDataBase *data); /// contexts. Modifications of those member variables inside const methods /// must be made thread-safe by mutual exclusion or other means. Modifying /// those variables in non-const methods need not be guarded. -template < - class Type - , class HashFn -> -class TfFlyweight : - boost::equality_comparable > +template +class TfFlyweight { -public: - - typedef typename boost::call_traits::value_type Value; - typedef typename boost::call_traits::param_type ValueParam; - typedef typename boost::call_traits::const_reference ValueConstRef; - private: // A rep just stores an object's reference count. struct _Rep { - _Rep() : refCount(1) {} - - // std::atomic copy c'tor is deleted so implement. - _Rep(const _Rep& other) : refCount(other.refCount.load()) {} + _Rep() : refCount(0) {} + _Rep(_Rep const &other) : refCount(other.refCount.load()) {} + mutable std::atomic_size_t refCount; + }; - std::atomic refCount; + struct _TbbHashEq { + inline bool equal(T const &l, T const &r) const { + return l == r; + } + inline size_t hash(T const &val) const { + return HashFn()(val); + } }; - typedef TfHashMap _PoolHash; - typedef typename _PoolHash::iterator _PoolHashIterator; - typedef typename _PoolHash::value_type *_ElementPairPtr; + typedef tbb::concurrent_hash_map< + T, _Rep, _TbbHashEq, std::allocator > > _PoolHash; + typedef typename _PoolHash::value_type const *_ElementPairPtr; typedef Tf_FlyweightData<_PoolHash> _Data; @@ -189,36 +179,24 @@ class TfFlyweight : // there and never returns NULL. Otherwise does not add \a value to the // pool, and will return NULL if that value isn't found. static _ElementPairPtr - _FindOrCreate(ValueParam value, bool create=true) { + _FindOrCreate(T const &value, bool create=true) { TfAutoMallocTag2 tag2("Tf", "TfFlyweight::_FindOrCreate"); TfAutoMallocTag tag(__ARCH_PRETTY_FUNCTION__); _Data *data = _GetData(); - tbb::spin_mutex::scoped_lock lock(data->poolMutex); - TF_FLYWEIGHT_INC_STAT(findOrCreateCalls); _PoolHash &pool = data->pool; - - _PoolHashIterator i = pool.find(value); - if (not create) - return i != pool.end() ? &(*i) : 0; - - // If at end, insert a new entry. - if (ARCH_UNLIKELY(i == pool.end())) { - TF_FLYWEIGHT_INC_STAT(numCreated); - std::pair<_PoolHashIterator, bool> result = - pool.insert(std::make_pair( - value, _Rep())); - TF_AXIOM(result.second); - i = result.first; - } else { - // Bump ref count. - TF_FLYWEIGHT_INC_STAT(numFound); - ++i->second.refCount; + + typename _PoolHash::const_accessor acc; + if (create) { + if (pool.insert(acc, std::make_pair(value, _Rep()))) + TF_FLYWEIGHT_INC_STAT(numCreated); + ++acc->second.refCount; + return &(*acc); } - return &(*i); // guaranteed to have a valid entry here. + return pool.find(acc, value) ? &(*acc) : nullptr; } // Return an iterator with a pre-incremented reference count for the @@ -228,11 +206,7 @@ class TfFlyweight : // XXX this is (technically speaking) broken double-checked locking. _ElementPairPtr defaultPtr = data->defaultPtr; if (ARCH_UNLIKELY(not defaultPtr)) { - tbb::spin_mutex::scoped_lock lock(data->createDefaultMutex); - defaultPtr = data->defaultPtr; - if (not defaultPtr) { - data->defaultPtr = defaultPtr = _FindOrCreate(Value()); - } + data->defaultPtr = defaultPtr = _FindOrCreate(T()); } TF_FLYWEIGHT_INC_STAT(numGetDefault); ++defaultPtr->second.refCount; @@ -241,20 +215,21 @@ class TfFlyweight : static inline void _TryToErase(_ElementPairPtr ptr) { _Data *data = _GetData(); - tbb::spin_mutex::scoped_lock lock(data->poolMutex); // Try to remove \p elem from the data table. It's possible that // its refcount is greater than one, in which case we do nothing. - if (ARCH_LIKELY(--ptr->second.refCount == 0)) { - _PoolHashIterator iter = data->pool.find(ptr->first); - if (TF_VERIFY(iter != data->pool.end())) - data->pool.erase(iter); + + typename _PoolHash::accessor acc; + if (TF_VERIFY(data->pool.find(acc, ptr->first))) { + // We hold a write lock here so we can't be racing a _FindOrCreate + // caller that's not yet incremented its refcount. + if (ARCH_LIKELY(--ptr->second.refCount == 0)) + data->pool.erase(acc); } } static inline void _DumpStats() { #if TF_FLYWEIGHT_STATS _Data *data = _GetData(); - tbb::spin_mutex::scoped_lock lock(data->poolMutex); printf("================================\n"); printf("== Stats for %s\n", ArchGetDemangled(typeid(TfFlyweight)).c_str()); @@ -291,7 +266,6 @@ class TfFlyweight : static inline void _ClearStats() { #if TF_FLYWEIGHT_STATS _Data *data = _GetData(); - tbb::spin_mutex::scoped_lock lock(data->poolMutex); data->findOrCreateCalls = data->numFound = data->numCreated @@ -318,7 +292,7 @@ class TfFlyweight : } /// Construct a flyweight with \a val. - explicit TfFlyweight(ValueParam val) : _ptr(_FindOrCreate(val)) { + explicit TfFlyweight(T const &val) : _ptr(_FindOrCreate(val)) { TF_FLYWEIGHT_INC_STAT(numValueCtors); } @@ -334,7 +308,7 @@ class TfFlyweight : } /// Assign this flyweight to refer to \a val. - TfFlyweight &operator=(ValueParam val) { + TfFlyweight &operator=(T const &val) { // Saving the old rep and calling _RemoveRef after obtaining the new one // will avoid destruction in the case that the new and old reps are the // same. @@ -366,13 +340,17 @@ class TfFlyweight : return _ptr == other._ptr; } + bool operator!=(TfFlyweight const &other) const { + return !(*this == other); + } + /// Return a const reference to the object this flyweight refers to. - ValueConstRef Get() const { + T const &Get() const { return _ptr->first; } /// Implicitly convert to a const reference of the underlying value. - operator ValueConstRef() const { + operator T const &() const { return Get(); } @@ -382,8 +360,7 @@ class TfFlyweight : } /// Hash functor. - struct HashFunctor - { + struct HashFunctor { size_t operator()(const TfFlyweight &flyweight) const { return flyweight.Hash(); } @@ -395,7 +372,7 @@ class TfFlyweight : } /// Return true if \a value is a member of the flyweight pool. - static bool Contains(ValueParam value) { + static bool Contains(T const &value) { // Passing 'false' to FindOrCreate keeps it from creating an entry. return _FindOrCreate(value, false); } @@ -424,21 +401,14 @@ class TfFlyweight : return _data; } - - void _AddRef() { - _AddRef(_ptr); - } - - void _RemoveRef() { - _RemoveRef(_ptr); - } + inline void _AddRef() { _AddRef(_ptr); } + inline void _RemoveRef() { _RemoveRef(_ptr); } static inline void _AddRef(_ElementPairPtr const &ptr) { ++ptr->second.refCount; } static inline void _RemoveRef(_ElementPairPtr const &ptr) { - // This refcount check is fleeting and unreliable -- see comment in the // else clause below. if (ARCH_UNLIKELY(ptr->second.refCount == 1)) { @@ -474,7 +444,7 @@ struct TfFlyweightTotalOrderLessThan { } }; -// Specialize hash_value for TfFlyweight. +// Overload hash_value for TfFlyweight. template inline size_t hash_value(const TfFlyweight& x) From ac7f280a3c911b43436ff85ad1e54cc3d617946e Mon Sep 17 00:00:00 2001 From: pixar-oss Date: Thu, 8 Sep 2016 11:23:30 -0700 Subject: [PATCH 106/380] Cache and return the clipping planes inside UsdImaging_DefaultTaskDelegate::_UpdateRenderParams and return them in UsdImaging_DefaultTaskDelegate::GetClipPlanes() (Internal change: 1653112) --- pxr/usdImaging/lib/usdImaging/defaultTaskDelegate.cpp | 5 ++++- pxr/usdImaging/lib/usdImaging/defaultTaskDelegate.h | 2 ++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/pxr/usdImaging/lib/usdImaging/defaultTaskDelegate.cpp b/pxr/usdImaging/lib/usdImaging/defaultTaskDelegate.cpp index abbe654a6f..dba55751da 100644 --- a/pxr/usdImaging/lib/usdImaging/defaultTaskDelegate.cpp +++ b/pxr/usdImaging/lib/usdImaging/defaultTaskDelegate.cpp @@ -360,6 +360,9 @@ UsdImaging_DefaultTaskDelegate::_UpdateRenderParams( const float tinyThreshold = 0.9f; params.drawingRange = GfVec2f(tinyThreshold, -1.0f); + // Cache the clip planes. + _clipPlanes = renderParams.clipPlanes; + // note that params.rprims and params.viewport are not updated // in this function, and needed to be preserved. @@ -571,5 +574,5 @@ UsdImaging_DefaultTaskDelegate::IsConverged() const std::vector UsdImaging_DefaultTaskDelegate::GetClipPlanes(SdfPath const& cameraId) { - return _renderParams.clipPlanes; + return _clipPlanes; } diff --git a/pxr/usdImaging/lib/usdImaging/defaultTaskDelegate.h b/pxr/usdImaging/lib/usdImaging/defaultTaskDelegate.h index 644c35c21a..a2d3406334 100644 --- a/pxr/usdImaging/lib/usdImaging/defaultTaskDelegate.h +++ b/pxr/usdImaging/lib/usdImaging/defaultTaskDelegate.h @@ -129,4 +129,6 @@ class UsdImaging_DefaultTaskDelegate : public UsdImagingTaskDelegate { typedef TfHashMap _ValueCache; typedef TfHashMap _ValueCacheMap; _ValueCacheMap _valueCacheMap; + + std::vector _clipPlanes; }; From f04fa7eb44af901f63d7809c176d638f5f2387af Mon Sep 17 00:00:00 2001 From: mattyjams Date: Thu, 8 Sep 2016 11:24:36 -0700 Subject: [PATCH 107/380] export UV sets as indexed primvars (Internal change: 1653191) --- .../maya/lib/usdMaya/MayaMeshWriter.cpp | 55 +- third_party/maya/lib/usdMaya/MayaMeshWriter.h | 39 +- .../lib/usdMaya/MayaMeshWriter_PrimVars.cpp | 491 +++++------------- third_party/maya/lib/usdMaya/util.cpp | 218 ++++++++ third_party/maya/lib/usdMaya/util.h | 49 ++ 5 files changed, 440 insertions(+), 412 deletions(-) diff --git a/third_party/maya/lib/usdMaya/MayaMeshWriter.cpp b/third_party/maya/lib/usdMaya/MayaMeshWriter.cpp index 8817f91c08..b37c1a34f4 100644 --- a/third_party/maya/lib/usdMaya/MayaMeshWriter.cpp +++ b/third_party/maya/lib/usdMaya/MayaMeshWriter.cpp @@ -41,6 +41,8 @@ TF_DEFINE_PRIVATE_TOKENS(_tokens, ); +const GfVec2f MayaMeshWriter::_DefaultUV = GfVec2f(-1.0e30); + const GfVec3f MayaMeshWriter::_ShaderDefaultRGB = GfVec3f(0.5); const float MayaMeshWriter::_ShaderDefaultAlpha = 0.0; @@ -202,27 +204,42 @@ bool MayaMeshWriter::writeMeshAttrs(const UsdTimeCode &usdTime, UsdGeomMesh &pri if (getArgs().exportMeshUVs) { status = lMesh.getUVSetNames(uvSetNames); } - for (unsigned int i=0; i < uvSetNames.length(); i++) { - // Initialize the VtArray to the max possible size (facevarying) - VtArray uvValues(numFaceVertices); - TfToken interpolation=TfToken(); - // Gather UV data and interpolation into a Vec2f VtArray and try to compress if possible - if (_GetMeshUVSetData(lMesh, uvSetNames[i], &uvValues, &interpolation) == MS::kSuccess) { - - // XXX:bug 118447 - // We should be able to configure the UV map name that triggers this - // behavior, and the name to which it exports. - // The UV Set "map1" is renamed st. This is a Pixar/USD convention - TfToken setName(uvSetNames[i].asChar()); - if (setName == "map1") setName=UsdUtilsGetPrimaryUVSetName(); - - // Create the primvar and set the values - UsdGeomPrimvar uvSet = - primSchema.CreatePrimvar(setName, SdfValueTypeNames->Float2Array, interpolation); - uvSet.Set( uvValues ); // not animatable + for (unsigned int i = 0; i < uvSetNames.length(); ++i) { + VtArray uvValues; + TfToken interpolation; + VtArray assignmentIndices; + + if (not _GetMeshUVSetData(lMesh, + uvSetNames[i], + &uvValues, + &interpolation, + &assignmentIndices)) { + continue; } + + int unassignedValueIndex = -1; + PxrUsdMayaUtil::AddUnassignedUVIfNeeded(&uvValues, + &assignmentIndices, + &unassignedValueIndex, + _DefaultUV); + + // XXX:bug 118447 + // We should be able to configure the UV map name that triggers this + // behavior, and the name to which it exports. + // The UV Set "map1" is renamed st. This is a Pixar/USD convention. + TfToken setName(uvSetNames[i].asChar()); + if (setName == "map1") { + setName = UsdUtilsGetPrimaryUVSetName(); + } + + _createUVPrimVar(primSchema, + setName, + uvValues, + interpolation, + assignmentIndices, + unassignedValueIndex); } - + // == Gather ColorSets MStringArray colorSetNames; if (getArgs().exportColorSets) { diff --git a/third_party/maya/lib/usdMaya/MayaMeshWriter.h b/third_party/maya/lib/usdMaya/MayaMeshWriter.h index 56c74e4399..7d64ef87ab 100644 --- a/third_party/maya/lib/usdMaya/MayaMeshWriter.h +++ b/third_party/maya/lib/usdMaya/MayaMeshWriter.h @@ -26,11 +26,12 @@ #include "usdMaya/MayaTransformWriter.h" +#include #include +#include class UsdGeomMesh; class UsdGeomGprim; -class MString; // Writes an MFnMesh as a poly mesh OR a subd mesh @@ -53,13 +54,17 @@ class MayaMeshWriter : public MayaTransformWriter private: bool isMeshValid(); void assignSubDivTagsToUSDPrim( MFnMesh &meshFn, UsdGeomMesh &primSchema); - MStatus _GetMeshUVSetData( MFnMesh& m, MString uvSetName, - VtArray *uvArray, - TfToken *interpolation); + + bool _GetMeshUVSetData( + const MFnMesh& mesh, + const MString& uvSetName, + VtArray* uvArray, + TfToken* interpolation, + VtArray* assignmentIndices); bool _GetMeshColorSetData( MFnMesh& mesh, - MString colorSet, + const MString& colorSet, bool isDisplayColor, const VtArray& shadersRGBData, const VtArray& shadersAlphaData, @@ -71,19 +76,6 @@ class MayaMeshWriter : public MayaTransformWriter MFnMesh::MColorRepresentation* colorSetRep, bool* clamped); - static MStatus - _CompressUVs(const MFnMesh& m, - const MIntArray& uvIds, - const MFloatArray& uArray, const MFloatArray& vArray, - VtArray *uvArray, - TfToken *interpolation); - - static MStatus - _FullUVsFromSparse(const MFnMesh& m, - const MIntArray& uvCounts, const MIntArray& uvIds, - const MFloatArray& uArray, const MFloatArray& vArray, - VtArray *uvArray); - bool _createAlphaPrimVar(UsdGeomGprim &primSchema, const TfToken& name, const VtArray& data, @@ -109,6 +101,13 @@ class MayaMeshWriter : public MayaTransformWriter const int unassignedValueIndex, bool clamped); + bool _createUVPrimVar(UsdGeomGprim &primSchema, + const TfToken& name, + const VtArray& data, + const TfToken& interpolation, + const VtArray& assignmentIndices, + const int unassignedValueIndex); + /// Adds displayColor and displayOpacity primvars using the given color, /// alpha, and assignment data if the \p primSchema does not already have /// authored opinions for them. @@ -123,6 +122,10 @@ class MayaMeshWriter : public MayaTransformWriter const bool clamped, const bool authored); + /// Default value to use when collecting UVs from a UV set and a component + /// has no authored value. + static const GfVec2f _DefaultUV; + /// Default values to use when collecting colors based on shader values /// and an object or component has no assigned shader. static const GfVec3f _ShaderDefaultRGB; diff --git a/third_party/maya/lib/usdMaya/MayaMeshWriter_PrimVars.cpp b/third_party/maya/lib/usdMaya/MayaMeshWriter_PrimVars.cpp index f2c5ccf926..a28360fb0b 100644 --- a/third_party/maya/lib/usdMaya/MayaMeshWriter_PrimVars.cpp +++ b/third_party/maya/lib/usdMaya/MayaMeshWriter_PrimVars.cpp @@ -23,6 +23,8 @@ // #include "usdMaya/MayaMeshWriter.h" +#include "usdMaya/util.h" + #include "pxr/base/gf/gamma.h" #include "pxr/base/gf/math.h" #include "pxr/base/gf/transform.h" @@ -34,24 +36,60 @@ #include #include -#include - -template -struct ValueHash +bool +MayaMeshWriter::_GetMeshUVSetData( + const MFnMesh& mesh, + const MString& uvSetName, + VtArray* uvArray, + TfToken* interpolation, + VtArray* assignmentIndices) { - std::size_t operator() (const T& value) const { - return hash_value(value); + MStatus status; + + // Sanity check first to make sure this UV set even has assigned values + // before we attempt to do anything with the data. + MIntArray uvCounts, uvIds; + status = mesh.getAssignedUVs(uvCounts, uvIds, &uvSetName); + if (status != MS::kSuccess) { + return false; + } + if (uvCounts.length() == 0 or uvIds.length() == 0) { + return false; } -}; -template -struct ValuesEqual -{ - bool operator() (const T& a, const T& b) const { - return GfIsClose(a, b, 1e-9); + // We'll populate the assignment indices for every face vertex, but we'll + // only push values into the data if the face vertex has a value. All face + // vertices are initially unassigned/unauthored. + const unsigned int numFaceVertices = mesh.numFaceVertices(&status); + uvArray->clear(); + assignmentIndices->assign((size_t)numFaceVertices, -1); + *interpolation = UsdGeomTokens->faceVarying; + + MItMeshFaceVertex itFV(mesh.object()); + unsigned int fvi = 0; + for (itFV.reset(); not itFV.isDone(); itFV.next(), ++fvi) { + if (not itFV.hasUVs(uvSetName)) { + // No UVs for this faceVertex, so leave it unassigned. + continue; + } + + float2 uv; + itFV.getUV(uv, &uvSetName); + + GfVec2f value(uv[0], uv[1]); + uvArray->push_back(value); + (*assignmentIndices)[fvi] = uvArray->size() - 1; } -}; + + PxrUsdMayaUtil::MergeEquivalentIndexedValues(uvArray, + assignmentIndices); + PxrUsdMayaUtil::CompressFaceVaryingPrimvarIndices(mesh, + interpolation, + assignmentIndices); + + return true; +} // This function condenses distinct indices that point to the same color values // (the combination of RGB AND Alpha) to all point to the same index for that @@ -77,132 +115,39 @@ _MergeEquivalentColorSetValues( colorSetRGBData->size(), colorSetAlphaData->size()); } - // We maintain a map of values (color AND alpha together) to those values' - // indices in our unique value arrays (color and alpha separate). - std::unordered_map, ValuesEqual > valuesSet; - VtArray uniqueColors; - VtArray uniqueAlphas; - VtArray uniqueIndices; - - for (size_t i = 0; i < colorSetAssignmentIndices->size(); ++i) { - int index = (*colorSetAssignmentIndices)[i]; - - if (index < 0 or static_cast(index) >= numValues) { - // This is an unassigned or otherwise unknown index, so just keep it. - uniqueIndices.push_back(index); - continue; - } - - const GfVec3f color = (*colorSetRGBData)[index]; - const float alpha = (*colorSetAlphaData)[index]; - const GfVec4f value(color[0], color[1], color[2], alpha); - - int uniqueIndex = -1; - - auto inserted = valuesSet.insert( - std::pair(value, - uniqueColors.size())); - if (inserted.second) { - // This is a new value, so add it to the arrays. - uniqueColors.push_back(GfVec3f(value[0], value[1], value[2])); - uniqueAlphas.push_back(value[3]); - uniqueIndex = uniqueColors.size() - 1; - } else { - // This is an existing value, so re-use the original's index. - uniqueIndex = inserted.first->second; - } - - uniqueIndices.push_back(uniqueIndex); - } - - // If we reduced the number of values by merging, copy the results back. - if (uniqueColors.size() < numValues) { - (*colorSetRGBData) = uniqueColors; - (*colorSetAlphaData) = uniqueAlphas; - (*colorSetAssignmentIndices) = uniqueIndices; - } -} + // We first combine the separate color and alpha arrays into one GfVec4f + // array. + VtArray colorsWithAlphasData(numValues); + for (size_t i = 0; i < numValues; ++i) { + const GfVec3f color = (*colorSetRGBData)[i]; + const float alpha = (*colorSetAlphaData)[i]; -// This function tries to compress faceVarying primvar indices to uniform, -// vertex, or constant interpolation if possible. This will potentially shrink -// the indices array and will update the interpolation if any compression was -// possible. -static -void -_CompressFaceVaryingPrimvarIndices( - const MFnMesh& mesh, - TfToken *interpolation, - VtArray* assignmentIndices) -{ - if (not interpolation or - not assignmentIndices or - assignmentIndices->size() == 0) { - return; + colorsWithAlphasData[i][0] = color[0]; + colorsWithAlphasData[i][1] = color[1]; + colorsWithAlphasData[i][2] = color[2]; + colorsWithAlphasData[i][3] = alpha; } - int numPolygons = mesh.numPolygons(); - VtArray uniformAssignments; - uniformAssignments.assign((size_t)numPolygons, -2); - - int numVertices = mesh.numVertices(); - VtArray vertexAssignments; - vertexAssignments.assign((size_t)numVertices, -2); - - // We assume that the data is constant/uniform/vertex until we can - // prove otherwise that two components have differing values. - bool isConstant = true; - bool isUniform = true; - bool isVertex = true; - - MItMeshFaceVertex itFV(mesh.object()); - unsigned int fvi = 0; - for (itFV.reset(); not itFV.isDone(); itFV.next(), ++fvi) { - int faceIndex = itFV.faceId(); - int vertexIndex = itFV.vertId(); - - int assignedIndex = (*assignmentIndices)[fvi]; - - if (isConstant) { - if (assignedIndex != (*assignmentIndices)[0]) { - isConstant = false; - } - } + VtArray mergedIndices(*colorSetAssignmentIndices); + PxrUsdMayaUtil::MergeEquivalentIndexedValues(&colorsWithAlphasData, + &mergedIndices); - if (isUniform) { - if (uniformAssignments[faceIndex] < -1) { - // No value for this face yet, so store one. - uniformAssignments[faceIndex] = assignedIndex; - } else if (assignedIndex != uniformAssignments[faceIndex]) { - isUniform = false; - } - } + // If we reduced the number of values by merging, copy the results back, + // separating the values back out into colors and alphas. + const size_t newSize = colorsWithAlphasData.size(); + if (newSize < numValues) { + colorSetRGBData->resize(newSize); + colorSetAlphaData->resize(newSize); - if (isVertex) { - if (vertexAssignments[vertexIndex] < -1) { - // No value for this vertex yet, so store one. - vertexAssignments[vertexIndex] = assignedIndex; - } else if (assignedIndex != vertexAssignments[vertexIndex]) { - isVertex = false; - } - } + for (size_t i = 0; i < newSize; ++i) { + const GfVec4f colorWithAlpha = colorsWithAlphasData[i]; - if (not isConstant and not isUniform and not isVertex) { - // No compression will be possible, so stop trying. - break; + (*colorSetRGBData)[i][0] = colorWithAlpha[0]; + (*colorSetRGBData)[i][1] = colorWithAlpha[1]; + (*colorSetRGBData)[i][2] = colorWithAlpha[2]; + (*colorSetAlphaData)[i] = colorWithAlpha[3]; } - } - - if (isConstant) { - assignmentIndices->resize(1); - *interpolation = UsdGeomTokens->constant; - } else if (isUniform) { - *assignmentIndices = uniformAssignments; - *interpolation = UsdGeomTokens->uniform; - } else if(isVertex) { - *assignmentIndices = vertexAssignments; - *interpolation = UsdGeomTokens->vertex; - } else { - *interpolation = UsdGeomTokens->faceVarying; + (*colorSetAssignmentIndices) = mergedIndices; } } @@ -231,7 +176,7 @@ _LinearColorFromColorSet( /// Unauthored/unpainted values will be given the index -1. bool MayaMeshWriter::_GetMeshColorSetData( MFnMesh& mesh, - MString colorSet, + const MString& colorSet, bool isDisplayColor, const VtArray& shadersRGBData, const VtArray& shadersAlphaData, @@ -384,9 +329,9 @@ bool MayaMeshWriter::_GetMeshColorSetData( _MergeEquivalentColorSetValues(colorSetRGBData, colorSetAlphaData, colorSetAssignmentIndices); - _CompressFaceVaryingPrimvarIndices(mesh, - interpolation, - colorSetAssignmentIndices); + PxrUsdMayaUtil::CompressFaceVaryingPrimvarIndices(mesh, + interpolation, + colorSetAssignmentIndices); return true; } @@ -522,6 +467,41 @@ bool MayaMeshWriter::_createRGBAPrimVar( return true; } +bool MayaMeshWriter::_createUVPrimVar( + UsdGeomGprim &primSchema, + const TfToken& name, + const VtArray& data, + const TfToken& interpolation, + const VtArray& assignmentIndices, + const int unassignedValueIndex) +{ + unsigned int numValues = data.size(); + if (numValues == 0) { + return false; + } + + TfToken interp = interpolation; + if (numValues == 1 and interp == UsdGeomTokens->constant) { + interp = TfToken(); + } + + UsdGeomPrimvar primVar = + primSchema.CreatePrimvar(name, + SdfValueTypeNames->Float2Array, + interp); + + primVar.Set(data); + + if (not assignmentIndices.empty()) { + primVar.SetIndices(assignmentIndices); + if (unassignedValueIndex != primVar.GetUnauthoredValuesIndex()) { + primVar.SetUnauthoredValuesIndex(unassignedValueIndex); + } + } + + return true; +} + bool MayaMeshWriter::_addDisplayPrimvars( UsdGeomGprim &primSchema, const MFnMesh::MColorRepresentation colorRep, @@ -587,242 +567,3 @@ bool MayaMeshWriter::_addDisplayPrimvars( return true; } - -inline bool _IsClose(double a, double b) -{ - // This matches the results produced by numpy.allclose - static const double aTol(1.0e-8); - static const double rTol(1.0e-5); - return fabs(a - b) < (aTol + rTol * fabs(b)); -} - - -inline bool _HasZeros(const MIntArray& v) -{ - for (size_t i = 0; i < v.length(); i++) { - if (v[i] == 0) - return true; - } - - return false; -} - -inline void -_CopyUVs(const MFloatArray& uArray, const MFloatArray& vArray, - VtArray *uvArray) -{ - uvArray->clear(); - uvArray->resize(uArray.length()); - for (size_t i = 0; i < uvArray->size(); i++) { - (*uvArray)[i] = GfVec2f(uArray[i], vArray[i]); - } -} - -/* static */ -MStatus -MayaMeshWriter::_FullUVsFromSparse( - const MFnMesh& m, - const MIntArray& uvCounts, const MIntArray& uvIds, - const MFloatArray& uArray, const MFloatArray& vArray, - VtArray *uvArray -) -{ - MIntArray faceVertexCounts, faceVertexIndices; - MStatus status = m.getVertices(faceVertexCounts, faceVertexIndices); - if (!status) - return status; - - // Construct a cumulative index array. Each element in this array - // is the starting index into the vertex index and uv index arrays. - // We use it later to map face indices to uv indices. - // - std::vector cumIndices(faceVertexCounts.length()); - size_t cumIndex = 0; - for (size_t i = 0; i < cumIndices.size(); i++) { - cumIndices[i] = cumIndex; - cumIndex += faceVertexCounts[i]; - } - - // Our "full" u and v arrays will each have the same number of elements as - // faceVertexIndices. Make new arrays, and fill them with a very large - // negative value (very large positive values are poisonous to Mari). The - // idea is that texture look-ups on faces with no uvs will trigger wrap - // behavior, which can be set to "black", if necessary. - // - const int numUVs = faceVertexIndices.length(); - MFloatArray uArrayFull(numUVs, -1.0e30); - MFloatArray vArrayFull(numUVs, -1.0e30); - - // Now poke in the u and v values that actually exist - // k assumes values in the range [0, uvIds.length()) - // - int k = 0; - for (size_t i = 0; i < uvCounts.length(); i++) { - if (uvCounts[i] == 0) - continue; - - const int cumIndex = cumIndices[i]; - for (int j = cumIndex; j < cumIndex + uvCounts[i]; j++, k++) { - const int uvId = uvIds[k]; - uArrayFull[j] = uArray[uvId]; - vArrayFull[j] = vArray[uvId]; - } - } - - if (k == 0) { - // No uvs assigned at all ... clear the result - uvArray->clear(); - return MS::kFailure; - } else { - _CopyUVs(uArrayFull, vArrayFull, uvArray); - return MS::kSuccess; - } -} - -static inline bool _AllSame(const MFloatArray& v) -{ - const float& firstVal = v[0]; - for (size_t i = 1; i < v.length(); i++) { - if (!_IsClose(v[i], firstVal)) - return false; - } - - return true; -} - -/* static */ -MStatus -MayaMeshWriter::_CompressUVs(const MFnMesh& m, - const MIntArray& uvIds, - const MFloatArray& uArray, const MFloatArray& vArray, - VtArray *uvArray, - TfToken *interpolation) -{ - MIntArray faceVertexCounts, faceVertexIndices; - MStatus status = m.getVertices(faceVertexCounts, faceVertexIndices); - if (!status) - return status; - - // All uvs are natively stored and accessed as "faceVarying" in Maya. - // But we'd like to save space when possible, so we examine the u and - // values to see if they can't be represented as "vertex" or "constant" instead. - // - // Our strategy is to visit all vertices of all faces, some of which might - // be the same physical vertex. We look up the u and v values for each - // vertex, and check to see if they are the same as they were for the last - // visit to that vertex. If they are not, we know the uvs can't be "vertex", - // and thus not "constant" either. - // - // Even if the uv set turns out to be "faceVarying" after all, we have to - // fill in the face-varying arrays, because we can't assume that "uArray" - // and "vArray" have as many values as there are vertices (we may still - // have uv sharing). - // - // Note that the Maya API guarantees that vertex indices are always in the - // range [0, numVertices). This algorithm depends on that being the case. - // - MFloatArray uArrayFV(faceVertexIndices.length()); - MFloatArray vArrayFV(faceVertexIndices.length()); - - MFloatArray uArrayVertex(m.numVertices(), 0); - MFloatArray vArrayVertex(m.numVertices(), 0); - std::vector visited(m.numVertices(), false); - - // Start off with "vertex" -- we may decide it's - // "faceVarying" in the middle of the loop. - // - *interpolation = UsdGeomTokens->vertex; - - int k = 0; - for (size_t i = 0; i < faceVertexCounts.length(); i++) { - for (int j = 0; j < faceVertexCounts[i]; j++, k++) { - const int vertexIndex = faceVertexIndices[k]; - const float u = uArray[uvIds[k]]; - const float v = vArray[uvIds[k]]; - uArrayFV[k] = u; - vArrayFV[k] = v; - if (*interpolation == UsdGeomTokens->vertex) { - if (visited[vertexIndex]) { - // We've been here before -- check to see if - // the u and v are the same - if (!_IsClose(uArrayVertex[vertexIndex], u) || - !_IsClose(vArrayVertex[vertexIndex], v)) { - // Alas, it's not "vertex". Switch the detail - // to "faceVarying" and clear the arrays. Henceforth, - // only fill uArrayFV and vArrayFV. - // - *interpolation = UsdGeomTokens->faceVarying; - uArrayVertex.clear(); - vArrayVertex.clear(); - } - } else { - // Never been here .. mark visited, and - // store u and v. - visited[vertexIndex] = true; - uArrayVertex[vertexIndex] = u; - vArrayVertex[vertexIndex] = v; - } - } - } - } - - if (*interpolation == UsdGeomTokens->vertex) { - // Check to see if all the (u, v) values are the same. If they are, we can - // declare the detail ""constant"", and fill in just one value. - // - if (_AllSame(uArrayVertex) && _AllSame(vArrayVertex)) { - *interpolation = UsdGeomTokens->constant; - uvArray->clear(); - uvArray->push_back(GfVec2f(uArrayVertex[0], vArrayVertex[0])); - } else { - // Nope, still "vertex" - _CopyUVs(uArrayVertex, vArrayVertex, uvArray); - } - } else { - // "faceVarying" - _CopyUVs(uArrayFV, vArrayFV, uvArray); - } - - return MS::kSuccess; -} - - - -MStatus -MayaMeshWriter::_GetMeshUVSetData(MFnMesh& m, MString uvSetName, - VtArray *uvArray, - TfToken *interpolation) -{ - MStatus status; - - MIntArray uvCounts, uvIds; - status = m.getAssignedUVs(uvCounts, uvIds, &uvSetName); - if (!status) - return status; - - - MFloatArray uArray, vArray; - status = m.getUVs(uArray, vArray, &uvSetName); - if (!status) - return status; - - // Sanity check the data before we attempt to do anything with it. - if (uvCounts.length() == 0 or uvIds.length() == 0 or - uArray.length() == 0 or vArray.length() == 0) { - return MS::kFailure; - } - - // Check for zeros in "uvCounts" -- if there are any, - // the uvs are sparse. - const bool isSparse = _HasZeros(uvCounts); - - if (!isSparse) { - return _CompressUVs(m, uvIds, uArray, vArray, - uvArray, interpolation); - } else { - *interpolation = UsdGeomTokens->faceVarying; - return _FullUVsFromSparse(m, uvCounts, uvIds, uArray, vArray, - uvArray); - } - -} diff --git a/third_party/maya/lib/usdMaya/util.cpp b/third_party/maya/lib/usdMaya/util.cpp index b19ace60a4..42686b77b4 100644 --- a/third_party/maya/lib/usdMaya/util.cpp +++ b/third_party/maya/lib/usdMaya/util.cpp @@ -37,10 +37,13 @@ #include #include #include +#include #include #include #include +#include + // return seconds per frame double PxrUsdMayaUtil::spf() @@ -701,6 +704,221 @@ PxrUsdMayaUtil::GetLinearShaderColor( assignmentIndices); } +template +struct ValueHash +{ + std::size_t operator() (const T& value) const { + return hash_value(value); + } +}; + +template +struct ValuesEqual +{ + bool operator() (const T& a, const T& b) const { + return GfIsClose(a, b, 1e-9); + } +}; + +template +static +void +_MergeEquivalentIndexedValues( + VtArray* valueData, + VtArray* assignmentIndices) +{ + if (not valueData or not assignmentIndices) { + return; + } + + const size_t numValues = valueData->size(); + if (numValues == 0) { + return; + } + + // We maintain a map of values to that value's index in our uniqueValues + // array. + std::unordered_map, ValuesEqual > valuesMap; + VtArray uniqueValues; + VtArray uniqueIndices; + + for (size_t i = 0; i < assignmentIndices->size(); ++i) { + int index = (*assignmentIndices)[i]; + + if (index < 0 or static_cast(index) >= numValues) { + // This is an unassigned or otherwise unknown index, so just keep it. + uniqueIndices.push_back(index); + continue; + } + + const T value = (*valueData)[index]; + + int uniqueIndex = -1; + + auto inserted = valuesMap.insert( + std::pair(value, uniqueValues.size())); + if (inserted.second) { + // This is a new value, so add it to the array. + uniqueValues.push_back(value); + uniqueIndex = uniqueValues.size() - 1; + } else { + // This is an existing value, so re-use the original's index. + uniqueIndex = inserted.first->second; + } + + uniqueIndices.push_back(uniqueIndex); + } + + // If we reduced the number of values by merging, copy the results back. + if (uniqueValues.size() < numValues) { + (*valueData) = uniqueValues; + (*assignmentIndices) = uniqueIndices; + } +} + +void +PxrUsdMayaUtil::MergeEquivalentIndexedValues( + VtArray* valueData, + VtArray* assignmentIndices) { + return _MergeEquivalentIndexedValues(valueData, assignmentIndices); +} + +void +PxrUsdMayaUtil::MergeEquivalentIndexedValues( + VtArray* valueData, + VtArray* assignmentIndices) { + return _MergeEquivalentIndexedValues(valueData, assignmentIndices); +} + +void +PxrUsdMayaUtil::MergeEquivalentIndexedValues( + VtArray* valueData, + VtArray* assignmentIndices) { + return _MergeEquivalentIndexedValues(valueData, assignmentIndices); +} + +void +PxrUsdMayaUtil::MergeEquivalentIndexedValues( + VtArray* valueData, + VtArray* assignmentIndices) { + return _MergeEquivalentIndexedValues(valueData, assignmentIndices); +} + +void +PxrUsdMayaUtil::CompressFaceVaryingPrimvarIndices( + const MFnMesh& mesh, + TfToken *interpolation, + VtArray* assignmentIndices) +{ + if (not interpolation or + not assignmentIndices or + assignmentIndices->size() == 0) { + return; + } + + // Use -2 as the initial "un-stored" sentinel value, since -1 is the + // default unauthored value index for primvars. + int numPolygons = mesh.numPolygons(); + VtArray uniformAssignments; + uniformAssignments.assign((size_t)numPolygons, -2); + + int numVertices = mesh.numVertices(); + VtArray vertexAssignments; + vertexAssignments.assign((size_t)numVertices, -2); + + // We assume that the data is constant/uniform/vertex until we can + // prove otherwise that two components have differing values. + bool isConstant = true; + bool isUniform = true; + bool isVertex = true; + + MItMeshFaceVertex itFV(mesh.object()); + unsigned int fvi = 0; + for (itFV.reset(); not itFV.isDone(); itFV.next(), ++fvi) { + int faceIndex = itFV.faceId(); + int vertexIndex = itFV.vertId(); + + int assignedIndex = (*assignmentIndices)[fvi]; + + if (isConstant) { + if (assignedIndex != (*assignmentIndices)[0]) { + isConstant = false; + } + } + + if (isUniform) { + if (uniformAssignments[faceIndex] < -1) { + // No value for this face yet, so store one. + uniformAssignments[faceIndex] = assignedIndex; + } else if (assignedIndex != uniformAssignments[faceIndex]) { + isUniform = false; + } + } + + if (isVertex) { + if (vertexAssignments[vertexIndex] < -1) { + // No value for this vertex yet, so store one. + vertexAssignments[vertexIndex] = assignedIndex; + } else if (assignedIndex != vertexAssignments[vertexIndex]) { + isVertex = false; + } + } + + if (not isConstant and not isUniform and not isVertex) { + // No compression will be possible, so stop trying. + break; + } + } + + if (isConstant) { + assignmentIndices->resize(1); + *interpolation = UsdGeomTokens->constant; + } else if (isUniform) { + *assignmentIndices = uniformAssignments; + *interpolation = UsdGeomTokens->uniform; + } else if(isVertex) { + *assignmentIndices = vertexAssignments; + *interpolation = UsdGeomTokens->vertex; + } else { + *interpolation = UsdGeomTokens->faceVarying; + } +} + +bool +PxrUsdMayaUtil::AddUnassignedUVIfNeeded( + VtArray* uvData, + VtArray* assignmentIndices, + int* unassignedValueIndex, + const GfVec2f& defaultUV) +{ + if (not assignmentIndices or assignmentIndices->empty()) { + return false; + } + + *unassignedValueIndex = -1; + + for (size_t i = 0; i < assignmentIndices->size(); ++i) { + if ((*assignmentIndices)[i] >= 0) { + // This component has an assignment, so skip it. + continue; + } + + // We found an unassigned index. Add the unassigned value to uvData + // if we haven't already. + if (*unassignedValueIndex < 0) { + if (uvData) { + uvData->push_back(defaultUV); + } + *unassignedValueIndex = uvData->size() - 1; + } + + // Assign the component the unassigned value index. + (*assignmentIndices)[i] = *unassignedValueIndex; + } + + return true; +} + bool PxrUsdMayaUtil::AddUnassignedColorAndAlphaIfNeeded( VtArray* RGBData, diff --git a/third_party/maya/lib/usdMaya/util.h b/third_party/maya/lib/usdMaya/util.h index eef55e3d4b..365a10d329 100644 --- a/third_party/maya/lib/usdMaya/util.h +++ b/third_party/maya/lib/usdMaya/util.h @@ -24,6 +24,11 @@ #ifndef PXRUSDMAYA_UTIL_H #define PXRUSDMAYA_UTIL_H +/// \file util.h + +#include "pxr/base/gf/vec2f.h" +#include "pxr/base/gf/vec3f.h" +#include "pxr/base/gf/vec4f.h" #include "pxr/usd/sdf/path.h" #include "pxr/usd/usd/attribute.h" #include "pxr/usd/usd/timeCode.h" @@ -183,6 +188,50 @@ bool GetLinearShaderColor( TfToken *interpolation, VtArray *assignmentIndices); +/// Combine distinct indices that point to the same values to all point to the +/// same index for that value. This will potentially shrink the data array. +void MergeEquivalentIndexedValues( + VtArray* valueData, + VtArray* assignmentIndices); + +/// Combine distinct indices that point to the same values to all point to the +/// same index for that value. This will potentially shrink the data array. +void MergeEquivalentIndexedValues( + VtArray* valueData, + VtArray* assignmentIndices); + +/// Combine distinct indices that point to the same values to all point to the +/// same index for that value. This will potentially shrink the data array. +void MergeEquivalentIndexedValues( + VtArray* valueData, + VtArray* assignmentIndices); + +/// Combine distinct indices that point to the same values to all point to the +/// same index for that value. This will potentially shrink the data array. +void MergeEquivalentIndexedValues( + VtArray* valueData, + VtArray* assignmentIndices); + +/// Attempt to compress faceVarying primvar indices to uniform, vertex, or +/// constant interpolation if possible. This will potentially shrink the +/// indices array and will update the interpolation if any compression was +/// possible. +void CompressFaceVaryingPrimvarIndices( + const MFnMesh& mesh, + TfToken *interpolation, + VtArray* assignmentIndices); + +/// If any components in \p assignmentIndices are unassigned (-1), the given +/// default value will be added to uvData and all of those components will be +/// assigned that index, which is returned in \p unassignedValueIndex. +/// Returns true if unassigned values were added and indices were updated, or +/// false otherwise. +bool AddUnassignedUVIfNeeded( + VtArray* uvData, + VtArray* assignmentIndices, + int* unassignedValueIndex, + const GfVec2f& defaultUV); + /// If any components in \p assignmentIndices are unassigned (-1), the given /// default values will be added to RGBData and AlphaData and all of those /// components will be assigned that index, which is returned in From 167b653518ded77e56bc0b7983901be10c75e838 Mon Sep 17 00:00:00 2001 From: pixar-oss Date: Thu, 8 Sep 2016 11:24:46 -0700 Subject: [PATCH 108/380] Added support for point velocities and normals on prims which inherit UsdGeomPointBased. (Internal change: 1653264) --- .../katana/lib/usdKatana/readBasisCurves.cpp | 19 ++- .../katana/lib/usdKatana/readGprim.cpp | 148 +++++++++--------- third_party/katana/lib/usdKatana/readGprim.h | 5 + third_party/katana/lib/usdKatana/readMesh.cpp | 18 ++- .../katana/lib/usdKatana/readNurbsPatch.cpp | 19 +++ .../katana/lib/usdKatana/readPoints.cpp | 53 ++----- 6 files changed, 143 insertions(+), 119 deletions(-) diff --git a/third_party/katana/lib/usdKatana/readBasisCurves.cpp b/third_party/katana/lib/usdKatana/readBasisCurves.cpp index 762920230a..3f96088fa5 100644 --- a/third_party/katana/lib/usdKatana/readBasisCurves.cpp +++ b/third_party/katana/lib/usdKatana/readBasisCurves.cpp @@ -148,6 +148,7 @@ PxrUsdKatanaReadBasisCurves( geometryBuilder.update(curveAttr); } + // position geometryBuilder.set("point.P", PxrUsdKatanaGeomGetPAttr(basisCurves, data)); @@ -155,7 +156,23 @@ PxrUsdKatanaReadBasisCurves( FnKat::Attribute normalsAttr = PxrUsdKatanaGeomGetNormalAttr(basisCurves, data); if (normalsAttr.isValid()) { - geometryBuilder.set("point.N", normalsAttr); + // XXX RfK doesn't support uniform normals for curves. + // Additionally, varying and facevarying may not be correct for + // periodic cubic curves. + TfToken interp = basisCurves.GetNormalsInterpolation(); + if (interp == UsdGeomTokens->faceVarying + || interp == UsdGeomTokens->varying + || interp == UsdGeomTokens->vertex) { + geometryBuilder.set("point.N", normalsAttr); + } + } + + // velocity + FnKat::Attribute velocityAttr = + PxrUsdKatanaGeomGetVelocityAttr(basisCurves, data); + if (velocityAttr.isValid()) + { + geometryBuilder.set("point.v", velocityAttr); } // Construct the 'geometry.arbitrary' attribute. diff --git a/third_party/katana/lib/usdKatana/readGprim.cpp b/third_party/katana/lib/usdKatana/readGprim.cpp index afd4c47266..2c339df983 100644 --- a/third_party/katana/lib/usdKatana/readGprim.cpp +++ b/third_party/katana/lib/usdKatana/readGprim.cpp @@ -46,68 +46,6 @@ PxrUsdKatanaReadGprim( PxrUsdKatanaReadXformable(gprim, data, attrs); } -FnKat::Attribute -PxrUsdKatanaGeomGetPAttr( - const UsdGeomPointBased& points, - const PxrUsdKatanaUsdInPrivateData& data) -{ - UsdAttribute pointsAttr = points.GetPointsAttr(); - if (not pointsAttr) - { - return FnKat::Attribute(); - } - - const double currentTime = data.GetUsdInArgs()->GetCurrentTime(); - const std::vector& motionSampleTimes = data.GetMotionSampleTimes(pointsAttr); - - // Flag to check if we discovered the topology is varying, in - // which case we only output the sample at the curent frame. - bool varyingTopology = false; - - // Used to compare value sizes to identify varying topology. - int arraySize = -1; - - const bool isMotionBackward = data.GetUsdInArgs()->IsMotionBackward(); - - FnKat::FloatBuilder attrBuilder(/* tupleSize = */ 3); - TF_FOR_ALL(iter, motionSampleTimes) - { - double relSampleTime = *iter; - double time = currentTime + relSampleTime; - - // Eval points. - VtVec3fArray ptArray; - pointsAttr.Get(&ptArray, time); - - if (arraySize == -1) { - arraySize = ptArray.size(); - } else if ( ptArray.size() != static_cast(arraySize) ) { - // Topology has changed. Don't create this or subsequent samples. - varyingTopology = true; - break; - } - - std::vector &ptVec = attrBuilder.get(isMotionBackward ? - PxrUsdKatanaUtils::ReverseTimeSample(relSampleTime) : relSampleTime); - - PxrUsdKatanaUtils::ConvertArrayToVector(ptArray, &ptVec); - } - - // Varying topology was found, build for the current frame only. - if (varyingTopology) - { - FnKat::FloatBuilder defaultBuilder(/* tupleSize = */ 3); - VtVec3fArray ptArray; - - pointsAttr.Get(&ptArray, currentTime); - std::vector &ptVec = defaultBuilder.get(0); - PxrUsdKatanaUtils::ConvertArrayToVector(ptArray, &ptVec); - - return defaultBuilder.build(); - } - - return attrBuilder.build(); -} FnKat::Attribute PxrUsdKatanaGeomGetDisplayColorAttr( @@ -246,38 +184,98 @@ PxrUsdKatanaGeomGetWindingOrderAttr( } } -Foundry::Katana::Attribute -PxrUsdKatanaGeomGetNormalAttr( - const UsdGeomPointBased& points, +namespace { + +template FnKat::Attribute +_ConvertGeomAttr( + const UsdAttribute& usdAttr, + const int tupleSize, const PxrUsdKatanaUsdInPrivateData& data) { - UsdAttribute normalsAttr = points.GetNormalsAttr(); - if (not normalsAttr) + if (not usdAttr.HasValue()) { return FnKat::Attribute(); } const double currentTime = data.GetUsdInArgs()->GetCurrentTime(); - const std::vector& motionSampleTimes = - data.GetMotionSampleTimes(normalsAttr); + const std::vector& motionSampleTimes = data.GetMotionSampleTimes(usdAttr); + + // Flag to check if we discovered the topology is varying, in + // which case we only output the sample at the curent frame. + bool varyingTopology = false; + + // Used to compare value sizes to identify varying topology. + int arraySize = -1; const bool isMotionBackward = data.GetUsdInArgs()->IsMotionBackward(); - FnKat::FloatBuilder attrBuilder(/* tupleSize = */ 3); + FnKat::DataBuilder attrBuilder(tupleSize); TF_FOR_ALL(iter, motionSampleTimes) { double relSampleTime = *iter; double time = currentTime + relSampleTime; - // Retrieve normals at time. - VtVec3fArray normalsArray; - normalsAttr.Get(&normalsArray, time); + // Eval attr. + VtArray attrArray; + usdAttr.Get(&attrArray, time); - std::vector &normalsVec = attrBuilder.get(isMotionBackward ? + if (arraySize == -1) { + arraySize = attrArray.size(); + } else if ( attrArray.size() != static_cast(arraySize) ) { + // Topology has changed. Don't create this or subsequent samples. + varyingTopology = true; + break; + } + + std::vector &attrVec = + attrBuilder.get(isMotionBackward ? PxrUsdKatanaUtils::ReverseTimeSample(relSampleTime) : relSampleTime); - PxrUsdKatanaUtils::ConvertArrayToVector(normalsArray, &normalsVec); + PxrUsdKatanaUtils::ConvertArrayToVector(attrArray, &attrVec); + } + + // Varying topology was found, build for the current frame only. + if (varyingTopology) + { + FnKat::DataBuilder defaultBuilder(tupleSize); + VtArray attrArray; + + usdAttr.Get(&attrArray, currentTime); + std::vector &attrVec = defaultBuilder.get(0); + PxrUsdKatanaUtils::ConvertArrayToVector(attrArray, &attrVec); + + return defaultBuilder.build(); } return attrBuilder.build(); } + +} // anon namespace + +FnKat::Attribute +PxrUsdKatanaGeomGetPAttr( + const UsdGeomPointBased& points, + const PxrUsdKatanaUsdInPrivateData& data) +{ + return _ConvertGeomAttr( + points.GetPointsAttr(), 3, data); +} + +Foundry::Katana::Attribute +PxrUsdKatanaGeomGetNormalAttr( + const UsdGeomPointBased& points, + const PxrUsdKatanaUsdInPrivateData& data) +{ + return _ConvertGeomAttr( + points.GetNormalsAttr(), 3, data); +} + +Foundry::Katana::Attribute +PxrUsdKatanaGeomGetVelocityAttr( + const UsdGeomPointBased& points, + const PxrUsdKatanaUsdInPrivateData& data) +{ + return _ConvertGeomAttr( + points.GetVelocitiesAttr(), 3, data); + +} diff --git a/third_party/katana/lib/usdKatana/readGprim.h b/third_party/katana/lib/usdKatana/readGprim.h index 399c1d95c4..e9fd6f5246 100644 --- a/third_party/katana/lib/usdKatana/readGprim.h +++ b/third_party/katana/lib/usdKatana/readGprim.h @@ -61,6 +61,11 @@ PxrUsdKatanaGeomGetNormalAttr( const UsdGeomPointBased& points, const PxrUsdKatanaUsdInPrivateData& data); +Foundry::Katana::Attribute +PxrUsdKatanaGeomGetVelocityAttr( + const UsdGeomPointBased& points, + const PxrUsdKatanaUsdInPrivateData& data); + #endif // PXRUSDKATANA_READGPRIM_H diff --git a/third_party/katana/lib/usdKatana/readMesh.cpp b/third_party/katana/lib/usdKatana/readMesh.cpp index 74e7dae4f1..1bdd249b67 100644 --- a/third_party/katana/lib/usdKatana/readMesh.cpp +++ b/third_party/katana/lib/usdKatana/readMesh.cpp @@ -396,6 +396,7 @@ PxrUsdKatanaReadMesh( FnKat::GroupBuilder geometryBuilder; + // position geometryBuilder.set("point.P", PxrUsdKatanaGeomGetPAttr(mesh, data)); /// Only use custom normals if the object is a polymesh. @@ -404,10 +405,25 @@ PxrUsdKatanaReadMesh( FnKat::Attribute normalsAttr = PxrUsdKatanaGeomGetNormalAttr(mesh, data); if (normalsAttr.isValid()) { - geometryBuilder.set("point.N", normalsAttr); + // XXX RfK currently doesn't support uniform normals for polymeshes. + TfToken interp = mesh.GetNormalsInterpolation(); + if (interp == UsdGeomTokens->varying + || interp == UsdGeomTokens->vertex) { + geometryBuilder.set("point.N", normalsAttr); + } + else if (interp == UsdGeomTokens->faceVarying) { + geometryBuilder.set("vertex.N", normalsAttr); + } } } + // velocity + FnKat::Attribute velocityAttr = PxrUsdKatanaGeomGetVelocityAttr(mesh, data); + if (velocityAttr.isValid()) + { + geometryBuilder.set("point.v", velocityAttr); + } + FnKat::GroupAttribute polyAttr = _GetPolyAttr(mesh, currentTime); geometryBuilder.set("poly", polyAttr); diff --git a/third_party/katana/lib/usdKatana/readNurbsPatch.cpp b/third_party/katana/lib/usdKatana/readNurbsPatch.cpp index 23190d9f78..1f37cfcc2e 100644 --- a/third_party/katana/lib/usdKatana/readNurbsPatch.cpp +++ b/third_party/katana/lib/usdKatana/readNurbsPatch.cpp @@ -336,6 +336,25 @@ PxrUsdKatanaReadNurbsPatch( geometryBuilder.set("vClosed", _GetVClosedAttr(nurbsPatch, currentTime)); geometryBuilder.set("trimCurves", _GetTrimCurvesAttr(nurbsPatch, currentTime)); + // normals + FnKat::Attribute normalsAttr = PxrUsdKatanaGeomGetNormalAttr(nurbsPatch, data); + if (normalsAttr.isValid()) + { + // XXX RfK currently doesn't support uniform, varying, or facevarying + // normals for nuPatches. + TfToken interp = nurbsPatch.GetNormalsInterpolation(); + if (interp == UsdGeomTokens->vertex) { + geometryBuilder.set("point.N", normalsAttr); + } + } + + // velocity + FnKat::Attribute velocityAttr = PxrUsdKatanaGeomGetVelocityAttr(nurbsPatch, data); + if (velocityAttr.isValid()) + { + geometryBuilder.set("point.v", velocityAttr); + } + FnKat::GroupBuilder arbBuilder; FnKat::GroupAttribute primvarGroup = PxrUsdKatanaGeomGetPrimvarGroup(nurbsPatch, data); diff --git a/third_party/katana/lib/usdKatana/readPoints.cpp b/third_party/katana/lib/usdKatana/readPoints.cpp index dad489e1ad..ae931d3b22 100644 --- a/third_party/katana/lib/usdKatana/readPoints.cpp +++ b/third_party/katana/lib/usdKatana/readPoints.cpp @@ -29,44 +29,6 @@ #include "pxr/usd/usdGeom/points.h" -static FnKat::Attribute -_GetVelocityAttr( - const UsdGeomPointBased& points, - double currentTime) -{ - VtVec3fArray velocities; - if (not points.GetVelocitiesAttr().Get(&velocities, currentTime)) - { - return FnKat::Attribute(); - } - - // float attribute list with a width of 3 - FnKat::FloatBuilder velocitiesBuilder(3); - std::vector velVec; - PxrUsdKatanaUtils::ConvertArrayToVector(velocities, &velVec); - velocitiesBuilder.set(velVec); - - return velocitiesBuilder.build(); -} - -static FnKat::Attribute -_GetNormalsAttr(const UsdGeomPoints& points, double currentTime) -{ - VtVec3fArray normals; - if (not points.GetNormalsAttr().Get(&normals, currentTime)) - { - return FnKat::Attribute(); - } - - // float attribute list with a width of 3 - FnKat::FloatBuilder normalsBuilder(3); - std::vector normalsVec; - PxrUsdKatanaUtils::ConvertArrayToVector(normals, &normalsVec); - normalsBuilder.set(normalsVec); - - return normalsBuilder.build(); -} - static FnKat::Attribute _GetWidthAttr(const UsdGeomPoints& points, double currentTime) { @@ -109,21 +71,28 @@ PxrUsdKatanaReadPoints( FnKat::GroupBuilder geometryBuilder; - // point + // position geometryBuilder.set("point.P", PxrUsdKatanaGeomGetPAttr(points, data)); // velocity - FnKat::Attribute velocitiesAttr = _GetVelocityAttr(points, currentTime); + FnKat::Attribute velocitiesAttr = + PxrUsdKatanaGeomGetVelocityAttr(points, data); if (velocitiesAttr.isValid()) { geometryBuilder.set("point.v", velocitiesAttr); } // normals - FnKat::Attribute normalsAttr = _GetNormalsAttr(points, currentTime); + FnKat::Attribute normalsAttr = PxrUsdKatanaGeomGetNormalAttr(points, data); if (normalsAttr.isValid()) { - geometryBuilder.set("point.N", normalsAttr); + // XXX RfK doesn't support uniform curve normals. + TfToken interp = points.GetNormalsInterpolation(); + if (interp == UsdGeomTokens->faceVarying + || interp == UsdGeomTokens->varying + || interp == UsdGeomTokens->vertex) { + geometryBuilder.set("point.N", normalsAttr); + } } // width From d2df030142c56fc11f123dedf2934abf2b897889 Mon Sep 17 00:00:00 2001 From: superfunc Date: Thu, 8 Sep 2016 11:24:55 -0700 Subject: [PATCH 109/380] [Imaging] Fix signed-vs-unsigned warnings (Internal change: 1653265) --- pxr/imaging/lib/glf/uvTextureData.cpp | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/pxr/imaging/lib/glf/uvTextureData.cpp b/pxr/imaging/lib/glf/uvTextureData.cpp index 2e8d6e4b34..f71d87e7c1 100644 --- a/pxr/imaging/lib/glf/uvTextureData.cpp +++ b/pxr/imaging/lib/glf/uvTextureData.cpp @@ -327,7 +327,8 @@ GlfUVTextureData::Read(int degradeLevel, bool generateMipmap) const double scale = generateMipmap ? 4.0 / 3 : 1.0; int sizeAprox = _resizedWidth * _resizedHeight * _bytesPerPixel * scale; - while (_targetMemory > 0 && (sizeAprox > _targetMemory)) { + while ((_targetMemory > 0) + && (static_cast(sizeAprox) > _targetMemory)) { _resizedWidth >>= 1; _resizedHeight >>= 1; sizeAprox = _resizedWidth * _resizedHeight * _bytesPerPixel * scale; @@ -412,7 +413,7 @@ size_t GlfUVTextureData::ComputeBytesUsedByMip(int mipLevel) const { // Returns specific mip level sizes - if (mipLevel >= _rawBufferMips.size()) return 0; + if (static_cast(mipLevel) >= _rawBufferMips.size()) return 0; return _rawBufferMips[mipLevel].size; } @@ -425,28 +426,30 @@ GlfUVTextureData::ComputeBytesUsed() const bool GlfUVTextureData::HasRawBuffer(int mipLevel) const { - if (mipLevel >= _rawBufferMips.size()) return false; + if (static_cast(mipLevel) >= _rawBufferMips.size()) return false; return (_rawBufferMips[mipLevel].size > 0); } unsigned char * GlfUVTextureData::GetRawBuffer(int mipLevel) const { - if (mipLevel >= _rawBufferMips.size() or not _rawBuffer) return 0; + if (static_cast(mipLevel) >= _rawBufferMips.size() or not _rawBuffer) { + return 0; + } return _rawBuffer.get() + _rawBufferMips[mipLevel].offset; } int GlfUVTextureData::ResizedWidth(int mipLevel) const { - if (mipLevel >= _rawBufferMips.size()) return 0; + if (static_cast(mipLevel) >= _rawBufferMips.size()) return 0; return _rawBufferMips[mipLevel].width; } int GlfUVTextureData::ResizedHeight(int mipLevel) const { - if (mipLevel >= _rawBufferMips.size()) return 0; + if (static_cast(mipLevel) >= _rawBufferMips.size()) return 0; return _rawBufferMips[mipLevel].height; } From 87fcbde33a188168fed27d24b46e8beebab418ab Mon Sep 17 00:00:00 2001 From: superfunc Date: Thu, 8 Sep 2016 11:25:41 -0700 Subject: [PATCH 110/380] [Usd] Fix for attribute blocking. Previously, the typed Get() API in Usd was broken with respect to blocks. This occured because of failed calls to StoreValue() during the composition phase. To alleviate this, this adds a member, isValueBlock to the underlying SdfAbstractData classes, which allows consumers, such as the composition functions, to query whether or not a fetched value was a block. This also fixes a bug in the UsdAttributeQuery code, which wasn't consulting the typed value's "blockedness" at all. (Internal change: 1653268) --- pxr/usd/lib/sdf/abstractData.h | 26 +++++++++++++++++---- pxr/usd/lib/sdf/layer.h | 19 ++++++++++++--- pxr/usd/lib/usd/stage.cpp | 39 ++++++++++++++++++------------- pxr/usd/lib/usdGeom/bboxCache.cpp | 21 +++++++---------- 4 files changed, 68 insertions(+), 37 deletions(-) diff --git a/pxr/usd/lib/sdf/abstractData.h b/pxr/usd/lib/sdf/abstractData.h index bc8df0d54c..7c8179071f 100644 --- a/pxr/usd/lib/sdf/abstractData.h +++ b/pxr/usd/lib/sdf/abstractData.h @@ -43,6 +43,7 @@ class SdfAbstractDataSpecVisitor; class SdfAbstractDataConstValue; class SdfAbstractDataValue; + #define SDF_DATA_TOKENS \ ((TimeSamples, "timeSamples")) @@ -381,8 +382,9 @@ class SdfAbstractDataValue { public: virtual bool StoreValue(const VtValue& value) = 0; - - template bool StoreValue(const T& v) + + template + bool StoreValue(const T& v) { if (TfSafeTypeCompare(typeid(T), valueType)) { *static_cast(value) = v; @@ -391,13 +393,21 @@ class SdfAbstractDataValue return false; } + bool StoreValue(const SdfValueBlock& block) + { + isValueBlock = true; + return true; + } + void* value; const std::type_info& valueType; + bool isValueBlock; protected: SdfAbstractDataValue(void* value_, const std::type_info& valueType_) : value(value_) , valueType(valueType_) + , isValueBlock(false) { } }; @@ -424,6 +434,11 @@ class SdfAbstractDataTypedValue : public SdfAbstractDataValue virtual bool StoreValue(const VtValue& v) { + if (v.IsHolding()) { + isValueBlock = true; + return true; + } + if (not v.IsHolding()) { return false; } @@ -459,10 +474,11 @@ class SdfAbstractDataConstValue protected: SdfAbstractDataConstValue(const void* value_, - const std::type_info& valueType_) + const std::type_info& valueType_) : value(value_) , valueType(valueType_) - { } + { + } }; /// \class SdfAbstractDataConstTypedValue @@ -485,7 +501,7 @@ class SdfAbstractDataConstTypedValue : public SdfAbstractDataConstValue SdfAbstractDataConstTypedValue(const T* value) : SdfAbstractDataConstValue(value, typeid(T)) { } - + virtual bool GetValue(VtValue* v) const { *v = _GetValue(); diff --git a/pxr/usd/lib/sdf/layer.h b/pxr/usd/lib/sdf/layer.h index 03207eb61e..a8a7224188 100644 --- a/pxr/usd/lib/sdf/layer.h +++ b/pxr/usd/lib/sdf/layer.h @@ -455,12 +455,19 @@ class SdfLayer : public SdfLayerBase bool HasField(const SdfAbstractDataSpecId& id, const TfToken &name, T* value) const { - if (not value) + if (not value) { return HasField(id, name, static_cast(NULL)); + } SdfAbstractDataTypedValue outValue(value); - return HasField( + const bool hasValue = HasField( id, name, static_cast(&outValue)); + + if (std::is_same::value) { + return hasValue and outValue.isValueBlock; + } + + return hasValue and (not outValue.isValueBlock); } /// Return whether a value exists for the given \a id and \a fieldName and @@ -1111,8 +1118,14 @@ class SdfLayer : public SdfLayerBase } SdfAbstractDataTypedValue outValue(data); - return QueryTimeSample( + const bool hasValue = QueryTimeSample( id, time, static_cast(&outValue)); + + if (std::is_same::value) { + return hasValue and outValue.isValueBlock; + } + + return hasValue and (not outValue.isValueBlock); } void SetTimeSample(const SdfAbstractDataSpecId& id, double time, diff --git a/pxr/usd/lib/usd/stage.cpp b/pxr/usd/lib/usd/stage.cpp index 5cb446dc4c..0faacad449 100644 --- a/pxr/usd/lib/usd/stage.cpp +++ b/pxr/usd/lib/usd/stage.cpp @@ -1127,15 +1127,16 @@ _ValueContainsBlock(const VtValue* value) { } bool -_ValueContainsBlock(const SdfAbstractDataValue* value) { - static const TfType valueBlockType = TfType::Find(); - return value and value->valueType == valueBlockType.GetTypeid(); +_ValueContainsBlock(const SdfAbstractDataValue* value) +{ + return value and value->isValueBlock; } bool -_ValueContainsBlock(const SdfAbstractDataConstValue* value) { - static const TfType valueBlockType = TfType::Find(); - return value and value->valueType == valueBlockType.GetTypeid(); +_ValueContainsBlock(const SdfAbstractDataConstValue* value) +{ + constexpr const std::type_info& valueBlockTypeId(typeid(SdfValueBlock)); + return value and value->valueType == valueBlockTypeId; } bool @@ -1148,7 +1149,8 @@ _ClearValueIfBlocked(VtValue* value) { return false; } -bool _ClearValueIfBlocked(SdfAbstractDataValue* value) { +bool +_ClearValueIfBlocked(SdfAbstractDataValue* value) { return _ValueContainsBlock(value); } } @@ -4434,6 +4436,7 @@ UsdStage::_GetMetadataImpl( // Handle special cases. if (_GetSpecialMetadataImpl( obj, fieldName, keyPath, useFallbacks, composer)) { + return true; } @@ -4512,17 +4515,20 @@ UsdStage::_ComposeGeneralMetadataImpl(const UsdObject &obj, bool gotOpinion = false; for (bool isNewNode = false; res->IsValid(); isNewNode = res->NextLayer()) { - if (isNewNode) + if (isNewNode) specId = SdfAbstractDataSpecId(&res->GetLocalPath(), &propName); // Consume an authored opinion here, if one exists. gotOpinion |= composer->ConsumeAuthored( res->GetNode(), res->GetLayer(), specId, fieldName, keyPath); - if (composer->IsDone()) + + if (composer->IsDone()) return true; } + if (useFallbacks) _GetFallbackMetadataImpl(obj, fieldName, keyPath, composer); + return gotOpinion or composer->IsDone(); } @@ -4850,10 +4856,9 @@ UsdStage::_GetValueImpl(UsdTimeCode time, const UsdAttribute &attr, T *result) const { if (time.IsDefault()) { - bool metadataFetched = _GetMetadata(attr, SdfFieldKeys->Default, - TfToken(), /*useFallbacks=*/true, - result); - return metadataFetched and (not _ClearValueIfBlocked(result)); + bool valueFound = _GetMetadata(attr, SdfFieldKeys->Default, + TfToken(), /*useFallbacks=*/true, result); + return valueFound and (not _ClearValueIfBlocked(result)); } Usd_ResolveInfo resolveInfo; @@ -5237,9 +5242,11 @@ UsdStage::_GetValueFromResolveInfoImpl(const Usd_ResolveInfo &info, Usd_InterpolatorBase* interpolator, T* result) const { - if (time.IsDefault()) - return _GetMetadata(attr, SdfFieldKeys->Default, - TfToken(), /*useFallbacks=*/true, result); + if (time.IsDefault()) { + bool valueFound = _GetMetadata(attr, SdfFieldKeys->Default, + TfToken(), /*useFallbacks=*/true, result); + return valueFound and (not _ClearValueIfBlocked(result)); + } if (info.source == Usd_ResolveInfoSourceTimeSamples) { return _GetTimeSampleValue( diff --git a/pxr/usd/lib/usdGeom/bboxCache.cpp b/pxr/usd/lib/usdGeom/bboxCache.cpp index 68cc9a0c59..acc1a07369 100644 --- a/pxr/usd/lib/usdGeom/bboxCache.cpp +++ b/pxr/usd/lib/usdGeom/bboxCache.cpp @@ -680,7 +680,7 @@ UsdGeomBBoxCache::_ComputePurpose(const UsdPrim &prim) bool UsdGeomBBoxCache::_ShouldPruneChildren(const UsdPrim &prim, - UsdGeomBBoxCache::_Entry *entry) + UsdGeomBBoxCache::_Entry *entry) { // If the entry is already complete, we don't need to try to initialize it. if (entry->isComplete) { @@ -692,12 +692,10 @@ UsdGeomBBoxCache::_ShouldPruneChildren(const UsdPrim &prim, UsdAttribute extentsHintAttr = UsdGeomModelAPI(prim).GetExtentsHintAttr(); - VtValue extentsHint; - if (extentsHintAttr and - extentsHintAttr.Get(&extentsHint, _time) and - extentsHint.IsHolding() and - extentsHint.UncheckedGet().size() >=2) { - + VtVec3fArray extentsHint; + if (extentsHintAttr + and extentsHintAttr.Get(&extentsHint, _time) + and extentsHint.size() >= 2) { return true; } } @@ -830,8 +828,9 @@ UsdGeomBBoxCache::_GetBBoxFromExtentsHint( const UsdAttributeQuery &extentsHintQuery, _PurposeToBBoxMap *bboxes) { - VtValue extentsVal; - if (not extentsHintQuery or not extentsHintQuery.Get(&extentsVal, _time)){ + VtVec3fArray extents; + + if (not extentsHintQuery or not extentsHintQuery.Get(&extents, _time)){ if (TfDebug::IsEnabled(USDGEOM_BBOX) and not geomModel.GetPrim().IsLoaded()){ TF_DEBUG(USDGEOM_BBOX).Msg("[BBox Cache] MISSING extentsHint for " @@ -843,16 +842,12 @@ UsdGeomBBoxCache::_GetBBoxFromExtentsHint( return false; } - if (not extentsVal.IsHolding()) - return false; - TF_DEBUG(USDGEOM_BBOX).Msg("[BBox Cache] Found cached extentsHint for " "model %s.\n", geomModel.GetPrim().GetPath().GetString().c_str()); const TfTokenVector &purposeTokens = UsdGeomImageable::GetOrderedPurposeTokens(); - const VtVec3fArray &extents = extentsVal.UncheckedGet(); for(size_t i = 0; i < purposeTokens.size(); ++i) { size_t idx = i*2; // If extents are not available for the value of purpose, it From 85c920b9b2129fd195e5b010b3fba8257fff0d04 Mon Sep 17 00:00:00 2001 From: pixar-oss Date: Thu, 8 Sep 2016 11:29:11 -0700 Subject: [PATCH 111/380] Pass in clipping planes from the camera prim (i.e. the gfCamera computed from it) to hydra. (Internal change: 1653273) --- pxr/usdImaging/lib/usdviewq/stageView.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/pxr/usdImaging/lib/usdviewq/stageView.py b/pxr/usdImaging/lib/usdviewq/stageView.py index 2f7f9752a4..78b0ffe240 100644 --- a/pxr/usdImaging/lib/usdviewq/stageView.py +++ b/pxr/usdImaging/lib/usdviewq/stageView.py @@ -1306,7 +1306,8 @@ def paintGL(self): GL.glBlendFunc(GL.GL_SRC_ALPHA, GL.GL_ONE_MINUS_SRC_ALPHA) GL.glEnable(GL.GL_BLEND) - frustum = self.computeGfCamera().frustum + gfCamera = self.computeGfCamera() + frustum = gfCamera.frustum cam_pos = frustum.position cam_up = frustum.ComputeUpVector() @@ -1314,6 +1315,10 @@ def paintGL(self): self.setupOpenGLViewMatricesForFrustum(frustum) + # Set the clipping planes. + self._renderParams.clipPlanes = [Gf.Vec4d(i) for i in + gfCamera.clippingPlanes] + if self._nodes: GL.glColor3f(1.0,1.0,1.0) From dc10f824f2acf4e3346075b5de5ef3b930e1a43e Mon Sep 17 00:00:00 2001 From: takahito-tejima Date: Thu, 8 Sep 2016 11:29:38 -0700 Subject: [PATCH 112/380] [Hd] fix bug of non-rprim change tracking HdChangeTracker::isDirty should only be used for Rprim, since it masks Varying bit out, thus it can't be used for camera, light and draw target. adding a unit test to move a light. (Internal change: 1653275) --- pxr/imaging/lib/hd/renderIndex.cpp | 4 ++-- pxr/imaging/lib/hdx/unitTestDelegate.cpp | 18 ++++++++++++++++++ 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/pxr/imaging/lib/hd/renderIndex.cpp b/pxr/imaging/lib/hd/renderIndex.cpp index d23233489e..417c079c6e 100644 --- a/pxr/imaging/lib/hd/renderIndex.cpp +++ b/pxr/imaging/lib/hd/renderIndex.cpp @@ -1037,7 +1037,7 @@ void HdRenderIndex::SyncSprims() { TF_FOR_ALL(it, _sprimMap) { - if (HdChangeTracker::IsDirty(_tracker.GetSprimDirtyBits(it->first))) { + if (_tracker.GetSprimDirtyBits(it->first) != HdChangeTracker::Clean) { it->second->Sync(); _tracker.MarkSprimClean(it->first); @@ -1050,7 +1050,7 @@ void HdRenderIndex::SyncDrawTargets() { TF_FOR_ALL(it, _drawTargetMap) { - if (HdChangeTracker::IsDirty(_tracker.GetDrawTargetDirtyBits(it->first))) { + if (_tracker.GetDrawTargetDirtyBits(it->first) != HdChangeTracker::Clean) { it->second->Sync(); _tracker.MarkDrawTargetClean(it->first); diff --git a/pxr/imaging/lib/hdx/unitTestDelegate.cpp b/pxr/imaging/lib/hdx/unitTestDelegate.cpp index cd87f7b408..f640ad5184 100644 --- a/pxr/imaging/lib/hdx/unitTestDelegate.cpp +++ b/pxr/imaging/lib/hdx/unitTestDelegate.cpp @@ -200,6 +200,24 @@ Hdx_UnitTestDelegate::SetLight(SdfPath const &id, TfToken const &key, { _ValueCache &cache = _valueCacheMap[id]; cache[key] = value; + if (key == HdxLightTokens->params) { + // update shadow matrix too + GlfSimpleLight light = value.Get(); + HdxShadowParams shadowParams + = cache[HdxLightTokens->shadowParams].Get(); + shadowParams.shadowMatrix + = HdxShadowMatrixComputationSharedPtr(new ShadowMatrix(light)); + + GetRenderIndex().GetChangeTracker().MarkSprimDirty( + id, HdxLight::DirtyParams|HdxLight::DirtyShadowParams); + cache[HdxLightTokens->shadowParams] = shadowParams; + } else if (key == HdxLightTokens->transform) { + GetRenderIndex().GetChangeTracker().MarkSprimDirty( + id, HdxLight::DirtyTransform); + } else if (key == HdxLightTokens->shadowCollection) { + GetRenderIndex().GetChangeTracker().MarkSprimDirty( + id, HdxLight::DirtyCollection); + } } void From fc0604ad0d908799fa5406fd618548e8b07ecc7d Mon Sep 17 00:00:00 2001 From: jloy Date: Thu, 8 Sep 2016 11:29:55 -0700 Subject: [PATCH 113/380] Tf: allow TF_SUPPORTS_WEAKPTR to be applied to final classes. The previous implementation of __GetTfWeakBase__ member detection (Tf_HasGetWeakBase) relied on being able to derive from T. However, this is not allowed for final classes, resulting in a compilation error when putting instances of a final class into a TfAny. In addition to supporting final classes, there are two other changes in behavior: 1. Classes with a private or protected __GetTfWeakBase__ are no longer considered to support TfWeakPtr. 2. Classes with a member function named __GetTfWeakBase__ that does not match the required signature are no longer considered to support TfWeakPtr. The tests have been moved to the TfWeakPtr unit test so they will be run whenever tests are built. There is no runtime component; the unit test will simply fail to build. (Internal change: 1653331) --- pxr/base/lib/tf/testenv/weakPtr.cpp | 49 ++++++++++++++++++++ pxr/base/lib/tf/weakPtr.cpp | 30 ------------ pxr/base/lib/tf/weakPtr.h | 71 ++++++++++++----------------- 3 files changed, 79 insertions(+), 71 deletions(-) diff --git a/pxr/base/lib/tf/testenv/weakPtr.cpp b/pxr/base/lib/tf/testenv/weakPtr.cpp index cf3804c6aa..284b7a851f 100644 --- a/pxr/base/lib/tf/testenv/weakPtr.cpp +++ b/pxr/base/lib/tf/testenv/weakPtr.cpp @@ -391,3 +391,52 @@ Test_TfWeakPtrConversion() { TF_ADD_REGTEST(TfWeakPtr); TF_ADD_REGTEST(TfCreateRefPtrFromProtectedWeakPtr); TF_ADD_REGTEST(TfWeakPtrConversion); + +//////////////////////////////////////////////////////////////////////// + +// Compile-time testing of the Tf_SUPPORTS_WEAKPTR mechanism. +namespace +{ + struct Tf_TestHasGetWeakBase + { + TfWeakBase const &__GetTfWeakBase__() const; + }; + + struct Tf_TestHasGetWeakBaseDerived : public Tf_TestHasGetWeakBase + { + }; + + struct Tf_TestHasGetWeakBaseNot + { + }; + + struct Tf_TestIsWeakBase : public TfWeakBase + { + }; + + struct Tf_TestGetWeakBaseWrongSignature + { + void __GetTfWeakBase__() const; + }; + + class Tf_TestGetWeakBasePrivate + { + private: + const TfWeakBase& __GetTfWeakBase__() const; + }; + + class Tf_TestGetWeakBaseProtected + { + protected: + const TfWeakBase& __GetTfWeakBase__() const; + }; + + static_assert(TF_SUPPORTS_WEAKPTR(Tf_TestHasGetWeakBase), ""); + static_assert(TF_SUPPORTS_WEAKPTR(Tf_TestHasGetWeakBaseDerived), ""); + static_assert(!TF_SUPPORTS_WEAKPTR(Tf_TestHasGetWeakBaseNot), ""); + static_assert(!TF_SUPPORTS_WEAKPTR(TfWeakPtr), ""); + static_assert(!TF_SUPPORTS_WEAKPTR(Tf_TestGetWeakBaseWrongSignature), ""); + static_assert(!TF_SUPPORTS_WEAKPTR(Tf_TestGetWeakBasePrivate), ""); + static_assert(!TF_SUPPORTS_WEAKPTR(Tf_TestGetWeakBaseProtected), ""); + static_assert(!TF_SUPPORTS_WEAKPTR(int), ""); +} diff --git a/pxr/base/lib/tf/weakPtr.cpp b/pxr/base/lib/tf/weakPtr.cpp index 0bd93112b9..037c299537 100644 --- a/pxr/base/lib/tf/weakPtr.cpp +++ b/pxr/base/lib/tf/weakPtr.cpp @@ -22,33 +22,3 @@ // language governing permissions and limitations under the Apache License. // #include "pxr/base/tf/weakPtr.h" - -/* - * Compile-time testing of the Tf_SupportsWeakPtr mechanism. Change the 0 - * to 1 to enable. - */ -#if 0 - -#include - -struct _Tf_TestHasGetWeakBase { - TfWeakBase const &__GetTfWeakBase__() const; -}; - -struct _Tf_TestHasGetWeakBaseDerived : public _Tf_TestHasGetWeakBase -{ -}; - -struct _Tf_TestHasGetWeakBaseNot -{ -}; - -struct _Tf_TestIsWeakBase : public TfWeakBase -{ -}; - -BOOST_STATIC_ASSERT(TF_SUPPORTS_WEAKPTR(_Tf_TestHasGetWeakBase)); -BOOST_STATIC_ASSERT(TF_SUPPORTS_WEAKPTR(_Tf_TestHasGetWeakBaseDerived)); -BOOST_STATIC_ASSERT(not TF_SUPPORTS_WEAKPTR(_Tf_TestHasGetWeakBaseNot)); -BOOST_STATIC_ASSERT(not TF_SUPPORTS_WEAKPTR(TfWeakPtr<_Tf_TestIsWeakBase>)); -#endif // testing Tf_SupportsWeakPtr. diff --git a/pxr/base/lib/tf/weakPtr.h b/pxr/base/lib/tf/weakPtr.h index 79d44e23f7..8687d060e6 100644 --- a/pxr/base/lib/tf/weakPtr.h +++ b/pxr/base/lib/tf/weakPtr.h @@ -42,6 +42,7 @@ #include #include +#include class TfHash; template class TfRefPtr; @@ -388,52 +389,40 @@ class TfWeakPtr { // A mechanism to determine whether a class type has a method // __GetTfWeakBase__ with the correct signature. // -// The main idea is as follows. Given a type T to test, we derive a new type -// _Base that inherits T and a _BaseMixin class. The _BaseMixin class -// provides an implementation of __GetTfWeakBase__. Then we use sizeof() on a -// call expression to the function _Deduce with a single _Base* argument. -// _Deduce has two possible overloads; one for an affirmative answer -// (returning _YesType) and one for a negative answer (returning _NoType). -// The overloads are chosen by SFINAE. In the _NoType case, there is an extra -// parameter of type _Helper * with a default argument NULL. This overload is -// only chosen when Base's __GetTfWeakBase__ method comes from _BaseMixin, -// which means that there was no other __GetTfWeakBase__ in the method -// resolution order. If there was a __GetTfWeakBase__ from another class in -// the method resolution order, the _YesType overload of _Deduce would be -// preferred. Since the call expression's result type's size depends on which -// overload was chosen, we can use this to answer the question of whether the -// query type T has a __GetTfWeakBase__ or not. +// _HasSig can only be called with a pointer-to-member-function that matches +// the desired signature of __GetTfWeakBase__. +// +// _Deduce has two possible overloads. The first overload's return value uses +// expression SFINAE to detect if a call to _HasSig(&T::__GetTfWeakBase__) is +// well-formed. If so, the overload's return type is the return type of +// _HasSig, specifically std::true_type. The second _Deduce overload returns +// std::false_type and is viable for all types. // -template -struct Tf_HasGetWeakBase : public boost::mpl::false_ -{ -}; - template -struct Tf_HasGetWeakBase< - T, typename boost::enable_if >::type> +struct Tf_HasGetWeakBase { private: - struct _YesType { char m; }; - struct _NoType { _YesType m[2];}; - struct _BaseMixin { - TfWeakBase const &__GetTfWeakBase__() const { - return *((TfWeakBase *)(0)); - } - }; - struct _Base : public T, public _BaseMixin { ~_Base(); }; - template class _Helper{}; - template - static _NoType - _Deduce(V*, _Helper* = 0); - static _YesType _Deduce(...); + + // The required method signature of __GetTfWeakBase__ for implementations + // of the weak pointable interface. + template + using _SignatureOf__GetTfWeakBase__ = TfWeakBase const & (U::*)() const; + + template + static std::true_type + _HasSig(_SignatureOf__GetTfWeakBase__); + + template + static decltype(_HasSig(&U::__GetTfWeakBase__)) + _Deduce(U*); + + static std::false_type + _Deduce(...); + public: - typedef Tf_HasGetWeakBase type; - typedef bool value_type; - BOOST_STATIC_CONSTANT(bool, - value = sizeof(_YesType) == sizeof(_Deduce((_Base*)(0)))); + using type = decltype(_Deduce(static_cast(nullptr))); + using value_type = bool; + static const bool value = type::value; }; template From 61dd70700adbbcb32ba0702bbd127f90a8cfa2fb Mon Sep 17 00:00:00 2001 From: sunyab Date: Thu, 8 Sep 2016 12:06:53 -0700 Subject: [PATCH 114/380] Skip building X11-specific object on Mac (Internal change: 1653383) --- pxr/imaging/lib/glf/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pxr/imaging/lib/glf/CMakeLists.txt b/pxr/imaging/lib/glf/CMakeLists.txt index 8ed607c080..6aff7c7c33 100644 --- a/pxr/imaging/lib/glf/CMakeLists.txt +++ b/pxr/imaging/lib/glf/CMakeLists.txt @@ -2,7 +2,7 @@ set(PXR_PREFIX pxr/imaging) set(PXR_PACKAGE glf) set(optionalPublicClasses "") -if (X11_FOUND) +if (X11_FOUND AND NOT APPLE) list(APPEND optionalPublicClasses testGLContext) endif() From 6549b6d92fc8ec82f0437fb9e053fbe7df44a0f7 Mon Sep 17 00:00:00 2001 From: mattyjams Date: Fri, 9 Sep 2016 11:45:33 -0700 Subject: [PATCH 115/380] remove now defunct -attrprefix option to usdExport The AlembicChaser added in change 1623955 can provide this functionality instead. (Internal change: 1653386) --- third_party/maya/lib/usdMaya/usdExport.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/third_party/maya/lib/usdMaya/usdExport.cpp b/third_party/maya/lib/usdMaya/usdExport.cpp index 052868db8b..70ff9d3c9a 100644 --- a/third_party/maya/lib/usdMaya/usdExport.cpp +++ b/third_party/maya/lib/usdMaya/usdExport.cpp @@ -77,9 +77,6 @@ MSyntax usdExport::createSyntax() syntax.addFlag("-a" , "-append" , MSyntax::kBoolean); syntax.addFlag("-f" , "-file" , MSyntax::kString); - syntax.addFlag("-atp" , "-attrprefix", MSyntax::kString); - syntax.makeFlagMultiUse("-attrprefix"); - syntax.addFlag("-chr" , "-chaser", MSyntax::kString); syntax.makeFlagMultiUse("-chaser"); From 3c08ca2bfafc2c91e9658c3a9831da029c34de6e Mon Sep 17 00:00:00 2001 From: blevin Date: Fri, 9 Sep 2016 11:45:42 -0700 Subject: [PATCH 116/380] Pcp: Remove redundant tracking of "used asset paths". This information is already available and (more richly represented) in the prim index and error structures. Furthermore, there is some unspecified nuance involved in what it means to be "used", so move that policy downstream to the one (internal) client. Removing this saves a bit of storage: a pointer in every PcpPrimIndex plus any allocated std::vectors. (Internal change: 1653580) --- pxr/usd/lib/pcp/primIndex.cpp | 82 ----------------------------------- pxr/usd/lib/pcp/primIndex.h | 19 -------- 2 files changed, 101 deletions(-) diff --git a/pxr/usd/lib/pcp/primIndex.cpp b/pxr/usd/lib/pcp/primIndex.cpp index 769402a4fe..d1a3aacd1e 100644 --- a/pxr/usd/lib/pcp/primIndex.cpp +++ b/pxr/usd/lib/pcp/primIndex.cpp @@ -143,11 +143,6 @@ PcpPrimIndex::PcpPrimIndex(const PcpPrimIndex &rhs) if (rhs._localErrors) { _localErrors.reset(new PcpErrorVector(*rhs._localErrors.get())); } - - if (rhs._usedAssetPaths) { - _usedAssetPaths.reset( - new std::vector(*rhs._usedAssetPaths.get())); - } } void @@ -156,64 +151,6 @@ PcpPrimIndex::Swap(PcpPrimIndex& rhs) _graph.swap(rhs._graph); _primStack.swap(rhs._primStack); _localErrors.swap(rhs._localErrors); - _usedAssetPaths.swap(rhs._usedAssetPaths); -} - -void -PcpPrimIndex::AddUsedAssetPath( - const string& assetPath) -{ - if (assetPath.empty()) - return; - - if (not _usedAssetPaths) { - _usedAssetPaths.reset(new vector(1, assetPath)); - return; - } - - vector::iterator it = - std::lower_bound(_usedAssetPaths->begin(), _usedAssetPaths->end(), - assetPath); - if (it == _usedAssetPaths->end() or *it != assetPath) { - _usedAssetPaths->insert(it, assetPath); - } -} - -void -PcpPrimIndex::AddUsedAssetPaths( - const vector& assetPaths) -{ - if (assetPaths.empty()) - return; - - if (not _usedAssetPaths) { - _usedAssetPaths.reset(new vector); - } - - const size_t prevNumPaths = _usedAssetPaths->size(); - _usedAssetPaths->insert( - _usedAssetPaths->end(), assetPaths.begin(), assetPaths.end()); - - // Since _usedAssetPaths is always maintained in sorted order, - // we can just sort the newly-added elements and inplace_merge them - // with pre-existing entries. - std::sort( - _usedAssetPaths->begin() + prevNumPaths, _usedAssetPaths->end()); - std::inplace_merge( - _usedAssetPaths->begin(), - _usedAssetPaths->begin() + prevNumPaths, - _usedAssetPaths->end()); - - // Ensure uniqueness. - _usedAssetPaths->erase( - std::unique(_usedAssetPaths->begin(), _usedAssetPaths->end()), - _usedAssetPaths->end()); -} - -vector -PcpPrimIndex::GetUsedAssetPaths() const -{ - return _usedAssetPaths ? *_usedAssetPaths : vector(); } void @@ -1441,8 +1378,6 @@ _AddArc( TfStringify(site).c_str()); // Pass along the other outputs from the nested computation. - indexer->outputs->primIndex.AddUsedAssetPaths( - childOutputs.primIndex.GetUsedAssetPaths()); indexer->outputs->dependencies.sites.insert( childOutputs.dependencies.sites.begin(), childOutputs.dependencies.sites.end()); @@ -1673,19 +1608,12 @@ _EvalNodeReferences( const bool isInternalReference = ref.GetAssetPath().empty(); if (isInternalReference) { refLayer = node.GetLayerStack()->GetIdentifier().rootLayer; - index->AddUsedAssetPath(refLayer->GetIdentifier()); - refLayerStack = node.GetLayerStack(); } else { std::string canonicalMutedLayerId; if (indexer->inputs.cache->IsLayerMuted( srcLayer, ref.GetAssetPath(), &canonicalMutedLayerId)) { - // Record the used asset path the same way we would have - // had this layer not been muted. - index->AddUsedAssetPath(SdfComputeAssetPathRelativeToLayer( - srcLayer, ref.GetAssetPath())); - PcpErrorMutedAssetPathPtr err = PcpErrorMutedAssetPath::New(); err->rootSite = PcpSite(node.GetRootNode().GetSite()); err->site = PcpSite(node.GetSite()); @@ -1702,7 +1630,6 @@ _EvalNodeReferences( refLayer = SdfFindOrOpenRelativeToLayer( srcLayer, &resolvedAssetPath, Pcp_GetArgumentsForTargetSchema(indexer->inputs.targetSchema)); - index->AddUsedAssetPath(resolvedAssetPath); if (not refLayer) { PcpErrorInvalidAssetPathPtr err = @@ -3439,11 +3366,6 @@ _EvalNodePayload( if (indexer->inputs.cache->IsLayerMuted( payloadSpecLayer, payload.GetAssetPath(), &canonicalMutedLayerId)) { - // Record the used asset path the same way we would have - // had this layer not been muted. - index->AddUsedAssetPath(SdfComputeAssetPathRelativeToLayer( - payloadSpecLayer, payload.GetAssetPath())); - PcpErrorMutedAssetPathPtr err = PcpErrorMutedAssetPath::New(); err->rootSite = PcpSite(node.GetSite()); err->site = PcpSite(node.GetSite()); @@ -3471,10 +3393,6 @@ _EvalNodePayload( SdfLayerRefPtr payloadLayer = SdfFindOrOpenRelativeToLayer( payloadSpecLayer, &resolvedAssetPath, args); - // Record used asset path (even if we were unable to open it, - // we need to acknowledge it as a requested dependency) - index->AddUsedAssetPath(resolvedAssetPath); - if (not payloadLayer) { PcpErrorInvalidAssetPathPtr err = PcpErrorInvalidAssetPath::New(); err->rootSite = PcpSite(node.GetRootNode().GetSite()); diff --git a/pxr/usd/lib/pcp/primIndex.h b/pxr/usd/lib/pcp/primIndex.h index 3898023dd4..163702d9c7 100644 --- a/pxr/usd/lib/pcp/primIndex.h +++ b/pxr/usd/lib/pcp/primIndex.h @@ -138,18 +138,6 @@ class PcpPrimIndex /// \see PcpInstanceKey bool IsInstanceable() const; - /// Get the set of asset paths used by direct arcs in this prim. - /// This set does not include asset paths used by ancestral arcs - /// (from namespace ancestors), which may also contribute opinions - /// to this prim. It also includes any asset paths that were - /// requested by arcs, but could not be resolved. - std::vector GetUsedAssetPaths() const; - - /// Record a used asset path. - /// Only meant for internal use while constructing a PcpPrimIndex. - void AddUsedAssetPath(const std::string& assetPath); - void AddUsedAssetPaths(const std::vector& assetPaths); - /// \name Iteration /// @{ @@ -266,13 +254,6 @@ class PcpPrimIndex // List of errors local to this prim, encountered during computation. // NULL if no errors were found (the expected common case). boost::scoped_ptr _localErrors; - - // List of asset paths directly used by this prim. - // This data cannot be derived purely from the - // graph since it includes asset paths that failed to resolve, - // and consequently did not contribute any nodes to the graph. - // NULL if this list is empty (the expected common case). - boost::scoped_ptr > _usedAssetPaths; }; /// Free function version for generic code and ADL. From 487d16e8b0a6c85cdebcb1ba1a3bd42664cc1214 Mon Sep 17 00:00:00 2001 From: mrawde Date: Fri, 9 Sep 2016 11:46:43 -0700 Subject: [PATCH 117/380] Add test for shaderAdapter. Note, the baseline here adds in some cases that are known to be broken. (Internal change: 1653649) --- .../lib/usdImaging/unitTestGLDrawing.cpp | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/pxr/usdImaging/lib/usdImaging/unitTestGLDrawing.cpp b/pxr/usdImaging/lib/usdImaging/unitTestGLDrawing.cpp index 4b07e60cea..b638b46e5f 100644 --- a/pxr/usdImaging/lib/usdImaging/unitTestGLDrawing.cpp +++ b/pxr/usdImaging/lib/usdImaging/unitTestGLDrawing.cpp @@ -31,6 +31,9 @@ #include "pxr/base/arch/attributes.h" #include "pxr/base/gf/vec2i.h" +#include "pxr/base/plug/registry.h" +#include "pxr/base/arch/systemInfo.h" + #include #include #include @@ -38,6 +41,18 @@ #include #include +static void UsdImaging_UnitTestHelper_InitPlugins() +{ + // Unfortunately, in order to properly find plugins in our test setup, we + // need to know where the test is running. + std::string testDir = TfGetPathName(ArchGetExecutablePath()); + std::string pluginDir = TfStringCatPaths(testDir, + "UsdImagingPlugins/lib/UsdImagingTest.framework/Resources"); + printf("registering plugins in: %s\n", pluginDir.c_str()); + + PlugRegistry::GetInstance().RegisterPlugins(pluginDir); +} + //////////////////////////////////////////////////////////// static QGLFormat @@ -456,6 +471,8 @@ UsdImaging_UnitTestGLDrawing::RunTest(int argc, char *argv[]) { QApplication app(argc, argv); + UsdImaging_UnitTestHelper_InitPlugins(); + _Args args; _Parse(argc, argv, &args); From 12c10b6a35077db2df2259779eaf97b694da9b66 Mon Sep 17 00:00:00 2001 From: sunyab Date: Fri, 9 Sep 2016 11:46:56 -0700 Subject: [PATCH 118/380] Update Travis configuration Use OpenSubdiv 3.0.5, which matches the required version specified in the README.md. Also use -j instead of -j 4 per recommendations from Travis support. (Internal change: 1653780) --- .travis.yml | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/.travis.yml b/.travis.yml index cd3a4cb2fb..bc1e919711 100644 --- a/.travis.yml +++ b/.travis.yml @@ -88,12 +88,12 @@ install: ### GLEW 1.10.0 - sudo apt-get install libglew-dev - ### OpenSubdiv 3.0.0 + ### OpenSubdiv 3.0.5 - sudo apt-get install libxrandr-dev libxcursor-dev libxinerama-dev libglfw-dev - if [ ! -d "$HOME/osd/lib" ]; then - wget https://github.com/PixarAnimationStudios/OpenSubdiv/archive/v3_0_0.tar.gz -O /tmp/osd.tgz; + wget https://github.com/PixarAnimationStudios/OpenSubdiv/archive/v3_0_5.tar.gz -O /tmp/osd.tgz; tar -xvzf /tmp/osd.tgz -C $HOME; - pushd $HOME/OpenSubdiv-3_0_0; + pushd $HOME/OpenSubdiv-3_0_5; mkdir build && cd build; cmake -DCMAKE_INSTALL_PREFIX=$HOME/osd -DNO_EXAMPLES=1 -DNO_TUTORIALS=1 -DNO_REGRESSION=1 -D NO_MAYA=1 -D NO_PTEX=1 -D NO_DOC=1 -D NO_OMP=1 -D NO_TBB=1 -D NO_CUDA=1 -D NO_OPENCL=1 -D NO_CLEW=1 ..; make && make install; @@ -149,10 +149,9 @@ cache: script: - mkdir build && cd build - cmake -DTBB_ROOT_DIR=$HOME/tbb43_20141023oss -DOPENEXR_LOCATION=$HOME/openexr -DOIIO_LOCATION=$HOME/oiio -DOPENSUBDIV_ROOT_DIR=$HOME/osd -DPTEX_LOCATION=$HOME/ptex -DPXR_VALIDATE_GENERATED_CODE=OFF .. - - echo 'Building with -j4' # XXX: Need to explicitly build cameraUtil before hd due to missing dependency declaration. # This is fixed in commit 880b04. - - make -j4 cameraUtil - - make -j4 + - make -j cameraUtil + - make -j # Default install location is /usr/local; we need sudo access to write there. - sudo make install From fe62e4636e84477a86a882b9ae35862507fea82c Mon Sep 17 00:00:00 2001 From: George ElKoura Date: Sun, 11 Sep 2016 14:10:19 -0700 Subject: [PATCH 119/380] Fix missed merge. --- pxr/base/lib/arch/api.h | 4 ---- 1 file changed, 4 deletions(-) diff --git a/pxr/base/lib/arch/api.h b/pxr/base/lib/arch/api.h index bc9dd28e2b..463af444a2 100644 --- a/pxr/base/lib/arch/api.h +++ b/pxr/base/lib/arch/api.h @@ -21,10 +21,6 @@ // KIND, either express or implied. See the Apache License for the specific // language governing permissions and limitations under the Apache License. // -<<<<<<< HEAD - -======= ->>>>>>> cc6709e473450bb8271115fd82550da96ac5007f #ifndef ARCH_API_H #define ARCH_API_H From 8e948a4a159082d40963a929f031f540b40e437c Mon Sep 17 00:00:00 2001 From: George ElKoura Date: Sun, 11 Sep 2016 20:42:12 -0700 Subject: [PATCH 120/380] More merging of conflicts. --- pxr/usd/lib/usd/stage.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/pxr/usd/lib/usd/stage.cpp b/pxr/usd/lib/usd/stage.cpp index 43a88d117f..a002f7523d 100644 --- a/pxr/usd/lib/usd/stage.cpp +++ b/pxr/usd/lib/usd/stage.cpp @@ -1132,7 +1132,7 @@ _ValueContainsBlock(const SdfAbstractDataValue* value) bool _ValueContainsBlock(const SdfAbstractDataConstValue* value) { - constexpr const std::type_info& valueBlockTypeId(typeid(SdfValueBlock)); + const std::type_info& valueBlockTypeId(typeid(SdfValueBlock)); return value and value->valueType == valueBlockTypeId; } @@ -3310,19 +3310,19 @@ UsdStage::_ComposePrimIndexesInParallel( _cache->ComputePrimIndexesInParallel( primIndexPaths, &errs, _NameChildrenPred(_instanceCache.get()), [](const SdfPath &) { return true; }, - "Usd", _mallocTagID); + "Usd", _mallocTagID.c_str()); } else if (includeRule == _IncludeNoDiscoveredPayloads) { _cache->ComputePrimIndexesInParallel( primIndexPaths, &errs, _NameChildrenPred(_instanceCache.get()), [](const SdfPath &) { return false; }, - "Usd", _mallocTagID); + "Usd", _mallocTagID.c_str()); } else if (includeRule == _IncludeNewPayloadsIfAncestorWasIncluded) { _cache->ComputePrimIndexesInParallel( primIndexPaths, &errs, _NameChildrenPred(_instanceCache.get()), _IncludeNewlyDiscoveredPayloadsPredicate(this), - "Usd", _mallocTagID); + "Usd", _mallocTagID.c_str()); } if (not errs.empty()) { From b33df9ddb5805875f8accb201754a7b1d7c077db Mon Sep 17 00:00:00 2001 From: George ElKoura Date: Sun, 11 Sep 2016 21:20:25 -0700 Subject: [PATCH 121/380] Merge unitTestDelegate.cpp --- pxr/imaging/lib/hd/unitTestDelegate.cpp | 22 ---------------------- 1 file changed, 22 deletions(-) diff --git a/pxr/imaging/lib/hd/unitTestDelegate.cpp b/pxr/imaging/lib/hd/unitTestDelegate.cpp index 678a0efe69..70b6473f13 100644 --- a/pxr/imaging/lib/hd/unitTestDelegate.cpp +++ b/pxr/imaging/lib/hd/unitTestDelegate.cpp @@ -258,28 +258,6 @@ Hd_UnitTestDelegate::AddTexture(SdfPath const& id, _textures[id] = _Texture(texture); } -void -Hd_UnitTestDelegate::AddCamera(SdfPath const &id) -{ - HdRenderIndex& index = GetRenderIndex(); - index.InsertCamera(this, id); - _cameras[id].params[HdShaderTokens->worldToViewMatrix] - = VtValue(GfMatrix4d(1)); - _cameras[id].params[HdShaderTokens->projectionMatrix] - = VtValue(GfMatrix4d(1)); -} - -void -Hd_UnitTestDelegate::AddLight(SdfPath const &id) -{ - HdRenderIndex& index = GetRenderIndex(); - index.InsertLight(this, id); - _lights[id].params[HdTokens->lightParams] - = VtValue(GlfSimpleLight()); - _lights[id].params[HdTokens->lightShadowCollection] - = VtValue(HdRprimCollection(HdTokens->geometry, HdTokens->hull)); -} - void Hd_UnitTestDelegate::HideRprim(SdfPath const& id) { From f32853c0927612849b1975f15e56b8adb4c45e9b Mon Sep 17 00:00:00 2001 From: George ElKoura Date: Mon, 12 Sep 2016 00:34:52 -0700 Subject: [PATCH 122/380] More in-progress merging of dev. --- pxr/imaging/lib/hd/renderIndex.h | 70 ++-------------------------- pxr/usd/lib/usd/crateFile.h | 8 ++-- pxr/usd/lib/usdUI/nodeGraphNodeAPI.h | 4 ++ 3 files changed, 12 insertions(+), 70 deletions(-) diff --git a/pxr/imaging/lib/hd/renderIndex.h b/pxr/imaging/lib/hd/renderIndex.h index 1e50c74867..14a92c76cb 100644 --- a/pxr/imaging/lib/hd/renderIndex.h +++ b/pxr/imaging/lib/hd/renderIndex.h @@ -91,12 +91,6 @@ class HdRenderIndex : public boost::noncopyable { HDLIB_API HdDrawItemView GetDrawItems(HdRprimCollection const& collection); -<<<<<<< HEAD - HDLIB_API - HdLightView GetLights(); - -======= ->>>>>>> cc6709e473450bb8271115fd82550da96ac5007f /// Returns a list of all draw targets in the render index. HDLIB_API HdDrawTargetView GetDrawTargets(); @@ -109,27 +103,14 @@ class HdRenderIndex : public boost::noncopyable { HDLIB_API void SyncAll(); -<<<<<<< HEAD - /// Synchronize all cameras in the render index - HDLIB_API - void SyncCameras(); - - /// Synchronize all lights in the render index - HDLIB_API - void SyncLights(); - -======= ->>>>>>> cc6709e473450bb8271115fd82550da96ac5007f /// Synchronize all draw targets in the render index HDLIB_API void SyncDrawTargets(); -<<<<<<< HEAD -======= /// Synchronize all scene states in the render index + HDLIB_API void SyncSprims(); ->>>>>>> cc6709e473450bb8271115fd82550da96ac5007f /// Returns a vector of Rprim IDs that are bound to the given DelegateID. HDLIB_API SdfPathVector const& GetDelegateRprimIDs(SdfPath const& delegateID) const; @@ -277,49 +258,21 @@ class HdRenderIndex : public boost::noncopyable { HdTextureSharedPtr const& GetTexture(SdfPath const& id) const; // ---------------------------------------------------------------------- // -<<<<<<< HEAD - /// \name Camera Support - // ---------------------------------------------------------------------- // - - /// Inserts a new camera into the RenderIndex with an identifier of \p id. - template - void - InsertCamera(HdSceneDelegate* delegate, SdfPath const& id); - - /// Removes the given camera from the RenderIndex. - HDLIB_API - void RemoveCamera(SdfPath const& id); - - /// Returns the camera for the given \p id. - HDLIB_API - HdCameraSharedPtr const& GetCamera(SdfPath const& id) const; - - // ---------------------------------------------------------------------- // - /// \name Light Support -======= /// \name Scene state prims (e.g. camera, light) ->>>>>>> cc6709e473450bb8271115fd82550da96ac5007f // ---------------------------------------------------------------------- // template void InsertSprim(HdSceneDelegate* delegate, SdfPath const &id); + HDLIB_API void RemoveSprim(SdfPath const &id); -<<<<<<< HEAD - /// Removes the given light from the RenderIndex. - HDLIB_API - void RemoveLight(SdfPath const& id); - - /// Returns the light for the given \p id. - HDLIB_API - HdLightSharedPtr const& GetLight(SdfPath const& id) const; -======= + HDLIB_API HdSprimSharedPtr const &GetSprim(SdfPath const &id) const; /// Returns the subtree rooted under the given path. + HDLIB_API SdfPathVector GetSprimSubtree(SdfPath const& root) const; ->>>>>>> cc6709e473450bb8271115fd82550da96ac5007f // ---------------------------------------------------------------------- // /// \name Draw Target Support @@ -374,21 +327,6 @@ class HdRenderIndex : public boost::noncopyable { SdfPath const& textureId, HdTextureSharedPtr const& texture); -<<<<<<< HEAD - // Inserts the camera into the index and updates tracking state. - HDLIB_API - void _TrackDelegateCamera(HdSceneDelegate* delegate, - SdfPath const& cameraId, - HdCameraSharedPtr const& camera); - - // Inserts the light into the index and updates tracking state. - HDLIB_API - void _TrackDelegateLight(HdSceneDelegate* delegate, - SdfPath const& lightId, - HdLightSharedPtr const& light); - -======= ->>>>>>> cc6709e473450bb8271115fd82550da96ac5007f // Inserts the draw target into the index and updates tracking state. HDLIB_API void _TrackDelegateDrawTarget(HdSceneDelegate* delegate, diff --git a/pxr/usd/lib/usd/crateFile.h b/pxr/usd/lib/usd/crateFile.h index 97d8b493ea..e5611fbcb5 100644 --- a/pxr/usd/lib/usd/crateFile.h +++ b/pxr/usd/lib/usd/crateFile.h @@ -148,7 +148,7 @@ struct ValueRep { }; template <> struct _IsBitwiseReadWrite : std::true_type {}; -class TimeSamples { +struct TimeSamples { public: typedef Usd_Shared> SharedTimes; @@ -267,7 +267,7 @@ struct _Hasher { class CrateFile { public: - class Version; + struct Version; private: struct _Fcloser { @@ -302,8 +302,8 @@ class CrateFile }; public: - friend class ValueRep; - friend class TimeSamples; + friend struct ValueRep; + friend struct TimeSamples; typedef std::pair FieldValuePair; diff --git a/pxr/usd/lib/usdUI/nodeGraphNodeAPI.h b/pxr/usd/lib/usdUI/nodeGraphNodeAPI.h index 5b0d12dab0..eea24bd125 100644 --- a/pxr/usd/lib/usdUI/nodeGraphNodeAPI.h +++ b/pxr/usd/lib/usdUI/nodeGraphNodeAPI.h @@ -216,6 +216,7 @@ class UsdUINodeGraphNodeAPI : public UsdSchemaBase /// \n Usd Type: SdfValueTypeNames->Asset /// \n Variability: SdfVariabilityUniform /// \n Fallback Value: No Fallback + USDUI_API UsdAttribute GetIconAttr() const; /// See GetIconAttr(), and also @@ -223,6 +224,7 @@ class UsdUINodeGraphNodeAPI : public UsdSchemaBase /// If specified, author \p defaultValue as the attribute's default, /// sparsely (when it makes sense to do so) if \p writeSparsely is \c true - /// the default for \p writeSparsely is \c false. + USDUI_API UsdAttribute CreateIconAttr(VtValue const &defaultValue = VtValue(), bool writeSparsely=false) const; public: @@ -241,6 +243,7 @@ class UsdUINodeGraphNodeAPI : public UsdSchemaBase /// \n Variability: SdfVariabilityUniform /// \n Fallback Value: No Fallback /// \n \ref UsdUITokens "Allowed Values": [open, closed, minimized] + USDUI_API UsdAttribute GetExpansionStateAttr() const; /// See GetExpansionStateAttr(), and also @@ -248,6 +251,7 @@ class UsdUINodeGraphNodeAPI : public UsdSchemaBase /// If specified, author \p defaultValue as the attribute's default, /// sparsely (when it makes sense to do so) if \p writeSparsely is \c true - /// the default for \p writeSparsely is \c false. + USDUI_API UsdAttribute CreateExpansionStateAttr(VtValue const &defaultValue = VtValue(), bool writeSparsely=false) const; public: From 67cae1466a8131d8f77d8d2d86fea351f4e30ba3 Mon Sep 17 00:00:00 2001 From: George ElKoura Date: Mon, 12 Sep 2016 20:32:28 -0700 Subject: [PATCH 123/380] Add missing export symbols macro for hdx. --- pxr/imaging/lib/hdx/camera.h | 7 ++++++- pxr/imaging/lib/hdx/light.h | 6 +++++- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/pxr/imaging/lib/hdx/camera.h b/pxr/imaging/lib/hdx/camera.h index dee9404768..ee107e5c21 100644 --- a/pxr/imaging/lib/hdx/camera.h +++ b/pxr/imaging/lib/hdx/camera.h @@ -24,6 +24,8 @@ #ifndef HDX_CAMERA_H #define HDX_CAMERA_H +#include "pxr/imaging/hdx/api.h" + #include "pxr/imaging/hd/version.h" #include "pxr/imaging/hd/sprim.h" @@ -42,7 +44,7 @@ (projectionMatrix) \ (windowPolicy) -TF_DECLARE_PUBLIC_TOKENS(HdxCameraTokens, HDX_CAMERA_TOKENS); +TF_DECLARE_PUBLIC_TOKENS(HdxCameraTokens, HDXLIB_API, HDX_CAMERA_TOKENS); class HdSceneDelegate; typedef boost::shared_ptr HdxCameraSharedPtr; @@ -55,7 +57,10 @@ class HdxCamera : public HdSprim { public: typedef std::vector ClipPlanesVector; + HDXLIB_API HdxCamera(HdSceneDelegate* delegate, SdfPath const & id); + + HDLIB_API ~HdxCamera(); // note: not virtual (for now) // change tracking for HdxLight diff --git a/pxr/imaging/lib/hdx/light.h b/pxr/imaging/lib/hdx/light.h index 593b78ab41..1e31442cfa 100644 --- a/pxr/imaging/lib/hdx/light.h +++ b/pxr/imaging/lib/hdx/light.h @@ -24,6 +24,8 @@ #ifndef HDX_LIGHT_H #define HDX_LIGHT_H +#include "pxr/imaging/hdx/api.h" + #include "pxr/imaging/hd/version.h" #include "pxr/imaging/hd/sprim.h" @@ -41,7 +43,7 @@ (shadowParams) \ (transform) -TF_DECLARE_PUBLIC_TOKENS(HdxLightTokens, HDX_LIGHT_TOKENS); +TF_DECLARE_PUBLIC_TOKENS(HdxLightTokens, HDXLIB_API, HDX_LIGHT_TOKENS); class HdSceneDelegate; typedef boost::shared_ptr HdxLightSharedPtr; @@ -53,7 +55,9 @@ typedef std::vector HdxLightSharedPtrVector; /// class HdxLight : public HdSprim { public: + HDXLIB_API HdxLight(HdSceneDelegate* delegate, SdfPath const & id); + HDXLIB_API virtual ~HdxLight(); // change tracking for HdxLight From a2b5361d81e2e71019fee9cd661631e24d3f7036 Mon Sep 17 00:00:00 2001 From: George ElKoura Date: Mon, 12 Sep 2016 20:35:29 -0700 Subject: [PATCH 124/380] Add missing export symbols for hd. --- pxr/imaging/lib/hd/changeTracker.h | 5 +++++ pxr/imaging/lib/hd/lightingShader.h | 3 +++ pxr/imaging/lib/hd/renderIndex.h | 1 + pxr/imaging/lib/hd/shader.h | 4 ++++ 4 files changed, 13 insertions(+) diff --git a/pxr/imaging/lib/hd/changeTracker.h b/pxr/imaging/lib/hd/changeTracker.h index 7a49fdc0e1..3854f7717d 100644 --- a/pxr/imaging/lib/hd/changeTracker.h +++ b/pxr/imaging/lib/hd/changeTracker.h @@ -438,18 +438,23 @@ class HdChangeTracker : public boost::noncopyable { // ---------------------------------------------------------------------- // /// Start tracking sprim with the given \p id. + HDLIB_API void SprimInserted(SdfPath const& id, int initialDirtyState); /// Stop tracking sprim with the given \p id. + HDLIB_API void SprimRemoved(SdfPath const& id); /// Get the dirty bits for sprim with the given \p id. + HDLIB_API DirtyBits GetSprimDirtyBits(SdfPath const& id); /// Set the dirty flags to \p bits. + HDLIB_API void MarkSprimDirty(SdfPath const& id, DirtyBits bits); /// Set the dirty flags to \p newBits. + HDLIB_API void MarkSprimClean(SdfPath const& id, DirtyBits newBits=Clean); // ---------------------------------------------------------------------- // diff --git a/pxr/imaging/lib/hd/lightingShader.h b/pxr/imaging/lib/hd/lightingShader.h index b7120cad16..cfed382c18 100644 --- a/pxr/imaging/lib/hd/lightingShader.h +++ b/pxr/imaging/lib/hd/lightingShader.h @@ -24,6 +24,7 @@ #ifndef HD_LIGHTING_SHADER_H #define HD_LIGHTING_SHADER_H +#include "pxr/imaging/hd/api.h" #include "pxr/imaging/hd/version.h" #include "pxr/imaging/hd/shader.h" #include "pxr/base/gf/matrix4d.h" @@ -38,7 +39,9 @@ typedef boost::shared_ptr HdLightingShaderSharedPtr; /// class HdLightingShader : public HdShader { public: + HDLIB_API HdLightingShader(); + HDLIB_API virtual ~HdLightingShader(); /// Sets camera state. diff --git a/pxr/imaging/lib/hd/renderIndex.h b/pxr/imaging/lib/hd/renderIndex.h index 14a92c76cb..9be99e63c9 100644 --- a/pxr/imaging/lib/hd/renderIndex.h +++ b/pxr/imaging/lib/hd/renderIndex.h @@ -334,6 +334,7 @@ class HdRenderIndex : public boost::noncopyable { HdDrawTargetSharedPtr const& drawTarget); // Inserts the scene state prim into the index and updates tracking state. + HDLIB_API void _TrackDelegateSprim(HdSceneDelegate* delegate, SdfPath const& id, HdSprimSharedPtr const& state, diff --git a/pxr/imaging/lib/hd/shader.h b/pxr/imaging/lib/hd/shader.h index a479d02122..e154c0c42c 100644 --- a/pxr/imaging/lib/hd/shader.h +++ b/pxr/imaging/lib/hd/shader.h @@ -24,6 +24,7 @@ #ifndef HD_SHADER_H #define HD_SHADER_H +#include "pxr/imaging/hd/api.h" #include "pxr/imaging/hd/version.h" #include "pxr/imaging/hd/resourceBinder.h" // XXX: including a private class @@ -67,6 +68,7 @@ class HdShader { // XXX: Should be pure-virtual /// Returns the shader parameters for this shader. + HDLIB_API virtual HdShaderParamVector const& GetParams() const; struct TextureDescriptor { @@ -79,11 +81,13 @@ class HdShader { typedef std::vector TextureDescriptorVector; // XXX: DOC + HDLIB_API virtual TextureDescriptorVector GetTextures() const; // XXX: Should be pure-virtual /// Returns a buffer which stores parameter fallback values and texture /// handles. + HDLIB_API virtual HdBufferArrayRangeSharedPtr const& GetShaderData() const; /// Binds shader-specific resources to \a program From 1ab6533561674e5ff9fc3640fa23b7543d6d689b Mon Sep 17 00:00:00 2001 From: George ElKoura Date: Wed, 14 Sep 2016 22:05:14 -0700 Subject: [PATCH 125/380] Fix up more merge conflicts. --- pxr/imaging/lib/hdx/drawTargetTask.cpp | 1 - pxr/imaging/lib/hdx/drawTargetTask.h | 1 - 2 files changed, 2 deletions(-) diff --git a/pxr/imaging/lib/hdx/drawTargetTask.cpp b/pxr/imaging/lib/hdx/drawTargetTask.cpp index a63ea84521..ea89dab612 100644 --- a/pxr/imaging/lib/hdx/drawTargetTask.cpp +++ b/pxr/imaging/lib/hdx/drawTargetTask.cpp @@ -32,7 +32,6 @@ #include "pxr/imaging/hdx/tokens.h" #include "pxr/imaging/hdx/debugCodes.h" -#include "pxr/imaging/hd/camera.h" #include "pxr/imaging/hd/drawTarget.h" #include "pxr/imaging/hd/drawTargetRenderPass.h" #include "pxr/imaging/hd/renderPassState.h" diff --git a/pxr/imaging/lib/hdx/drawTargetTask.h b/pxr/imaging/lib/hdx/drawTargetTask.h index f4cc33a2ad..e7d4e2964a 100644 --- a/pxr/imaging/lib/hdx/drawTargetTask.h +++ b/pxr/imaging/lib/hdx/drawTargetTask.h @@ -28,7 +28,6 @@ #include "pxr/imaging/hd/task.h" #include "pxr/imaging/hd/drawTargetRenderPass.h" -#include "pxr/imaging/hd/simpleLightingShader.h" #include "pxr/base/gf/vec2f.h" #include "pxr/base/gf/vec4f.h" From 0d3e5d1d55034aac06777362625d9c0bbe1e33b1 Mon Sep 17 00:00:00 2001 From: gitamohr Date: Fri, 16 Sep 2016 17:02:33 -0700 Subject: [PATCH 126/380] usd: Add UsdTimeCode::SafeStep(maxValue, maxCompression) to produce a delta value that's robust over a range under shifts and scales. Also mark some UsdTimeCode members constexpr that can be. (Internal change: 1653849) --- pxr/usd/lib/usd/timeCode.h | 21 ++++++++++++++++++--- pxr/usd/lib/usd/wrapTimeCode.cpp | 4 ++++ 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/pxr/usd/lib/usd/timeCode.h b/pxr/usd/lib/usd/timeCode.h index 44af7e7356..739c875a74 100644 --- a/pxr/usd/lib/usd/timeCode.h +++ b/pxr/usd/lib/usd/timeCode.h @@ -70,7 +70,7 @@ class UsdTimeCode { public: /// Construct with optional time value. Impilicitly convert from double. - UsdTimeCode(double t = 0.0) : _value(t) { } + constexpr UsdTimeCode(double t = 0.0) : _value(t) {} /// Produce a UsdTimeCode representing the lowest/earliest possible /// timeCode. Thus, for any given timeSample \em s, its time ordinate @@ -80,7 +80,7 @@ class UsdTimeCode { /// timeSample for an attribute, as they can use UsdTimeCode::EarliestTime() /// as the \em time argument to UsdAttribute::Get() and /// UsdAttribute::GetBracketingTimeSamples() - static UsdTimeCode EarliestTime() { + static constexpr UsdTimeCode EarliestTime() { return UsdTimeCode(std::numeric_limits::lowest()); } @@ -91,10 +91,25 @@ class UsdTimeCode { /// in UsdAttribute value resolution, the sample at Default() (if any) is /// always weaker than any numeric timeSample in the same layer. For /// more information, see \ref Usd_ValueResolution - static UsdTimeCode Default() { + static constexpr UsdTimeCode Default() { return UsdTimeCode(std::numeric_limits::quiet_NaN()); } + /// Produce a safe step value such that for any numeric UsdTimeCode t in + /// [-maxValue, maxValue], t +/- (step / maxCompression) != t with a safety + /// factor of 2. This is shorthand for + /// std::numeric_limits::epsilon() * maxValue * maxCompression * + /// 2.0. Such a step value is recommended for simulating jump + /// discontinuities in time samples. For example, author value x at time t, + /// and value y at time t + SafeStep(). This ensures that as the sample + /// times are shifted and scaled, t and t + SafeStep() remain distinct so + /// long as they adhere to the \p maxValue and \p maxCompression limits. + static constexpr double + SafeStep(double maxValue=1e6, double maxCompression=10.0) { + return std::numeric_limits::epsilon() * + maxValue * maxCompression * 2.0; + } + /// Return true if this time represents the 'default' sentinel value, false /// otherwise. This is equivalent to !IsNumeric(). bool IsDefault() const { diff --git a/pxr/usd/lib/usd/wrapTimeCode.cpp b/pxr/usd/lib/usd/wrapTimeCode.cpp index 24a3b42a7a..72b9826ffe 100644 --- a/pxr/usd/lib/usd/wrapTimeCode.cpp +++ b/pxr/usd/lib/usd/wrapTimeCode.cpp @@ -58,6 +58,10 @@ void wrapUsdTimeCode() .def("Default", &UsdTimeCode::Default) .staticmethod("Default") + .def("SafeStep", &UsdTimeCode::SafeStep, + (arg("maxValue")=1e6, arg("maxCompression")=10.0)) + .staticmethod("SafeStep") + .def("IsDefault", &UsdTimeCode::IsDefault) .def("IsNumeric", &UsdTimeCode::IsNumeric) .def("GetValue", &UsdTimeCode::GetValue) From cdf68e5ad289393f1dd21ea5209b923cfaeae9aa Mon Sep 17 00:00:00 2001 From: superfunc Date: Fri, 16 Sep 2016 17:30:30 -0700 Subject: [PATCH 127/380] [Usd] Fix for bracketing time sample code in Usd in the presence of flat time segments. This occurs when two consecutive stage times map to the same clip time. (Internal change: 1653961) --- pxr/usd/lib/usd/clip.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/pxr/usd/lib/usd/clip.cpp b/pxr/usd/lib/usd/clip.cpp index a604641bf8..5950587aab 100644 --- a/pxr/usd/lib/usd/clip.cpp +++ b/pxr/usd/lib/usd/clip.cpp @@ -546,7 +546,13 @@ Usd_Clip::ListTimeSamplesForPath(const SdfAbstractDataSpecId& id) const const TimeMapping& m2 = times[i+1]; if (m1.second <= t and t <= m2.second) { - timeSamples.insert(_TranslateTimeToExternal(t, m1, m2)); + if (m1.second == m2.second) { + timeSamples.insert(m1.first); + timeSamples.insert(m2.first); + } + else { + timeSamples.insert(_TranslateTimeToExternal(t, m1, m2)); + } } } } From e3177536843da516d019d42f26253691f9b53963 Mon Sep 17 00:00:00 2001 From: takahito-tejima Date: Fri, 16 Sep 2016 17:30:43 -0700 Subject: [PATCH 128/380] [Hd] packed normals This change adds support of packed format for vertex normals. GL_INT_2_10_10_10_REV will be used as a vertex normal format by default for the coarse (unrefined and unquadrangulated) vertex normals. It reduces 20~30% of GPU memory consumption in typical cases. One caveat though: if we use uniform subdivision (which is default now), we refine the coarse smooth normals to the dense mesh as an approximation. This refinement is done by OpenSubdiv as a primvar refinement, which only supports single-precision float currently. We use float as before if a mesh needs to be refined, however, if the mesh has already been drawn with packed normals for the coarse level, additional 32bit float normals will be populated instead of sharing same buffers between coarse and dense mesh. It results in consuming more memory than not using packed type at all. This happens when a prim is initialized with packed and then is requested to draw as refined. If the prim is initialized with 32bit float normals from the beginning, packed normals will never be used for that prim (same footprint as before). We'd like to avoid this problem by enabling adaptive subdivision. (it's desirable for memory anyway) adding HD_ENABLE_PACKED_NORMALS (defaults to 1) for better future bug triage. (Internal change: 1653962) --- pxr/imaging/lib/hd/bufferResource.cpp | 2 + pxr/imaging/lib/hd/conversions.cpp | 4 +- pxr/imaging/lib/hd/glUtils.h | 40 +++++++++++- pxr/imaging/lib/hd/mesh.cpp | 67 ++++++++++++++++---- pxr/imaging/lib/hd/mesh.h | 4 ++ pxr/imaging/lib/hd/resourceBinder.cpp | 25 +++++++- pxr/imaging/lib/hd/shaders/meshNormal.glslfx | 6 ++ pxr/imaging/lib/hd/smoothNormals.cpp | 58 ++++++++++++----- pxr/imaging/lib/hd/smoothNormals.h | 4 +- pxr/imaging/lib/hd/tokens.h | 1 + pxr/imaging/lib/hd/vboMemoryManager.cpp | 12 ++-- pxr/imaging/lib/hd/vertexAdjacency.cpp | 59 +++++++++++------ pxr/imaging/lib/hd/vertexAdjacency.h | 8 ++- pxr/imaging/lib/hd/vtBufferSource.cpp | 2 + pxr/imaging/lib/hd/vtBufferSource.h | 6 +- 15 files changed, 233 insertions(+), 65 deletions(-) diff --git a/pxr/imaging/lib/hd/bufferResource.cpp b/pxr/imaging/lib/hd/bufferResource.cpp index e9dfd1ab68..4ce7cda256 100644 --- a/pxr/imaging/lib/hd/bufferResource.cpp +++ b/pxr/imaging/lib/hd/bufferResource.cpp @@ -167,6 +167,8 @@ HdBufferResource::GetGLTypeName() const return _tokens->uvec2; } else if (_glDataType == GL_INT_SAMPLER_BUFFER) { return _tokens->uvec2; + } else if (_glDataType == GL_INT_2_10_10_10_REV) { + return _tokens->vec4; } TF_CODING_ERROR("unsupported type: 0x%x numComponents = %d\n", diff --git a/pxr/imaging/lib/hd/conversions.cpp b/pxr/imaging/lib/hd/conversions.cpp index 7b3a60c5cb..83667a7f28 100644 --- a/pxr/imaging/lib/hd/conversions.cpp +++ b/pxr/imaging/lib/hd/conversions.cpp @@ -84,6 +84,8 @@ HdConversions::GetComponentSize(int glDataType) return sizeof(GLuint64EXT); case GL_DOUBLE: return sizeof(GLdouble); + case GL_INT_2_10_10_10_REV: + return sizeof(GLint); // following enums are for bindless texture pointers. case GL_SAMPLER_2D: return sizeof(GLuint64EXT); @@ -93,7 +95,7 @@ HdConversions::GetComponentSize(int glDataType) return sizeof(GLuint64EXT); }; - TF_CODING_ERROR("Unexpected GL datatype %d", glDataType); + TF_CODING_ERROR("Unexpected GL datatype 0x%x", glDataType); return 1; } diff --git a/pxr/imaging/lib/hd/glUtils.h b/pxr/imaging/lib/hd/glUtils.h index 52f62df5e0..79efe9cc07 100644 --- a/pxr/imaging/lib/hd/glUtils.h +++ b/pxr/imaging/lib/hd/glUtils.h @@ -27,7 +27,45 @@ #include "pxr/imaging/hd/version.h" #include "pxr/base/vt/value.h" -// XXX: could be moved into GlopUtils +#include +#include + +struct HdVec4f_2_10_10_10_REV { + // we treat packed type as single-component values + static const size_t dimension = 1; + + HdVec4f_2_10_10_10_REV() { } + + template + HdVec4f_2_10_10_10_REV(Vec3Type const &value) { + x = to10bits(value[0]); + y = to10bits(value[1]); + z = to10bits(value[2]); + w = 0; + } + + // ref. GL spec 2.3.5.2 + // Conversion from floating point to normalized fixed point + template + int to10bits(R v) { + return int( + std::round( + std::min(std::max(v, static_cast(-1)), static_cast(1)) + *static_cast(511))); + } + + bool operator==(const HdVec4f_2_10_10_10_REV &other) const { + return (other.w == w and + other.z == z and + other.y == y and + other.x == x); + } + + int x : 10; + int y : 10; + int z : 10; + int w : 2; +}; class HdGLUtils { public: diff --git a/pxr/imaging/lib/hd/mesh.cpp b/pxr/imaging/lib/hd/mesh.cpp index e80543d6db..9a1a6597f1 100644 --- a/pxr/imaging/lib/hd/mesh.cpp +++ b/pxr/imaging/lib/hd/mesh.cpp @@ -52,6 +52,8 @@ TF_DEFINE_ENV_SETTING(HD_ENABLE_SMOOTH_NORMALS, "CPU", TF_DEFINE_ENV_SETTING(HD_ENABLE_QUADRANGULATE, "0", "Enable quadrangulation (0/CPU/GPU)"); TF_DEFINE_ENV_SETTING(HD_ENABLE_REFINE_GPU, 0, "GPU refinement"); +TF_DEFINE_ENV_SETTING(HD_ENABLE_PACKED_NORMALS, 1, + "Use packed normals"); // static repr configuration HdMesh::_MeshReprConfig HdMesh::_reprDescConfig; @@ -62,6 +64,7 @@ HdMesh::HdMesh(HdSceneDelegate* delegate, SdfPath const& id, , _topologyId(0) , _customDirtyBitsInUse(0) , _doubleSided(false) + , _packedNormals(IsEnabledPackedNormals()) , _cullStyle(HdCullStyleDontCare) { /*NOTHING*/ @@ -71,25 +74,40 @@ HdMesh::HdMesh(HdSceneDelegate* delegate, SdfPath const& id, bool HdMesh::IsEnabledSmoothNormalsGPU() { - return TfGetEnvSetting(HD_ENABLE_SMOOTH_NORMALS) == "GPU"; + static bool enabled = (TfGetEnvSetting(HD_ENABLE_SMOOTH_NORMALS) == "GPU"); + return enabled; } +/* static */ bool HdMesh::IsEnabledQuadrangulationCPU() { - return TfGetEnvSetting(HD_ENABLE_QUADRANGULATE) == "CPU"; + static bool enabled = (TfGetEnvSetting(HD_ENABLE_QUADRANGULATE) == "CPU"); + return enabled; } +/* static */ bool HdMesh::IsEnabledQuadrangulationGPU() { - return TfGetEnvSetting(HD_ENABLE_QUADRANGULATE) == "GPU"; + static bool enabled = (TfGetEnvSetting(HD_ENABLE_QUADRANGULATE) == "GPU"); + return enabled; } +/* static */ bool HdMesh::IsEnabledRefineGPU() { - return TfGetEnvSetting(HD_ENABLE_REFINE_GPU) == 1; + static bool enabled = (TfGetEnvSetting(HD_ENABLE_REFINE_GPU) == 1); + return enabled; +} + +/* static */ +bool +HdMesh::IsEnabledPackedNormals() +{ + static bool enabled = (TfGetEnvSetting(HD_ENABLE_PACKED_NORMALS) == 1); + return enabled; } int @@ -554,16 +572,37 @@ HdMesh::_PopulateVertexPrimVars(HdDrawItem *drawItem, if (cpuSmoothNormals) { if (points) { // CPU smooth normals depends on CPU adjacency. - HdBufferSourceSharedPtr normal = - _vertexAdjacency->GetSmoothNormalsComputation( - points, HdTokens->normals); - - if (refineLevel > 0) { - normal = _RefinePrimVar(normal, /*varying=*/false, - &computations, _topology); - } else if (_UsePtexIndices()) { - normal = _QuadrangulatePrimVar( - normal, &computations, _topology, GetId()); + // + HdBufferSourceSharedPtr normal; + bool doRefine = (refineLevel > 0); + bool doQuadrangulate = _UsePtexIndices(); + + if (doRefine or doQuadrangulate) { + if (_packedNormals) { + // we can't use packed normals for refined/quad, + // let's migrate the buffer to full precision + isNew = true; + _packedNormals = false; + } + normal = _vertexAdjacency->GetSmoothNormalsComputation( + points, HdTokens->normals); + if (doRefine) { + normal = _RefinePrimVar(normal, /*varying=*/false, + &computations, _topology); + } else if (doQuadrangulate) { + normal = _QuadrangulatePrimVar( + normal, &computations, _topology, GetId()); + } + } else { + // if we haven't refined or quadrangulated normals, + // may use packed format if enabled. + if (_packedNormals) { + normal = _vertexAdjacency->GetSmoothNormalsComputation( + points, HdTokens->packedNormals, true); + } else { + normal = _vertexAdjacency->GetSmoothNormalsComputation( + points, HdTokens->normals, false); + } } sources.push_back(normal); } diff --git a/pxr/imaging/lib/hd/mesh.h b/pxr/imaging/lib/hd/mesh.h index 94c24c6fa3..cccc34e68c 100644 --- a/pxr/imaging/lib/hd/mesh.h +++ b/pxr/imaging/lib/hd/mesh.h @@ -94,6 +94,9 @@ class HdMesh : public HdRprim { /// Returns whether GPU refinement is enabled or not. static bool IsEnabledRefineGPU(); + /// Returns whether packed (10_10_10 bits) normals to be used + static bool IsEnabledPackedNormals(); + /// Configure geometric style of drawItems for \p reprName /// HdMesh can have up to 2 descriptors for some complex styling /// (FeyRay, Outline) @@ -168,6 +171,7 @@ class HdMesh : public HdRprim { HdTopology::ID _topologyId; int _customDirtyBitsInUse; bool _doubleSided; + bool _packedNormals; HdCullStyle _cullStyle; typedef _ReprDescConfigs _MeshReprConfig; diff --git a/pxr/imaging/lib/hd/resourceBinder.cpp b/pxr/imaging/lib/hd/resourceBinder.cpp index ec494bfa0a..e8c4506519 100644 --- a/pxr/imaging/lib/hd/resourceBinder.cpp +++ b/pxr/imaging/lib/hd/resourceBinder.cpp @@ -95,6 +95,24 @@ namespace { int attribLocation; int textureUnit; }; + + static inline GLboolean _ShouldBeNormalized(int GLdataType) + { + if (GLdataType == GL_INT_2_10_10_10_REV or + GLdataType == GL_UNSIGNED_INT_2_10_10_10_REV) { + return GL_TRUE; + } + return GL_FALSE; + } + static inline int _GetNumComponents(int numComponents, int GLdataType) + { + if (GLdataType == GL_INT_2_10_10_10_REV or + GLdataType == GL_UNSIGNED_INT_2_10_10_10_REV) { + return 4; + } else { + return numComponents; + } + } } Hd_ResourceBinder::Hd_ResourceBinder() @@ -507,9 +525,10 @@ Hd_ResourceBinder::BindBuffer(TfToken const &name, case HdBinding::VERTEX_ATTR: glBindBuffer(GL_ARRAY_BUFFER, buffer->GetId()); glVertexAttribPointer(loc, - buffer->GetNumComponents(), + _GetNumComponents(buffer->GetNumComponents(), + buffer->GetGLDataType()), buffer->GetGLDataType(), - GL_FALSE, + _ShouldBeNormalized(buffer->GetGLDataType()), buffer->GetStride(), offsetPtr); glBindBuffer(GL_ARRAY_BUFFER, 0); @@ -566,7 +585,7 @@ Hd_ResourceBinder::BindBuffer(TfToken const &name, // at least in nvidia driver 346.59, this query call doesn't show // any pipeline stall. if (not glIsNamedBufferResidentNV(buffer->GetId())) { - glMakeNamedBufferResidentNV(buffer->GetId(), GL_READ_ONLY); + glMakeNamedBufferResidentNV(buffer->GetId(), GL_READ_WRITE); } glUniformui64NV(loc, buffer->GetGPUAddress()); break; diff --git a/pxr/imaging/lib/hd/shaders/meshNormal.glslfx b/pxr/imaging/lib/hd/shaders/meshNormal.glslfx index 0b1f24b909..8f93945081 100644 --- a/pxr/imaging/lib/hd/shaders/meshNormal.glslfx +++ b/pxr/imaging/lib/hd/shaders/meshNormal.glslfx @@ -67,7 +67,13 @@ vec3 GetQuadGeometryNormal(vec3 vertexNormal, vec3 GetVertexNormal() { // get normal from vertex attribute +#if defined(HD_HAS_normals) return vec3(HdGet_normals().xyz); +#elif defined(HD_HAS_packedNormals) + return vec3(HdGet_packedNormals().xyz); +#else + return vec3(0); +#endif } vec3 GetTriGeometryNormal(vec3 vertexNormal, diff --git a/pxr/imaging/lib/hd/smoothNormals.cpp b/pxr/imaging/lib/hd/smoothNormals.cpp index e291e2d21d..01543b0fd7 100644 --- a/pxr/imaging/lib/hd/smoothNormals.cpp +++ b/pxr/imaging/lib/hd/smoothNormals.cpp @@ -42,9 +42,10 @@ Hd_SmoothNormalsComputation::Hd_SmoothNormalsComputation( Hd_VertexAdjacency const *adjacency, HdBufferSourceSharedPtr const &points, TfToken const &dstName, - HdBufferSourceSharedPtr const &adjacencyBuilder) + HdBufferSourceSharedPtr const &adjacencyBuilder, + bool packed) : _adjacency(adjacency), _points(points), _dstName(dstName), - _adjacencyBuilder(adjacencyBuilder) + _adjacencyBuilder(adjacencyBuilder), _packed(packed) { } @@ -53,8 +54,8 @@ Hd_SmoothNormalsComputation::AddBufferSpecs(HdBufferSpecVector *specs) const { // the datatype of normals is same as points (float or double). specs->push_back(HdBufferSpec(_dstName, - _points->GetGLComponentDataType(), - 3)); + GetGLComponentDataType(), + (_packed ? 1 : 3))); } TfToken const & @@ -66,7 +67,11 @@ Hd_SmoothNormalsComputation::GetName() const int Hd_SmoothNormalsComputation::GetGLComponentDataType() const { - return _points->GetGLComponentDataType(); + if (_packed) { + return GL_INT_2_10_10_10_REV; + } else { + return _points->GetGLComponentDataType(); + } } bool @@ -89,22 +94,41 @@ Hd_SmoothNormalsComputation::Resolve() int numPoints = _points->GetNumElements(); HdBufferSourceSharedPtr normals; + switch (_points->GetGLElementDataType()) { case GL_FLOAT_VEC3: - normals = HdBufferSourceSharedPtr( - new HdVtBufferSource( - _dstName, VtValue( - _adjacency->ComputeSmoothNormals( - numPoints, - static_cast(_points->GetData()))))); + if (_packed) { + normals = HdBufferSourceSharedPtr( + new HdVtBufferSource( + _dstName, VtValue( + _adjacency->ComputeSmoothNormalsPacked( + numPoints, + static_cast(_points->GetData()))))); + } else { + normals = HdBufferSourceSharedPtr( + new HdVtBufferSource( + _dstName, VtValue( + _adjacency->ComputeSmoothNormals( + numPoints, + static_cast(_points->GetData()))))); + } break; case GL_DOUBLE_VEC3: - normals = HdBufferSourceSharedPtr( - new HdVtBufferSource( - _dstName, VtValue( - _adjacency->ComputeSmoothNormals( - numPoints, - static_cast(_points->GetData()))))); + if (_packed) { + normals = HdBufferSourceSharedPtr( + new HdVtBufferSource( + _dstName, VtValue( + _adjacency->ComputeSmoothNormalsPacked( + numPoints, + static_cast(_points->GetData()))))); + } else { + normals = HdBufferSourceSharedPtr( + new HdVtBufferSource( + _dstName, VtValue( + _adjacency->ComputeSmoothNormals( + numPoints, + static_cast(_points->GetData()))))); + } break; default: TF_CODING_ERROR("Unsupported points type for computing smooth normals"); diff --git a/pxr/imaging/lib/hd/smoothNormals.h b/pxr/imaging/lib/hd/smoothNormals.h index 45c9e42951..f58f338909 100644 --- a/pxr/imaging/lib/hd/smoothNormals.h +++ b/pxr/imaging/lib/hd/smoothNormals.h @@ -44,7 +44,8 @@ class Hd_SmoothNormalsComputation : public HdComputedBufferSource { Hd_SmoothNormalsComputation(Hd_VertexAdjacency const *adjacency, HdBufferSourceSharedPtr const &points, TfToken const &dstName, - HdBufferSourceSharedPtr const &adjacencyBuilder); + HdBufferSourceSharedPtr const &adjacencyBuilder, + bool packed); /// overrides virtual void AddBufferSpecs(HdBufferSpecVector *specs) const; @@ -60,6 +61,7 @@ class Hd_SmoothNormalsComputation : public HdComputedBufferSource { HdBufferSourceSharedPtr _points; TfToken _dstName; HdBufferSourceSharedPtr _adjacencyBuilder; + bool _packed; }; /// smooth normal computation GPU diff --git a/pxr/imaging/lib/hd/tokens.h b/pxr/imaging/lib/hd/tokens.h index f0bcbea5e7..f94961c346 100644 --- a/pxr/imaging/lib/hd/tokens.h +++ b/pxr/imaging/lib/hd/tokens.h @@ -79,6 +79,7 @@ (linear) \ (nonperiodic) \ (normals) \ + (packedNormals) \ (params) \ (patchParam) \ (periodic) \ diff --git a/pxr/imaging/lib/hd/vboMemoryManager.cpp b/pxr/imaging/lib/hd/vboMemoryManager.cpp index 56cca66e33..65d05f323e 100644 --- a/pxr/imaging/lib/hd/vboMemoryManager.cpp +++ b/pxr/imaging/lib/hd/vboMemoryManager.cpp @@ -498,14 +498,18 @@ HdVBOMemoryManager::_StripedBufferArrayRange::CopyData( HdBufferResourceSharedPtr VBO = _stripedBufferArray->GetResource(bufferSource->GetName()); - if (not VBO or VBO->GetId() == 0) { - TF_CODING_ERROR("VBO doesn't exist for %s", - bufferSource->GetName().GetText()); + if (not TF_VERIFY((VBO and VBO->GetId()), + "VBO doesn't exist for %s", + bufferSource->GetName().GetText())) { return; } // datatype of bufferSource has to match with bufferResource - if (not TF_VERIFY(bufferSource->GetGLComponentDataType() == VBO->GetGLDataType()) or + if (not TF_VERIFY(bufferSource->GetGLComponentDataType() == VBO->GetGLDataType(), + "%s: 0x%x != 0x%x\n", + bufferSource->GetName().GetText(), + bufferSource->GetGLComponentDataType(), + VBO->GetGLDataType()) or not TF_VERIFY(bufferSource->GetNumComponents() == VBO->GetNumComponents(), "%s: %d != %d\n", bufferSource->GetName().GetText(), diff --git a/pxr/imaging/lib/hd/vertexAdjacency.cpp b/pxr/imaging/lib/hd/vertexAdjacency.cpp index d9c716796a..8bf94cfb1f 100644 --- a/pxr/imaging/lib/hd/vertexAdjacency.cpp +++ b/pxr/imaging/lib/hd/vertexAdjacency.cpp @@ -33,14 +33,14 @@ Hd_VertexAdjacency::Hd_VertexAdjacency() { } -template +template class _SmoothNormalsWorker { public: - _SmoothNormalsWorker(Vec3Type const * pointsPtr, + _SmoothNormalsWorker(SrcVec3Type const * pointsPtr, std::vector const &entry, int stride, - VtArray *normals) + DstType *normals) : _pointsPtr(pointsPtr) , _entry(entry) , _stride(stride) @@ -53,34 +53,34 @@ class _SmoothNormalsWorker for(size_t i = begin; i < end; ++i) { int const * e = &_entry[i * _stride]; int valence = *e++; - Vec3Type normal(0); - Vec3Type const & curr = _pointsPtr[i]; + SrcVec3Type normal(0); + SrcVec3Type const & curr = _pointsPtr[i]; for (int j=0; j const &_entry; int _stride; - VtArray *_normals; + DstType *_normals; }; /// Returns an array of the same size and type as the source points /// containing normal vectors computed by averaging the cross products /// of incident face edges. -template -VtArray -_ComputeSmoothNormals(int numPoints, Vec3Type const * pointsPtr, +template +VtArray +_ComputeSmoothNormals(int numPoints, SrcVec3Type const * pointsPtr, std::vector const &entry, int stride) { // to be safe. @@ -89,14 +89,15 @@ _ComputeSmoothNormals(int numPoints, Vec3Type const * pointsPtr, numPoints = std::min(numPoints, (int)entry.size()/stride); - VtArray normals(numPoints); + VtArray normals(numPoints); - _SmoothNormalsWorker workerState - (pointsPtr, entry, stride, &normals); + _SmoothNormalsWorker workerState + (pointsPtr, entry, stride, normals.data()); - WorkParallelForN(numPoints, - boost::bind(&_SmoothNormalsWorker::Compute, - workerState, _1, _2)); + WorkParallelForN( + numPoints, + boost::bind(&_SmoothNormalsWorker::Compute, + workerState, _1, _2)); @@ -119,16 +120,32 @@ Hd_VertexAdjacency::ComputeSmoothNormals(int numPoints, _entry, _stride); } +VtArray +Hd_VertexAdjacency::ComputeSmoothNormalsPacked(int numPoints, + GfVec3f const * pointsPtr) const +{ + return _ComputeSmoothNormals( + numPoints, pointsPtr, _entry, _stride); +} + +VtArray +Hd_VertexAdjacency::ComputeSmoothNormalsPacked(int numPoints, + GfVec3d const * pointsPtr) const +{ + return _ComputeSmoothNormals( + numPoints, pointsPtr, _entry, _stride); +} + HdBufferSourceSharedPtr Hd_VertexAdjacency::GetSmoothNormalsComputation( HdBufferSourceSharedPtr const &points, - TfToken const &dstName) + TfToken const &dstName, bool packed) { // if the vertex adjacency is scheduled to be built (and not yet resolved), // make a dependency to its builder. return HdBufferSourceSharedPtr( new Hd_SmoothNormalsComputation( - this, points, dstName, _adjacencyBuilder.lock())); + this, points, dstName, _adjacencyBuilder.lock(), packed)); } HdComputationSharedPtr diff --git a/pxr/imaging/lib/hd/vertexAdjacency.h b/pxr/imaging/lib/hd/vertexAdjacency.h index ea59b9ea9b..e2a2c91ad3 100644 --- a/pxr/imaging/lib/hd/vertexAdjacency.h +++ b/pxr/imaging/lib/hd/vertexAdjacency.h @@ -29,6 +29,7 @@ #include "pxr/imaging/hd/bufferArrayRange.h" #include "pxr/imaging/hd/bufferSource.h" #include "pxr/imaging/hd/computation.h" +#include "pxr/imaging/hd/glUtils.h" #include "pxr/base/gf/vec3d.h" #include "pxr/base/gf/vec3f.h" @@ -68,6 +69,10 @@ class Hd_VertexAdjacency { GfVec3f const * pointsPtr) const; VtArray ComputeSmoothNormals(int numPoints, GfVec3d const * pointsPtr) const; + VtArray ComputeSmoothNormalsPacked(int numPoints, + GfVec3f const * pointsPtr) const; + VtArray ComputeSmoothNormalsPacked(int numPoints, + GfVec3d const * pointsPtr) const; /// Returns the adjacency builder computation. /// This computaions generates adjacency table on CPU. @@ -88,7 +93,8 @@ class Hd_VertexAdjacency { /// produced by AdjacencyBuilderComputation. HdBufferSourceSharedPtr GetSmoothNormalsComputation( HdBufferSourceSharedPtr const &points, - TfToken const &dstName); + TfToken const &dstName, + bool packed=false); /// Returns the smooth normal computation on GPU. /// This computation requires adjacency table on GPU produced by diff --git a/pxr/imaging/lib/hd/vtBufferSource.cpp b/pxr/imaging/lib/hd/vtBufferSource.cpp index 3ab1addcd9..2c9a4d4c94 100644 --- a/pxr/imaging/lib/hd/vtBufferSource.cpp +++ b/pxr/imaging/lib/hd/vtBufferSource.cpp @@ -135,6 +135,8 @@ template<> _GLDataType _GetGLType() { return _GLDataType(GL_DOUBLE, GL_DOUBLE_MAT4); } template<> _GLDataType _GetGLType() { return _GLDataType(GL_INT, GL_INT); } +template<> _GLDataType _GetGLType() + { return _GLDataType(GL_INT_2_10_10_10_REV, GL_INT_2_10_10_10_REV); } // XXX: we don't have BOOST_TTI_HAS_MEMBER_DATA yet. (requires boost 1.54) diff --git a/pxr/imaging/lib/hd/vtBufferSource.h b/pxr/imaging/lib/hd/vtBufferSource.h index 0b1a06e688..ea95b47ad0 100644 --- a/pxr/imaging/lib/hd/vtBufferSource.h +++ b/pxr/imaging/lib/hd/vtBufferSource.h @@ -38,13 +38,14 @@ #include "pxr/base/gf/vec4i.h" #include "pxr/imaging/hd/version.h" #include "pxr/imaging/hd/bufferSource.h" +#include "pxr/imaging/hd/glUtils.h" #include "pxr/imaging/hd/patchIndex.h" #include "pxr/base/vt/value.h" #include #include #include -#include +#include #include @@ -75,7 +76,7 @@ class HdVtBufferSource : public HdBufferSource { }; // The valid types a HdBufferSource can be constructed from. - typedef boost::mpl::vector30< + typedef boost::mpl::vector31< THolder, THolder, THolder, @@ -103,6 +104,7 @@ class HdVtBufferSource : public HdBufferSource { THolder, THolder, THolder, + THolder >, THolder >, THolder >, THolder > From 76c46e34f46ceda90edb1a6ec6579953e1cc9627 Mon Sep 17 00:00:00 2001 From: spiffmon Date: Fri, 16 Sep 2016 17:31:23 -0700 Subject: [PATCH 129/380] Add "proxyPrim" relationship to UsdGeomImageable schema, and convenience method SetProxyPrim(). Also provide computation UsdGeomImageable::ComputeProxyPrim() as reference standard. We do not, at this time, provide a computation for the reverse-mapping, as we'll need more infrastructure to provide that without needing to process the entire stage for every request. (Internal change: 1654100) --- pxr/usd/lib/usdGeom/generatedSchema.usda | 589 ++++++++++++++++++++--- pxr/usd/lib/usdGeom/imageable.cpp | 89 +++- pxr/usd/lib/usdGeom/imageable.h | 83 +++- pxr/usd/lib/usdGeom/schema.usda | 31 +- pxr/usd/lib/usdGeom/tokens.h | 2 + pxr/usd/lib/usdGeom/wrapImageable.cpp | 34 ++ 6 files changed, 732 insertions(+), 96 deletions(-) diff --git a/pxr/usd/lib/usdGeom/generatedSchema.usda b/pxr/usd/lib/usdGeom/generatedSchema.usda index 9454354533..aa68317689 100644 --- a/pxr/usd/lib/usdGeom/generatedSchema.usda +++ b/pxr/usd/lib/usdGeom/generatedSchema.usda @@ -15,6 +15,28 @@ class "Imageable" ( primitive and can override shader inputs.''' ) { + rel proxyPrim = None ( + doc = '''The proxyPrim relationship allows us to link a + prim whose purpose is "render" to its (single target) + purpose="proxy" prim. This is entirely optional, but can be + useful in several scenarios: + + - In a pipeline that does pruning (for complexity management) + by deactivating prims composed from asset references, when we + deactivate a purpose="render" prim, we will be able to discover + and additionally deactivate its associated purpose="proxy" prim, + so that preview renders reflect the pruning accurately. + + - DCC importers may be able to make more aggressive optimizations + for interactive processing and display if they can discover the proxy + for a given render prim. + + - With a little more work, a Hydra-based application will be able + to map a picked proxy prim back to its render geometry for selection. + + \\note It is only valid to author the proxyPrim relationship on + prims whose purpose is "render".''' + ) uniform token purpose = "default" ( allowedTokens = ["default", "render", "proxy", "guide"] doc = '''Purpose is a concept we have found useful in our pipeline for @@ -47,10 +69,11 @@ class "Imageable" ( proxy can be used together to partition a complicated model into a lightweight proxy representation for interactive use, and a fully realized, potentially quite heavy, representation for rendering. - One can also use UsdVariantSets to create proxy representations, but - this can potentially lead to an explosion in variants for models that - already have several axes of variation. Purpose provides us with - another tool for interactive complexity management.''' + One can use UsdVariantSets to create proxy representations, but doing + so requires that we recompose parts of the UsdStage in order to change + to a different runtime level of detail, and that does not interact + well with the needs of multithreaded rendering. Purpose provides us with + a better tool for dynamic, interactive complexity management.''' ) token visibility = "inherited" ( allowedTokens = ["inherited", "invisible"] @@ -248,6 +271,28 @@ class "Xformable" ( """ ) { + rel proxyPrim = None ( + doc = '''The proxyPrim relationship allows us to link a + prim whose purpose is "render" to its (single target) + purpose="proxy" prim. This is entirely optional, but can be + useful in several scenarios: + + - In a pipeline that does pruning (for complexity management) + by deactivating prims composed from asset references, when we + deactivate a purpose="render" prim, we will be able to discover + and additionally deactivate its associated purpose="proxy" prim, + so that preview renders reflect the pruning accurately. + + - DCC importers may be able to make more aggressive optimizations + for interactive processing and display if they can discover the proxy + for a given render prim. + + - With a little more work, a Hydra-based application will be able + to map a picked proxy prim back to its render geometry for selection. + + \\note It is only valid to author the proxyPrim relationship on + prims whose purpose is "render".''' + ) uniform token purpose = "default" ( allowedTokens = ["default", "render", "proxy", "guide"] doc = '''Purpose is a concept we have found useful in our pipeline for @@ -280,10 +325,11 @@ class "Xformable" ( proxy can be used together to partition a complicated model into a lightweight proxy representation for interactive use, and a fully realized, potentially quite heavy, representation for rendering. - One can also use UsdVariantSets to create proxy representations, but - this can potentially lead to an explosion in variants for models that - already have several axes of variation. Purpose provides us with - another tool for interactive complexity management.''' + One can use UsdVariantSets to create proxy representations, but doing + so requires that we recompose parts of the UsdStage in order to change + to a different runtime level of detail, and that does not interact + well with the needs of multithreaded rendering. Purpose provides us with + a better tool for dynamic, interactive complexity management.''' ) token visibility = "inherited" ( allowedTokens = ["inherited", "invisible"] @@ -314,6 +360,28 @@ class Scope "Scope" ( transformability perspective.""" ) { + rel proxyPrim = None ( + doc = '''The proxyPrim relationship allows us to link a + prim whose purpose is "render" to its (single target) + purpose="proxy" prim. This is entirely optional, but can be + useful in several scenarios: + + - In a pipeline that does pruning (for complexity management) + by deactivating prims composed from asset references, when we + deactivate a purpose="render" prim, we will be able to discover + and additionally deactivate its associated purpose="proxy" prim, + so that preview renders reflect the pruning accurately. + + - DCC importers may be able to make more aggressive optimizations + for interactive processing and display if they can discover the proxy + for a given render prim. + + - With a little more work, a Hydra-based application will be able + to map a picked proxy prim back to its render geometry for selection. + + \\note It is only valid to author the proxyPrim relationship on + prims whose purpose is "render".''' + ) uniform token purpose = "default" ( allowedTokens = ["default", "render", "proxy", "guide"] doc = '''Purpose is a concept we have found useful in our pipeline for @@ -346,10 +414,11 @@ class Scope "Scope" ( proxy can be used together to partition a complicated model into a lightweight proxy representation for interactive use, and a fully realized, potentially quite heavy, representation for rendering. - One can also use UsdVariantSets to create proxy representations, but - this can potentially lead to an explosion in variants for models that - already have several axes of variation. Purpose provides us with - another tool for interactive complexity management.''' + One can use UsdVariantSets to create proxy representations, but doing + so requires that we recompose parts of the UsdStage in order to change + to a different runtime level of detail, and that does not interact + well with the needs of multithreaded rendering. Purpose provides us with + a better tool for dynamic, interactive complexity management.''' ) token visibility = "inherited" ( allowedTokens = ["inherited", "invisible"] @@ -366,6 +435,28 @@ class Xform "Xform" ( doc = "Concrete prim schema for a transform, which implements Xformable " ) { + rel proxyPrim = None ( + doc = '''The proxyPrim relationship allows us to link a + prim whose purpose is "render" to its (single target) + purpose="proxy" prim. This is entirely optional, but can be + useful in several scenarios: + + - In a pipeline that does pruning (for complexity management) + by deactivating prims composed from asset references, when we + deactivate a purpose="render" prim, we will be able to discover + and additionally deactivate its associated purpose="proxy" prim, + so that preview renders reflect the pruning accurately. + + - DCC importers may be able to make more aggressive optimizations + for interactive processing and display if they can discover the proxy + for a given render prim. + + - With a little more work, a Hydra-based application will be able + to map a picked proxy prim back to its render geometry for selection. + + \\note It is only valid to author the proxyPrim relationship on + prims whose purpose is "render".''' + ) uniform token purpose = "default" ( allowedTokens = ["default", "render", "proxy", "guide"] doc = '''Purpose is a concept we have found useful in our pipeline for @@ -398,10 +489,11 @@ class Xform "Xform" ( proxy can be used together to partition a complicated model into a lightweight proxy representation for interactive use, and a fully realized, potentially quite heavy, representation for rendering. - One can also use UsdVariantSets to create proxy representations, but - this can potentially lead to an explosion in variants for models that - already have several axes of variation. Purpose provides us with - another tool for interactive complexity management.''' + One can use UsdVariantSets to create proxy representations, but doing + so requires that we recompose parts of the UsdStage in order to change + to a different runtime level of detail, and that does not interact + well with the needs of multithreaded rendering. Purpose provides us with + a better tool for dynamic, interactive complexity management.''' ) token visibility = "inherited" ( allowedTokens = ["inherited", "invisible"] @@ -467,6 +559,28 @@ class "Boundable" ( the extent of all children, as they will be pruned from BBox computation during traversal.""" ) + rel proxyPrim = None ( + doc = '''The proxyPrim relationship allows us to link a + prim whose purpose is "render" to its (single target) + purpose="proxy" prim. This is entirely optional, but can be + useful in several scenarios: + + - In a pipeline that does pruning (for complexity management) + by deactivating prims composed from asset references, when we + deactivate a purpose="render" prim, we will be able to discover + and additionally deactivate its associated purpose="proxy" prim, + so that preview renders reflect the pruning accurately. + + - DCC importers may be able to make more aggressive optimizations + for interactive processing and display if they can discover the proxy + for a given render prim. + + - With a little more work, a Hydra-based application will be able + to map a picked proxy prim back to its render geometry for selection. + + \\note It is only valid to author the proxyPrim relationship on + prims whose purpose is "render".''' + ) uniform token purpose = "default" ( allowedTokens = ["default", "render", "proxy", "guide"] doc = '''Purpose is a concept we have found useful in our pipeline for @@ -499,10 +613,11 @@ class "Boundable" ( proxy can be used together to partition a complicated model into a lightweight proxy representation for interactive use, and a fully realized, potentially quite heavy, representation for rendering. - One can also use UsdVariantSets to create proxy representations, but - this can potentially lead to an explosion in variants for models that - already have several axes of variation. Purpose provides us with - another tool for interactive complexity management.''' + One can use UsdVariantSets to create proxy representations, but doing + so requires that we recompose parts of the UsdStage in order to change + to a different runtime level of detail, and that does not interact + well with the needs of multithreaded rendering. Purpose provides us with + a better tool for dynamic, interactive complexity management.''' ) token visibility = "inherited" ( allowedTokens = ["inherited", "invisible"] @@ -583,6 +698,28 @@ class "Gprim" ( each can be indepedently overridden, and because shaders rarely consume rgba parameters.""" ) + rel proxyPrim = None ( + doc = '''The proxyPrim relationship allows us to link a + prim whose purpose is "render" to its (single target) + purpose="proxy" prim. This is entirely optional, but can be + useful in several scenarios: + + - In a pipeline that does pruning (for complexity management) + by deactivating prims composed from asset references, when we + deactivate a purpose="render" prim, we will be able to discover + and additionally deactivate its associated purpose="proxy" prim, + so that preview renders reflect the pruning accurately. + + - DCC importers may be able to make more aggressive optimizations + for interactive processing and display if they can discover the proxy + for a given render prim. + + - With a little more work, a Hydra-based application will be able + to map a picked proxy prim back to its render geometry for selection. + + \\note It is only valid to author the proxyPrim relationship on + prims whose purpose is "render".''' + ) uniform token purpose = "default" ( allowedTokens = ["default", "render", "proxy", "guide"] doc = '''Purpose is a concept we have found useful in our pipeline for @@ -615,10 +752,11 @@ class "Gprim" ( proxy can be used together to partition a complicated model into a lightweight proxy representation for interactive use, and a fully realized, potentially quite heavy, representation for rendering. - One can also use UsdVariantSets to create proxy representations, but - this can potentially lead to an explosion in variants for models that - already have several axes of variation. Purpose provides us with - another tool for interactive complexity management.''' + One can use UsdVariantSets to create proxy representations, but doing + so requires that we recompose parts of the UsdStage in order to change + to a different runtime level of detail, and that does not interact + well with the needs of multithreaded rendering. Purpose provides us with + a better tool for dynamic, interactive complexity management.''' ) token visibility = "inherited" ( allowedTokens = ["inherited", "invisible"] @@ -689,6 +827,28 @@ class Cube "Cube" ( each can be indepedently overridden, and because shaders rarely consume rgba parameters.""" ) + rel proxyPrim = None ( + doc = '''The proxyPrim relationship allows us to link a + prim whose purpose is "render" to its (single target) + purpose="proxy" prim. This is entirely optional, but can be + useful in several scenarios: + + - In a pipeline that does pruning (for complexity management) + by deactivating prims composed from asset references, when we + deactivate a purpose="render" prim, we will be able to discover + and additionally deactivate its associated purpose="proxy" prim, + so that preview renders reflect the pruning accurately. + + - DCC importers may be able to make more aggressive optimizations + for interactive processing and display if they can discover the proxy + for a given render prim. + + - With a little more work, a Hydra-based application will be able + to map a picked proxy prim back to its render geometry for selection. + + \\note It is only valid to author the proxyPrim relationship on + prims whose purpose is "render".''' + ) uniform token purpose = "default" ( allowedTokens = ["default", "render", "proxy", "guide"] doc = '''Purpose is a concept we have found useful in our pipeline for @@ -721,10 +881,11 @@ class Cube "Cube" ( proxy can be used together to partition a complicated model into a lightweight proxy representation for interactive use, and a fully realized, potentially quite heavy, representation for rendering. - One can also use UsdVariantSets to create proxy representations, but - this can potentially lead to an explosion in variants for models that - already have several axes of variation. Purpose provides us with - another tool for interactive complexity management.''' + One can use UsdVariantSets to create proxy representations, but doing + so requires that we recompose parts of the UsdStage in order to change + to a different runtime level of detail, and that does not interact + well with the needs of multithreaded rendering. Purpose provides us with + a better tool for dynamic, interactive complexity management.''' ) double size = 2 ( doc = """Indicates the length of each edge of the cube. If you @@ -801,6 +962,28 @@ class Sphere "Sphere" ( each can be indepedently overridden, and because shaders rarely consume rgba parameters.""" ) + rel proxyPrim = None ( + doc = '''The proxyPrim relationship allows us to link a + prim whose purpose is "render" to its (single target) + purpose="proxy" prim. This is entirely optional, but can be + useful in several scenarios: + + - In a pipeline that does pruning (for complexity management) + by deactivating prims composed from asset references, when we + deactivate a purpose="render" prim, we will be able to discover + and additionally deactivate its associated purpose="proxy" prim, + so that preview renders reflect the pruning accurately. + + - DCC importers may be able to make more aggressive optimizations + for interactive processing and display if they can discover the proxy + for a given render prim. + + - With a little more work, a Hydra-based application will be able + to map a picked proxy prim back to its render geometry for selection. + + \\note It is only valid to author the proxyPrim relationship on + prims whose purpose is "render".''' + ) uniform token purpose = "default" ( allowedTokens = ["default", "render", "proxy", "guide"] doc = '''Purpose is a concept we have found useful in our pipeline for @@ -833,10 +1016,11 @@ class Sphere "Sphere" ( proxy can be used together to partition a complicated model into a lightweight proxy representation for interactive use, and a fully realized, potentially quite heavy, representation for rendering. - One can also use UsdVariantSets to create proxy representations, but - this can potentially lead to an explosion in variants for models that - already have several axes of variation. Purpose provides us with - another tool for interactive complexity management.''' + One can use UsdVariantSets to create proxy representations, but doing + so requires that we recompose parts of the UsdStage in order to change + to a different runtime level of detail, and that does not interact + well with the needs of multithreaded rendering. Purpose provides us with + a better tool for dynamic, interactive complexity management.''' ) double radius = 1 ( doc = """Indicates the sphere's radius. If you @@ -924,6 +1108,28 @@ class Cylinder "Cylinder" ( each can be indepedently overridden, and because shaders rarely consume rgba parameters.""" ) + rel proxyPrim = None ( + doc = '''The proxyPrim relationship allows us to link a + prim whose purpose is "render" to its (single target) + purpose="proxy" prim. This is entirely optional, but can be + useful in several scenarios: + + - In a pipeline that does pruning (for complexity management) + by deactivating prims composed from asset references, when we + deactivate a purpose="render" prim, we will be able to discover + and additionally deactivate its associated purpose="proxy" prim, + so that preview renders reflect the pruning accurately. + + - DCC importers may be able to make more aggressive optimizations + for interactive processing and display if they can discover the proxy + for a given render prim. + + - With a little more work, a Hydra-based application will be able + to map a picked proxy prim back to its render geometry for selection. + + \\note It is only valid to author the proxyPrim relationship on + prims whose purpose is "render".''' + ) uniform token purpose = "default" ( allowedTokens = ["default", "render", "proxy", "guide"] doc = '''Purpose is a concept we have found useful in our pipeline for @@ -956,10 +1162,11 @@ class Cylinder "Cylinder" ( proxy can be used together to partition a complicated model into a lightweight proxy representation for interactive use, and a fully realized, potentially quite heavy, representation for rendering. - One can also use UsdVariantSets to create proxy representations, but - this can potentially lead to an explosion in variants for models that - already have several axes of variation. Purpose provides us with - another tool for interactive complexity management.''' + One can use UsdVariantSets to create proxy representations, but doing + so requires that we recompose parts of the UsdStage in order to change + to a different runtime level of detail, and that does not interact + well with the needs of multithreaded rendering. Purpose provides us with + a better tool for dynamic, interactive complexity management.''' ) double radius = 1 ( doc = """The radius of the cylinder. If you author radius @@ -1046,6 +1253,28 @@ class Capsule "Capsule" ( each can be indepedently overridden, and because shaders rarely consume rgba parameters.""" ) + rel proxyPrim = None ( + doc = '''The proxyPrim relationship allows us to link a + prim whose purpose is "render" to its (single target) + purpose="proxy" prim. This is entirely optional, but can be + useful in several scenarios: + + - In a pipeline that does pruning (for complexity management) + by deactivating prims composed from asset references, when we + deactivate a purpose="render" prim, we will be able to discover + and additionally deactivate its associated purpose="proxy" prim, + so that preview renders reflect the pruning accurately. + + - DCC importers may be able to make more aggressive optimizations + for interactive processing and display if they can discover the proxy + for a given render prim. + + - With a little more work, a Hydra-based application will be able + to map a picked proxy prim back to its render geometry for selection. + + \\note It is only valid to author the proxyPrim relationship on + prims whose purpose is "render".''' + ) uniform token purpose = "default" ( allowedTokens = ["default", "render", "proxy", "guide"] doc = '''Purpose is a concept we have found useful in our pipeline for @@ -1078,10 +1307,11 @@ class Capsule "Capsule" ( proxy can be used together to partition a complicated model into a lightweight proxy representation for interactive use, and a fully realized, potentially quite heavy, representation for rendering. - One can also use UsdVariantSets to create proxy representations, but - this can potentially lead to an explosion in variants for models that - already have several axes of variation. Purpose provides us with - another tool for interactive complexity management.''' + One can use UsdVariantSets to create proxy representations, but doing + so requires that we recompose parts of the UsdStage in order to change + to a different runtime level of detail, and that does not interact + well with the needs of multithreaded rendering. Purpose provides us with + a better tool for dynamic, interactive complexity management.''' ) double radius = 0.5 ( doc = """The radius of the capsule. If you @@ -1170,6 +1400,28 @@ class Cone "Cone" ( each can be indepedently overridden, and because shaders rarely consume rgba parameters.""" ) + rel proxyPrim = None ( + doc = '''The proxyPrim relationship allows us to link a + prim whose purpose is "render" to its (single target) + purpose="proxy" prim. This is entirely optional, but can be + useful in several scenarios: + + - In a pipeline that does pruning (for complexity management) + by deactivating prims composed from asset references, when we + deactivate a purpose="render" prim, we will be able to discover + and additionally deactivate its associated purpose="proxy" prim, + so that preview renders reflect the pruning accurately. + + - DCC importers may be able to make more aggressive optimizations + for interactive processing and display if they can discover the proxy + for a given render prim. + + - With a little more work, a Hydra-based application will be able + to map a picked proxy prim back to its render geometry for selection. + + \\note It is only valid to author the proxyPrim relationship on + prims whose purpose is "render".''' + ) uniform token purpose = "default" ( allowedTokens = ["default", "render", "proxy", "guide"] doc = '''Purpose is a concept we have found useful in our pipeline for @@ -1202,10 +1454,11 @@ class Cone "Cone" ( proxy can be used together to partition a complicated model into a lightweight proxy representation for interactive use, and a fully realized, potentially quite heavy, representation for rendering. - One can also use UsdVariantSets to create proxy representations, but - this can potentially lead to an explosion in variants for models that - already have several axes of variation. Purpose provides us with - another tool for interactive complexity management.''' + One can use UsdVariantSets to create proxy representations, but doing + so requires that we recompose parts of the UsdStage in order to change + to a different runtime level of detail, and that does not interact + well with the needs of multithreaded rendering. Purpose provides us with + a better tool for dynamic, interactive complexity management.''' ) double radius = 1 ( doc = """The radius of the cone. If you @@ -1302,6 +1555,28 @@ class "PointBased" ( each can be indepedently overridden, and because shaders rarely consume rgba parameters.""" ) + rel proxyPrim = None ( + doc = '''The proxyPrim relationship allows us to link a + prim whose purpose is "render" to its (single target) + purpose="proxy" prim. This is entirely optional, but can be + useful in several scenarios: + + - In a pipeline that does pruning (for complexity management) + by deactivating prims composed from asset references, when we + deactivate a purpose="render" prim, we will be able to discover + and additionally deactivate its associated purpose="proxy" prim, + so that preview renders reflect the pruning accurately. + + - DCC importers may be able to make more aggressive optimizations + for interactive processing and display if they can discover the proxy + for a given render prim. + + - With a little more work, a Hydra-based application will be able + to map a picked proxy prim back to its render geometry for selection. + + \\note It is only valid to author the proxyPrim relationship on + prims whose purpose is "render".''' + ) uniform token purpose = "default" ( allowedTokens = ["default", "render", "proxy", "guide"] doc = '''Purpose is a concept we have found useful in our pipeline for @@ -1334,10 +1609,11 @@ class "PointBased" ( proxy can be used together to partition a complicated model into a lightweight proxy representation for interactive use, and a fully realized, potentially quite heavy, representation for rendering. - One can also use UsdVariantSets to create proxy representations, but - this can potentially lead to an explosion in variants for models that - already have several axes of variation. Purpose provides us with - another tool for interactive complexity management.''' + One can use UsdVariantSets to create proxy representations, but doing + so requires that we recompose parts of the UsdStage in order to change + to a different runtime level of detail, and that does not interact + well with the needs of multithreaded rendering. Purpose provides us with + a better tool for dynamic, interactive complexity management.''' ) vector3f[] velocities ( doc = """If provided, 'velocities' should be used by renderers to @@ -1518,6 +1794,28 @@ class Mesh "Mesh" ( each can be indepedently overridden, and because shaders rarely consume rgba parameters.""" ) + rel proxyPrim = None ( + doc = '''The proxyPrim relationship allows us to link a + prim whose purpose is "render" to its (single target) + purpose="proxy" prim. This is entirely optional, but can be + useful in several scenarios: + + - In a pipeline that does pruning (for complexity management) + by deactivating prims composed from asset references, when we + deactivate a purpose="render" prim, we will be able to discover + and additionally deactivate its associated purpose="proxy" prim, + so that preview renders reflect the pruning accurately. + + - DCC importers may be able to make more aggressive optimizations + for interactive processing and display if they can discover the proxy + for a given render prim. + + - With a little more work, a Hydra-based application will be able + to map a picked proxy prim back to its render geometry for selection. + + \\note It is only valid to author the proxyPrim relationship on + prims whose purpose is "render".''' + ) uniform token purpose = "default" ( allowedTokens = ["default", "render", "proxy", "guide"] doc = '''Purpose is a concept we have found useful in our pipeline for @@ -1550,10 +1848,11 @@ class Mesh "Mesh" ( proxy can be used together to partition a complicated model into a lightweight proxy representation for interactive use, and a fully realized, potentially quite heavy, representation for rendering. - One can also use UsdVariantSets to create proxy representations, but - this can potentially lead to an explosion in variants for models that - already have several axes of variation. Purpose provides us with - another tool for interactive complexity management.''' + One can use UsdVariantSets to create proxy representations, but doing + so requires that we recompose parts of the UsdStage in order to change + to a different runtime level of detail, and that does not interact + well with the needs of multithreaded rendering. Purpose provides us with + a better tool for dynamic, interactive complexity management.''' ) uniform token subdivisionScheme = "catmullClark" ( allowedTokens = ["catmullClark", "loop", "bilinear", "none"] @@ -1719,6 +2018,28 @@ class NurbsPatch "NurbsPatch" ( each can be indepedently overridden, and because shaders rarely consume rgba parameters.""" ) + rel proxyPrim = None ( + doc = '''The proxyPrim relationship allows us to link a + prim whose purpose is "render" to its (single target) + purpose="proxy" prim. This is entirely optional, but can be + useful in several scenarios: + + - In a pipeline that does pruning (for complexity management) + by deactivating prims composed from asset references, when we + deactivate a purpose="render" prim, we will be able to discover + and additionally deactivate its associated purpose="proxy" prim, + so that preview renders reflect the pruning accurately. + + - DCC importers may be able to make more aggressive optimizations + for interactive processing and display if they can discover the proxy + for a given render prim. + + - With a little more work, a Hydra-based application will be able + to map a picked proxy prim back to its render geometry for selection. + + \\note It is only valid to author the proxyPrim relationship on + prims whose purpose is "render".''' + ) uniform token purpose = "default" ( allowedTokens = ["default", "render", "proxy", "guide"] doc = '''Purpose is a concept we have found useful in our pipeline for @@ -1751,10 +2072,11 @@ class NurbsPatch "NurbsPatch" ( proxy can be used together to partition a complicated model into a lightweight proxy representation for interactive use, and a fully realized, potentially quite heavy, representation for rendering. - One can also use UsdVariantSets to create proxy representations, but - this can potentially lead to an explosion in variants for models that - already have several axes of variation. Purpose provides us with - another tool for interactive complexity management.''' + One can use UsdVariantSets to create proxy representations, but doing + so requires that we recompose parts of the UsdStage in order to change + to a different runtime level of detail, and that does not interact + well with the needs of multithreaded rendering. Purpose provides us with + a better tool for dynamic, interactive complexity management.''' ) int[] trimCurve:counts ( doc = '''Each element specifies how many curves are present in each @@ -1947,6 +2269,28 @@ class "Curves" ( each can be indepedently overridden, and because shaders rarely consume rgba parameters.""" ) + rel proxyPrim = None ( + doc = '''The proxyPrim relationship allows us to link a + prim whose purpose is "render" to its (single target) + purpose="proxy" prim. This is entirely optional, but can be + useful in several scenarios: + + - In a pipeline that does pruning (for complexity management) + by deactivating prims composed from asset references, when we + deactivate a purpose="render" prim, we will be able to discover + and additionally deactivate its associated purpose="proxy" prim, + so that preview renders reflect the pruning accurately. + + - DCC importers may be able to make more aggressive optimizations + for interactive processing and display if they can discover the proxy + for a given render prim. + + - With a little more work, a Hydra-based application will be able + to map a picked proxy prim back to its render geometry for selection. + + \\note It is only valid to author the proxyPrim relationship on + prims whose purpose is "render".''' + ) uniform token purpose = "default" ( allowedTokens = ["default", "render", "proxy", "guide"] doc = '''Purpose is a concept we have found useful in our pipeline for @@ -1979,10 +2323,11 @@ class "Curves" ( proxy can be used together to partition a complicated model into a lightweight proxy representation for interactive use, and a fully realized, potentially quite heavy, representation for rendering. - One can also use UsdVariantSets to create proxy representations, but - this can potentially lead to an explosion in variants for models that - already have several axes of variation. Purpose provides us with - another tool for interactive complexity management.''' + One can use UsdVariantSets to create proxy representations, but doing + so requires that we recompose parts of the UsdStage in order to change + to a different runtime level of detail, and that does not interact + well with the needs of multithreaded rendering. Purpose provides us with + a better tool for dynamic, interactive complexity management.''' ) vector3f[] velocities ( doc = """If provided, 'velocities' should be used by renderers to @@ -2189,6 +2534,28 @@ class BasisCurves "BasisCurves" ( each can be indepedently overridden, and because shaders rarely consume rgba parameters.""" ) + rel proxyPrim = None ( + doc = '''The proxyPrim relationship allows us to link a + prim whose purpose is "render" to its (single target) + purpose="proxy" prim. This is entirely optional, but can be + useful in several scenarios: + + - In a pipeline that does pruning (for complexity management) + by deactivating prims composed from asset references, when we + deactivate a purpose="render" prim, we will be able to discover + and additionally deactivate its associated purpose="proxy" prim, + so that preview renders reflect the pruning accurately. + + - DCC importers may be able to make more aggressive optimizations + for interactive processing and display if they can discover the proxy + for a given render prim. + + - With a little more work, a Hydra-based application will be able + to map a picked proxy prim back to its render geometry for selection. + + \\note It is only valid to author the proxyPrim relationship on + prims whose purpose is "render".''' + ) uniform token purpose = "default" ( allowedTokens = ["default", "render", "proxy", "guide"] doc = '''Purpose is a concept we have found useful in our pipeline for @@ -2221,10 +2588,11 @@ class BasisCurves "BasisCurves" ( proxy can be used together to partition a complicated model into a lightweight proxy representation for interactive use, and a fully realized, potentially quite heavy, representation for rendering. - One can also use UsdVariantSets to create proxy representations, but - this can potentially lead to an explosion in variants for models that - already have several axes of variation. Purpose provides us with - another tool for interactive complexity management.''' + One can use UsdVariantSets to create proxy representations, but doing + so requires that we recompose parts of the UsdStage in order to change + to a different runtime level of detail, and that does not interact + well with the needs of multithreaded rendering. Purpose provides us with + a better tool for dynamic, interactive complexity management.''' ) uniform token type = "cubic" ( allowedTokens = ["linear", "cubic"] @@ -2371,6 +2739,28 @@ class NurbsCurves "NurbsCurves" ( each can be indepedently overridden, and because shaders rarely consume rgba parameters.""" ) + rel proxyPrim = None ( + doc = '''The proxyPrim relationship allows us to link a + prim whose purpose is "render" to its (single target) + purpose="proxy" prim. This is entirely optional, but can be + useful in several scenarios: + + - In a pipeline that does pruning (for complexity management) + by deactivating prims composed from asset references, when we + deactivate a purpose="render" prim, we will be able to discover + and additionally deactivate its associated purpose="proxy" prim, + so that preview renders reflect the pruning accurately. + + - DCC importers may be able to make more aggressive optimizations + for interactive processing and display if they can discover the proxy + for a given render prim. + + - With a little more work, a Hydra-based application will be able + to map a picked proxy prim back to its render geometry for selection. + + \\note It is only valid to author the proxyPrim relationship on + prims whose purpose is "render".''' + ) uniform token purpose = "default" ( allowedTokens = ["default", "render", "proxy", "guide"] doc = '''Purpose is a concept we have found useful in our pipeline for @@ -2403,10 +2793,11 @@ class NurbsCurves "NurbsCurves" ( proxy can be used together to partition a complicated model into a lightweight proxy representation for interactive use, and a fully realized, potentially quite heavy, representation for rendering. - One can also use UsdVariantSets to create proxy representations, but - this can potentially lead to an explosion in variants for models that - already have several axes of variation. Purpose provides us with - another tool for interactive complexity management.''' + One can use UsdVariantSets to create proxy representations, but doing + so requires that we recompose parts of the UsdStage in order to change + to a different runtime level of detail, and that does not interact + well with the needs of multithreaded rendering. Purpose provides us with + a better tool for dynamic, interactive complexity management.''' ) double2[] ranges ( doc = "Specifies the parametric range used to evaluate the curve." @@ -2529,6 +2920,28 @@ class Points "Points" ( each can be indepedently overridden, and because shaders rarely consume rgba parameters.""" ) + rel proxyPrim = None ( + doc = '''The proxyPrim relationship allows us to link a + prim whose purpose is "render" to its (single target) + purpose="proxy" prim. This is entirely optional, but can be + useful in several scenarios: + + - In a pipeline that does pruning (for complexity management) + by deactivating prims composed from asset references, when we + deactivate a purpose="render" prim, we will be able to discover + and additionally deactivate its associated purpose="proxy" prim, + so that preview renders reflect the pruning accurately. + + - DCC importers may be able to make more aggressive optimizations + for interactive processing and display if they can discover the proxy + for a given render prim. + + - With a little more work, a Hydra-based application will be able + to map a picked proxy prim back to its render geometry for selection. + + \\note It is only valid to author the proxyPrim relationship on + prims whose purpose is "render".''' + ) uniform token purpose = "default" ( allowedTokens = ["default", "render", "proxy", "guide"] doc = '''Purpose is a concept we have found useful in our pipeline for @@ -2561,10 +2974,11 @@ class Points "Points" ( proxy can be used together to partition a complicated model into a lightweight proxy representation for interactive use, and a fully realized, potentially quite heavy, representation for rendering. - One can also use UsdVariantSets to create proxy representations, but - this can potentially lead to an explosion in variants for models that - already have several axes of variation. Purpose provides us with - another tool for interactive complexity management.''' + One can use UsdVariantSets to create proxy representations, but doing + so requires that we recompose parts of the UsdStage in order to change + to a different runtime level of detail, and that does not interact + well with the needs of multithreaded rendering. Purpose provides us with + a better tool for dynamic, interactive complexity management.''' ) vector3f[] velocities ( doc = """If provided, 'velocities' should be used by renderers to @@ -2663,6 +3077,28 @@ class Camera "Camera" ( token projection = "perspective" ( allowedTokens = ["perspective", "orthographic"] ) + rel proxyPrim = None ( + doc = '''The proxyPrim relationship allows us to link a + prim whose purpose is "render" to its (single target) + purpose="proxy" prim. This is entirely optional, but can be + useful in several scenarios: + + - In a pipeline that does pruning (for complexity management) + by deactivating prims composed from asset references, when we + deactivate a purpose="render" prim, we will be able to discover + and additionally deactivate its associated purpose="proxy" prim, + so that preview renders reflect the pruning accurately. + + - DCC importers may be able to make more aggressive optimizations + for interactive processing and display if they can discover the proxy + for a given render prim. + + - With a little more work, a Hydra-based application will be able + to map a picked proxy prim back to its render geometry for selection. + + \\note It is only valid to author the proxyPrim relationship on + prims whose purpose is "render".''' + ) uniform token purpose = "default" ( allowedTokens = ["default", "render", "proxy", "guide"] doc = '''Purpose is a concept we have found useful in our pipeline for @@ -2695,10 +3131,11 @@ class Camera "Camera" ( proxy can be used together to partition a complicated model into a lightweight proxy representation for interactive use, and a fully realized, potentially quite heavy, representation for rendering. - One can also use UsdVariantSets to create proxy representations, but - this can potentially lead to an explosion in variants for models that - already have several axes of variation. Purpose provides us with - another tool for interactive complexity management.''' + One can use UsdVariantSets to create proxy representations, but doing + so requires that we recompose parts of the UsdStage in order to change + to a different runtime level of detail, and that does not interact + well with the needs of multithreaded rendering. Purpose provides us with + a better tool for dynamic, interactive complexity management.''' ) uniform token stereoRole = "mono" ( allowedTokens = ["mono", "left", "right"] diff --git a/pxr/usd/lib/usdGeom/imageable.cpp b/pxr/usd/lib/usdGeom/imageable.cpp index 60ccd4087f..c1bcc9fbd0 100644 --- a/pxr/usd/lib/usdGeom/imageable.cpp +++ b/pxr/usd/lib/usdGeom/imageable.cpp @@ -110,6 +110,19 @@ UsdGeomImageable::CreatePurposeAttr(VtValue const &defaultValue, bool writeSpars writeSparsely); } +UsdRelationship +UsdGeomImageable::GetProxyPrimRel() const +{ + return GetPrim().GetRelationship(UsdGeomTokens->proxyPrim); +} + +UsdRelationship +UsdGeomImageable::CreateProxyPrimRel() const +{ + return GetPrim().CreateRelationship(UsdGeomTokens->proxyPrim, + /* custom = */ false); +} + namespace { static inline TfTokenVector _ConcatenateAttributeNames(const TfTokenVector& left,const TfTokenVector& right) @@ -247,11 +260,6 @@ _ComputeVisibility(UsdPrim const &prim, UsdTimeCode const &time) TfToken myVis = _ComputeVisibility(parent, time); if (myVis == UsdGeomTokens->invisible) return myVis; - // XXX This could be a multithreaded performance concern - // due to operator-bool reliance on TfType, but it is more correct - // than just speculatively looking up an attribute called - // "visibility" and querying it, since it could appear as - // custom on a non-imageable prim. if (UsdGeomImageable ip = UsdGeomImageable(prim)){ ip.GetVisibilityAttr().Get(&myVis, time); } @@ -271,19 +279,17 @@ UsdGeomImageable::ComputeVisibility(UsdTimeCode const &time) const static TfToken -_ComputePurpose(UsdPrim const &prim) +_ComputePurpose(UsdPrim const &prim, UsdPrim *root=NULL) { if (UsdPrim parent = prim.GetParent()){ - TfToken myPurpose = _ComputePurpose(parent); + TfToken myPurpose = _ComputePurpose(parent, root); if (myPurpose != UsdGeomTokens->default_) return myPurpose; - // XXX This could be a multithreaded performance concern - // due to operator-bool reliance on TfType, but it is more correct - // than just speculatively looking up an attribute called - // "purpose" and querying it, since it could appear as - // custom on a non-imageable prim. if (UsdGeomImageable ip = UsdGeomImageable(prim)){ ip.GetPurposeAttr().Get(&myPurpose); + if (root){ + *root = prim; + } } return myPurpose; @@ -372,6 +378,65 @@ UsdGeomImageable::ComputePurpose() const return _ComputePurpose(GetPrim()); } +UsdPrim +UsdGeomImageable::ComputeProxyPrim(UsdPrim *renderPrim) const +{ + UsdPrim purposeRoot, self=GetPrim(); + + TfToken purpose = _ComputePurpose(self, &purposeRoot); + + if (purpose == UsdGeomTokens->render){ + TF_VERIFY(purposeRoot); + SdfPathVector target; + UsdRelationship proxyPrimRel = + UsdGeomImageable(purposeRoot).GetProxyPrimRel(); + if (proxyPrimRel.GetForwardedTargets(&target)){ + if (target.size() == 1){ + if (UsdPrim proxy = self.GetStage()->GetPrimAtPath(target[0])){ + if (_ComputePurpose(proxy) != UsdGeomTokens->proxy){ + TF_WARN("Prim <%s>, targeted as proxyPrim of prim " + "<%s> does not have purpose 'proxy'", + proxy.GetPath().GetText(), + purposeRoot.GetPath().GetText()); + return UsdPrim(); + } + if (renderPrim){ + *renderPrim = purposeRoot; + } + return proxy; + } + } + else if (target.size() > 1){ + TF_WARN("Found multiple targets for proxyPrim rel on " + "prim <%s>", purposeRoot.GetPath().GetText()); + } + } + } + + return UsdPrim(); +} + +bool +UsdGeomImageable::SetProxyPrim(const UsdPrim &proxy) const +{ + if (proxy){ + SdfPathVector targets {proxy.GetPath()}; + return CreateProxyPrimRel().SetTargets(targets); + } + return false; +} + +bool +UsdGeomImageable::SetProxyPrim(const UsdSchemaBase &proxy) const +{ + if (proxy){ + SdfPathVector targets {proxy.GetPrim().GetPath()}; + return CreateProxyPrimRel().SetTargets(targets); + } + return false; +} + + static TfTokenVector _MakePurposeVector(TfToken const &purpose1, diff --git a/pxr/usd/lib/usdGeom/imageable.h b/pxr/usd/lib/usdGeom/imageable.h index 5537d5e99b..c9810bf589 100644 --- a/pxr/usd/lib/usdGeom/imageable.h +++ b/pxr/usd/lib/usdGeom/imageable.h @@ -183,10 +183,11 @@ class UsdGeomImageable : public UsdTyped /// \em proxy can be used together to partition a complicated model /// into a lightweight proxy representation for interactive use, and a /// fully realized, potentially quite heavy, representation for rendering. - /// One can also use UsdVariantSets to create proxy representations, but - /// this can potentially lead to an explosion in variants for models that - /// already have several axes of variation. Purpose provides us with - /// another tool for interactive complexity management. + /// One can use UsdVariantSets to create proxy representations, but doing + /// so requires that we recompose parts of the UsdStage in order to change + /// to a different runtime level of detail, and that does not interact + /// well with the needs of multithreaded rendering. Purpose provides us with + /// a better tool for dynamic, interactive complexity management. /// /// \n C++ Type: TfToken /// \n Usd Type: SdfValueTypeNames->Token @@ -202,6 +203,37 @@ class UsdGeomImageable : public UsdTyped /// the default for \p writeSparsely is \c false. UsdAttribute CreatePurposeAttr(VtValue const &defaultValue = VtValue(), bool writeSparsely=false) const; +public: + // --------------------------------------------------------------------- // + // PROXYPRIM + // --------------------------------------------------------------------- // + /// The \em proxyPrim relationship allows us to link a + /// prim whose \em purpose is "render" to its (single target) + /// purpose="proxy" prim. This is entirely optional, but can be + /// useful in several scenarios: + /// + /// \li In a pipeline that does pruning (for complexity management) + /// by deactivating prims composed from asset references, when we + /// deactivate a purpose="render" prim, we will be able to discover + /// and additionally deactivate its associated purpose="proxy" prim, + /// so that preview renders reflect the pruning accurately. + /// + /// \li DCC importers may be able to make more aggressive optimizations + /// for interactive processing and display if they can discover the proxy + /// for a given render prim. + /// + /// \li With a little more work, a Hydra-based application will be able + /// to map a picked proxy prim back to its render geometry for selection. + /// + /// \note It is only valid to author the proxyPrim relationship on + /// prims whose purpose is "render". + /// + UsdRelationship GetProxyPrimRel() const; + + /// See GetProxyPrimRel(), and also + /// \ref Usd_Create_Or_Get_Property for when to use Get vs Create + UsdRelationship CreateProxyPrimRel() const; + public: // ===================================================================== // // Feel free to add custom code below this line, it will be preserved by @@ -412,6 +444,49 @@ class UsdGeomImageable : public UsdTyped /// \sa GetPurposeAttr() TfToken ComputePurpose() const; + /// Find the prim whose purpose is \em proxy that serves as the proxy + /// for this prim, as established by the GetProxyPrimRel(), or an + /// invalid UsdPrim if this prim has no proxy. + /// + /// This method will find the proxy for \em any prim whose computed + /// purpose (see ComputePurpose()) is \em render. If provided and a proxy + /// was found, we will set *renderPrim to the root of the \em render + /// subtree upon which the renderProxy relationship was authored. + /// + /// If the renderProxy relationship has more than one target, we will + /// issue a warning and return an invalid UsdPrim. If the targeted prim + /// does not have a resolved purpose of \em proxy, we will warn and + /// return an invalid prim. + /// + /// This function should be considered a reference implementation for + /// correctness. If called on each prim in the context of a traversal + /// we will perform massive overcomputation, because sibling prims share + /// sub-problems in the query that can be efficiently cached, but are not + /// (cannot be) by this simple implementation. If you have control of + /// your traversal, it will be far more efficient to compute proxy-prims + /// on a stack as you traverse. + /// + /// \note Currently the returned prim will not contain any instancing + /// context if it is inside a master - its path will be relative to the + /// master's root. Once UsdPrim is instancing-aware in the core, we can + /// change this method to return a context-aware result. + /// + /// \sa SetProxyPrim(), GetProxyPrimRel() + UsdPrim ComputeProxyPrim(UsdPrim *renderPrim=NULL) const; + + /// Convenience function for authoring the \em renderProxy rel on this + /// prim to target the given \p proxy prim. + /// + /// To facilitate authoring on sparse or unloaded stages, we do not + /// perform any validation of this prim's purpose or the type or + /// purpoes of the specified prim. + /// + /// \sa ComputeProxyPrim(), GetProxyPrimRel() + bool SetProxyPrim(const UsdPrim &proxy) const; + + /// \overload that takes any UsdSchemaBase-derived object + bool SetProxyPrim(const UsdSchemaBase &proxy) const; + /// Compute the bound of this prim in world space, at the specified /// \p time, and for the specified purposes. /// diff --git a/pxr/usd/lib/usdGeom/schema.usda b/pxr/usd/lib/usdGeom/schema.usda index 8d972fc2fc..47894c1cec 100644 --- a/pxr/usd/lib/usdGeom/schema.usda +++ b/pxr/usd/lib/usdGeom/schema.usda @@ -162,10 +162,33 @@ class "Imageable" ( \\em proxy can be used together to partition a complicated model into a lightweight proxy representation for interactive use, and a fully realized, potentially quite heavy, representation for rendering. - One can also use UsdVariantSets to create proxy representations, but - this can potentially lead to an explosion in variants for models that - already have several axes of variation. Purpose provides us with - another tool for interactive complexity management.""" + One can use UsdVariantSets to create proxy representations, but doing + so requires that we recompose parts of the UsdStage in order to change + to a different runtime level of detail, and that does not interact + well with the needs of multithreaded rendering. Purpose provides us with + a better tool for dynamic, interactive complexity management.""" + ) + rel proxyPrim ( + doc = """The \\em proxyPrim relationship allows us to link a + prim whose \\em purpose is "render" to its (single target) + purpose="proxy" prim. This is entirely optional, but can be + useful in several scenarios: + + \\li In a pipeline that does pruning (for complexity management) + by deactivating prims composed from asset references, when we + deactivate a purpose="render" prim, we will be able to discover + and additionally deactivate its associated purpose="proxy" prim, + so that preview renders reflect the pruning accurately. + + \\li DCC importers may be able to make more aggressive optimizations + for interactive processing and display if they can discover the proxy + for a given render prim. + + \\li With a little more work, a Hydra-based application will be able + to map a picked proxy prim back to its render geometry for selection. + + \\note It is only valid to author the proxyPrim relationship on + prims whose purpose is "render".""" ) } diff --git a/pxr/usd/lib/usdGeom/tokens.h b/pxr/usd/lib/usdGeom/tokens.h index 3e3e00be46..b739e09246 100644 --- a/pxr/usd/lib/usdGeom/tokens.h +++ b/pxr/usd/lib/usdGeom/tokens.h @@ -111,6 +111,7 @@ ((primvarsDisplayOpacity, "primvars:displayOpacity")) \ (projection) \ (proxy) \ + (proxyPrim) \ (purpose) \ (radius) \ (ranges) \ @@ -247,6 +248,7 @@ /// \li primvarsDisplayOpacity - UsdGeomGprim /// \li projection - UsdGeomCamera /// \li proxy - Possible value for UsdGeomImageable::GetPurposeAttr() +/// \li proxyPrim - UsdGeomImageable /// \li purpose - UsdGeomImageable /// \li radius - UsdGeomCone, UsdGeomCapsule, UsdGeomCylinder, UsdGeomSphere /// \li ranges - UsdGeomNurbsCurves diff --git a/pxr/usd/lib/usdGeom/wrapImageable.cpp b/pxr/usd/lib/usdGeom/wrapImageable.cpp index 5cc9d85ee0..646ad538b3 100644 --- a/pxr/usd/lib/usdGeom/wrapImageable.cpp +++ b/pxr/usd/lib/usdGeom/wrapImageable.cpp @@ -103,6 +103,11 @@ void wrapUsdGeomImageable() (arg("defaultValue")=object(), arg("writeSparsely")=false)) + + .def("GetProxyPrimRel", + &This::GetProxyPrimRel) + .def("CreateProxyPrimRel", + &This::CreateProxyPrimRel) ; _CustomWrapCode(cls); @@ -123,6 +128,23 @@ void wrapUsdGeomImageable() // ===================================================================== // // --(BEGIN CUSTOM CODE)-- +#include "pxr/base/tf/pyObjWrapper.h" + +static TfPyObjWrapper +_ComputeProxyPrim(UsdGeomImageable const &self) +{ + UsdPrim renderPrim, proxyPrim; + + if (self){ + proxyPrim = self.ComputeProxyPrim(&renderPrim); + if (proxyPrim){ + return TfPyObjWrapper(boost::python::make_tuple(proxyPrim, + renderPrim)); + } + } + return TfPyObjWrapper(); +} + WRAP_CUSTOM { _class .def("CreatePrimvar", &UsdGeomImageable::CreatePrimvar, @@ -141,6 +163,18 @@ WRAP_CUSTOM { .def("ComputeVisibility", &UsdGeomImageable::ComputeVisibility, arg("time")=UsdTimeCode::Default()) .def("ComputePurpose", &UsdGeomImageable::ComputePurpose) + .def("ComputeProxyPrim", &_ComputeProxyPrim, + "Returns None if neither this prim nor any of its ancestors " + "has a valid renderProxy prim. Otherwise, returns a tuple of " + "(proxyPrim, renderPrimWithAuthoredProxyPrimRel)") + .def("SetProxyPrim", + (bool (UsdGeomImageable::*)(const UsdPrim &) const) + &UsdGeomImageable::SetProxyPrim, + arg("proxy")) + .def("SetProxyPrim", + (bool (UsdGeomImageable::*)(const UsdSchemaBase &) const) + &UsdGeomImageable::SetProxyPrim, + arg("proxy")) .def("MakeVisible", &UsdGeomImageable::MakeVisible, arg("time")=UsdTimeCode::Default()) .def("MakeInvisible", &UsdGeomImageable::MakeInvisible, From 237e3ffa9102bedb041aef252a3e728b21247222 Mon Sep 17 00:00:00 2001 From: superfunc Date: Fri, 16 Sep 2016 17:32:01 -0700 Subject: [PATCH 130/380] [UsdUtils] Remove redundant clipTimes authoring from stitchClips. (Internal change: 1654118) --- pxr/usd/lib/usdUtils/stitchClips.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/pxr/usd/lib/usdUtils/stitchClips.cpp b/pxr/usd/lib/usdUtils/stitchClips.cpp index 5738d7658f..8c41d24c5d 100644 --- a/pxr/usd/lib/usdUtils/stitchClips.cpp +++ b/pxr/usd/lib/usdUtils/stitchClips.cpp @@ -393,8 +393,13 @@ namespace { // insert the sample pair into the cliptimes currentClipTimes.push_back(GfVec2d(startTimeCode, startTimeCode)); - currentClipTimes.push_back(GfVec2d(startTimeCode + timeSpent, - endTimeCode)); + + // We need not author duplicate pairs + if (timeSpent != 0) { + currentClipTimes.push_back(GfVec2d(startTimeCode + timeSpent, + endTimeCode)); + } + resultLayer ->GetPrimAtPath(stitchPath) ->SetInfo(clipTimeKey, VtValue(currentClipTimes)); From 66c48e3a54754859860576309fe2f0adc9500432 Mon Sep 17 00:00:00 2001 From: takahito-tejima Date: Fri, 16 Sep 2016 17:32:11 -0700 Subject: [PATCH 131/380] [UsdImaging] fix change tracking on surface shader of nested instance instance adapter was not tracking surface shader change correctly. (Internal change: 1654151) --- pxr/usdImaging/lib/usdImaging/instanceAdapter.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/pxr/usdImaging/lib/usdImaging/instanceAdapter.cpp b/pxr/usdImaging/lib/usdImaging/instanceAdapter.cpp index 50953b07ab..887727a7c4 100644 --- a/pxr/usdImaging/lib/usdImaging/instanceAdapter.cpp +++ b/pxr/usdImaging/lib/usdImaging/instanceAdapter.cpp @@ -762,6 +762,8 @@ UsdImagingInstanceAdapter::UpdateForTimePrep(UsdPrim const& prim, valueCache->GetInstanceIndices(cachePath); if (requestedBits & HdChangeTracker::DirtyTransform) valueCache->GetInstancerTransform(cachePath); + if (requestedBits & HdChangeTracker::DirtySurfaceShader) + valueCache->GetSurfaceShader(cachePath); rproto.adapter->UpdateForTimePrep( _GetPrim(rproto.path), cachePath, time, requestedBits, @@ -853,6 +855,10 @@ UsdImagingInstanceAdapter::UpdateForTime(UsdPrim const& prim, childXf = childXf * GetRootTransform().GetInverse(); } + if (requestedBits & HdChangeTracker::DirtySurfaceShader) { + valueCache->GetSurfaceShader(cachePath) = GetShaderBinding(prim); + } + } else { // For the instancer itself, we only send the instance transforms // back as primvars, which falls into the DirtyPrimVar bucket From 46ed7ee65d3f23caf8792270e34c55e003dad8a9 Mon Sep 17 00:00:00 2001 From: dakrunch Date: Fri, 16 Sep 2016 17:32:54 -0700 Subject: [PATCH 132/380] small fixes to readMaterial (Internal change: 1654187) --- .../katana/lib/usdKatana/readMaterial.cpp | 52 ++++++++++--------- 1 file changed, 27 insertions(+), 25 deletions(-) diff --git a/third_party/katana/lib/usdKatana/readMaterial.cpp b/third_party/katana/lib/usdKatana/readMaterial.cpp index 8a7336f0b5..c4646fb772 100644 --- a/third_party/katana/lib/usdKatana/readMaterial.cpp +++ b/third_party/katana/lib/usdKatana/readMaterial.cpp @@ -132,7 +132,6 @@ _GatherShadingParameters( // only material interface attributes should bother recording such. if (shaderParam.IsConnected()) { - TfToken channel; std::vector sources; std::vector outputNames; @@ -170,20 +169,17 @@ _GatherShadingParameters( } } } - else { - // XXX: maybe the right thing is actually to just produce - // the value here and let katana handle the connection part - // correctly.. - UsdAttribute attr = shaderParam.GetAttr(); - VtValue vtValue; - if (not attr.Get(&vtValue, currentTime)) { - continue; - } - - paramsBuilder.set(inputParamId, - PxrUsdKatanaUtils::ConvertVtValueToKatAttr(vtValue, true)); + // produce the value here and let katana handle the connection part + // correctly.. + UsdAttribute attr = shaderParam.GetAttr(); + VtValue vtValue; + if (not attr.Get(&vtValue, currentTime)) { + continue; } + + paramsBuilder.set(inputParamId, + PxrUsdKatanaUtils::ConvertVtValueToKatAttr(vtValue, true)); } // XXX check for info attrs as they're not strictly parameters but @@ -265,8 +261,15 @@ _CreateShadingNode( nodesBuilder, paramsBuilder, interfaceBuilder, connectionsBuilder, targetName); - shdNodeAttr.set("parameters", paramsBuilder.build()); - shdNodeAttr.set("connections", connectionsBuilder.build()); + // if no content, don't bother creating the group. + FnKat::GroupAttribute paramsAttr = paramsBuilder.build(); + if (paramsAttr.getNumberOfChildren() > 0) { + shdNodeAttr.set("parameters", paramsAttr); + } + FnKat::GroupAttribute connectionsAttr = connectionsBuilder.build(); + if (connectionsAttr.getNumberOfChildren() > 0) { + shdNodeAttr.set("connections", connectionsAttr); + } } else if (UsdShadeShader shaderSchema = UsdShadeShader(shadingNode)) { validData = true; @@ -325,8 +328,15 @@ _CreateShadingNode( nodesBuilder, paramsBuilder, interfaceBuilder, connectionsBuilder, targetName); - shdNodeAttr.set("parameters", paramsBuilder.build()); - shdNodeAttr.set("connections", connectionsBuilder.build()); + + FnKat::GroupAttribute paramsAttr = paramsBuilder.build(); + if (paramsAttr.getNumberOfChildren() > 0) { + shdNodeAttr.set("parameters", paramsAttr); + } + FnKat::GroupAttribute connectionsAttr = connectionsBuilder.build(); + if (connectionsAttr.getNumberOfChildren() > 0) { + shdNodeAttr.set("connections", connectionsAttr); + } // read position UsdUINodeGraphNodeAPI nodeApi(shadingNode); @@ -430,10 +440,6 @@ _GetMaterialAttr( nodesBuilder, interfaceBuilder, "prman"); terminalsBuilder.set("prmanDisplacement", FnKat::StringAttribute(handle)); - // XXX: what's the right way to get the port name? - // see bug 108308 - terminalsBuilder.set("prmanDisplacementPort", - FnKat::StringAttribute("out")); } else { FnLogWarn("Displacement shader does not exist at:" << targetPath.GetString()); @@ -494,10 +500,6 @@ _GetMaterialAttr( terminalsBuilder.set("prmanBxdf", FnKat::StringAttribute(handle)); - // XXX: what's the right way to get the port name? - // see bug 108308 - terminalsBuilder.set("prmanBxdfPort", - FnKat::StringAttribute("out")); } else { FnLogWarn("Bxdf does not exist at " << targetPath.GetString()); From b838f77c520c0951fa2adec43bea1df06a99abbf Mon Sep 17 00:00:00 2001 From: superfunc Date: Fri, 16 Sep 2016 17:33:21 -0700 Subject: [PATCH 133/380] [Pxr] Small readme clarification. (Internal change: 1654196) --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index 89b8360400..4be88bdf34 100644 --- a/README.md +++ b/README.md @@ -150,6 +150,9 @@ $ export PYTHONPATH=$PYTHONPATH:USD_INSTALL_ROOT/lib/python $ usdview extras/usd/tutorials/convertingLayerFormats/sphere.usda ``` +> Note: Replace ```USD_INSTALL_ROOT``` with the location set in your build, +> usually via ```CMAKE_INSTALL_PREFIX```. + Contributing ------------ From f1adfc5a02fa1e1d6938908a4d48570e7d3ee701 Mon Sep 17 00:00:00 2001 From: poljere Date: Fri, 16 Sep 2016 17:34:41 -0700 Subject: [PATCH 134/380] [glf] If the user is using late cropping make sure we discard the mip levels and use the cropped dimensions. (Internal change: 1654226) --- pxr/imaging/lib/glf/baseTexture.cpp | 92 ++++++++++++++++++----------- pxr/imaging/lib/glf/baseTexture.h | 10 ++-- 2 files changed, 62 insertions(+), 40 deletions(-) diff --git a/pxr/imaging/lib/glf/baseTexture.cpp b/pxr/imaging/lib/glf/baseTexture.cpp index ddba728319..4fdb2862d9 100644 --- a/pxr/imaging/lib/glf/baseTexture.cpp +++ b/pxr/imaging/lib/glf/baseTexture.cpp @@ -128,7 +128,7 @@ GlfBaseTexture::_UpdateTexture(GlfBaseTextureDataConstPtr texData) void GlfBaseTexture::_CreateTexture(GlfBaseTextureDataConstPtr texData, - bool const generateMipmap, + bool const useMipmaps, int const unpackCropTop, int const unpackCropBottom, int const unpackCropLeft, @@ -141,24 +141,48 @@ GlfBaseTexture::_CreateTexture(GlfBaseTextureDataConstPtr texData, // Check if mip maps have been requested, if so, it will either // enable automatic generation or use the ones loaded in cpu memory - const int numMipLevels = texData->GetNumMipLevels(); - if (generateMipmap) { - if( numMipLevels > 1 ) { - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, numMipLevels - 1); + int numMipLevels = 1; + + if (useMipmaps) { + numMipLevels = texData->GetNumMipLevels(); + + // When we are using uncompressed textures and late cropping + // we won't use cpu loaded mips. + if (not texData->IsCompressed() and + (unpackCropRight or unpackCropLeft or + unpackCropTop or unpackCropBottom)) { + numMipLevels = 1; + } + if (numMipLevels > 1) { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, numMipLevels-1); } else { glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE); } + } else { + glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_FALSE); } - // Uncompressed textures can have cropping and other special - // behaviours. - if (not texData->IsCompressed()) { + if (texData->IsCompressed()) { + // Compressed textures don't have as many options, so + // we just need to send the mips to the driver. + for (int i = 0 ; i < numMipLevels; i++) { + glCompressedTexImage2D( GL_TEXTURE_2D, i, + texData->GLInternalFormat(), + texData->ResizedWidth(i), + texData->ResizedHeight(i), + 0, + texData->ComputeBytesUsedByMip(i), + texData->GetRawBuffer(i)); + } + } else { + // Uncompressed textures can have cropping and other special + // behaviours. if (GlfGetNumElements(texData->GLFormat()) == 1) { - GLint swizzleMask[] = {GL_RED, GL_RED, GL_RED, GL_ONE}; - glTexParameteriv( - GL_TEXTURE_2D, - GL_TEXTURE_SWIZZLE_RGBA, - swizzleMask); + GLint swizzleMask[] = {GL_RED, GL_RED, GL_RED, GL_ONE}; + glTexParameteriv( + GL_TEXTURE_2D, + GL_TEXTURE_SWIZZLE_RGBA, + swizzleMask); } // If we are not sending full mipchains to the gpu then we can @@ -198,35 +222,33 @@ GlfBaseTexture::_CreateTexture(GlfBaseTextureDataConstPtr texData, glPixelStorei(GL_UNPACK_ALIGNMENT, 1); glPixelStorei(GL_UNPACK_SKIP_PIXELS, unpackSkipPixels); glPixelStorei(GL_UNPACK_SKIP_ROWS, unpackSkipRows); - } - } - // Send the mips to the driver now, either compressed or uncompressed. - for (int i = 0 ; i < numMipLevels; i++) { - if (texData->IsCompressed()) { - glCompressedTexImage2D( GL_TEXTURE_2D, i, + // Send the mip to the driver now + glTexImage2D( GL_TEXTURE_2D, 0, texData->GLInternalFormat(), - texData->ResizedWidth(i), - texData->ResizedHeight(i), - 0, - texData->ComputeBytesUsedByMip(i), - texData->GetRawBuffer(i)); - } else { - glTexImage2D( GL_TEXTURE_2D, i, - texData->GLInternalFormat(), - texData->ResizedWidth(i), - texData->ResizedHeight(i), + texDataWidth, + texDataHeight, 0, texData->GLFormat(), texData->GLType(), - texData->GetRawBuffer(i)); + texData->GetRawBuffer(0)); + + // Reset the OpenGL state if we have modify it previously + glPopClientAttrib(); + } else { + // Send the mips to the driver now + for (int i = 0 ; i < numMipLevels; i++) { + glTexImage2D( GL_TEXTURE_2D, i, + texData->GLInternalFormat(), + texData->ResizedWidth(i), + texData->ResizedHeight(i), + 0, + texData->GLFormat(), + texData->GLType(), + texData->GetRawBuffer(i)); + } } } - - // Reset the OpenGL state if we have modify it previously - if (not texData->IsCompressed() and numMipLevels == 1) { - glPopClientAttrib(); - } glBindTexture(GL_TEXTURE_2D, 0); _SetMemoryUsed(texData->ComputeBytesUsed()); diff --git a/pxr/imaging/lib/glf/baseTexture.h b/pxr/imaging/lib/glf/baseTexture.h index fd94f74924..0043e5d2b6 100644 --- a/pxr/imaging/lib/glf/baseTexture.h +++ b/pxr/imaging/lib/glf/baseTexture.h @@ -75,11 +75,11 @@ class GlfBaseTexture : public GlfTexture { void _UpdateTexture(GlfBaseTextureDataConstPtr texData); void _CreateTexture(GlfBaseTextureDataConstPtr texData, - bool const generateMipmap, - int const unpackCropTop = 0, - int const unpackCropBottom = 0, - int const unpackCropLeft = 0, - int const unpackCropRight = 0); + bool const useMipmaps, + int const unpackCropTop = 0, + int const unpackCropBottom = 0, + int const unpackCropLeft = 0, + int const unpackCropRight = 0); private: From 9961fe0d3ac0365168a47a92bc147478429b082a Mon Sep 17 00:00:00 2001 From: jloy Date: Mon, 19 Sep 2016 09:43:36 -0700 Subject: [PATCH 135/380] tf: add test for TfPyFunctionFromPython Provide some simple coverage for the function types in wrapFunction.cpp. (Internal change: 1654494) --- pxr/base/lib/tf/testenv/testTfPyFunction.cpp | 128 +++++++++++++++++++ 1 file changed, 128 insertions(+) create mode 100644 pxr/base/lib/tf/testenv/testTfPyFunction.cpp diff --git a/pxr/base/lib/tf/testenv/testTfPyFunction.cpp b/pxr/base/lib/tf/testenv/testTfPyFunction.cpp new file mode 100644 index 0000000000..727fbe0b14 --- /dev/null +++ b/pxr/base/lib/tf/testenv/testTfPyFunction.cpp @@ -0,0 +1,128 @@ +#include "pxr/base/tf/pyFunction.h" +#include "pxr/base/tf/pyInterpreter.h" +#include "pxr/base/tf/pyUtils.h" + +#include + +#include +#include +#include +#include + +#include + +using namespace boost::python; + +static const char VoidFuncSource[] = "def VoidFunc(): pass\n"; +static const char BoolFuncSource[] = "def BoolFunc(): return True\n"; +static const char IntFuncSource[] = "def IntFunc(): return 13\n"; +static const char LongFuncSource[] = "def LongFunc(): return 17L\n"; +static const char DoubleFuncSource[] = "def DoubleFunc(): return 19.0\n"; +static const char StringFuncSource[] = "def StringFunc(): return 'a string'\n"; +static const char ObjectFuncSource[] = "def ObjectFunc(): return testObject\n"; + +template +static void +AssertCallResult(object callable, T const &expected) +{ + extract> stdFunc(callable); + TF_AXIOM(stdFunc.check()); + TF_AXIOM(stdFunc()() == expected); + + extract> boostFunc(callable); + TF_AXIOM(boostFunc.check()); + TF_AXIOM(boostFunc()() == expected); +} + +static void +AssertCallVoid(object callable) +{ + // As there's no result to check, all we care about is that calling the + // function does not throw. + extract> stdFunc(callable); + TF_AXIOM(stdFunc.check()); + stdFunc()(); + + extract> boostFunc(callable); + TF_AXIOM(boostFunc.check()); + boostFunc()(); +} + +static object +DefineFunc(const char *funcName, const char *funcSource, dict testEnv) +{ + TfPyRunString(funcSource, Py_single_input, testEnv); + return testEnv[funcName]; +} + +int +main(int argc, char **argv) +{ + TfPyInitialize(); + + // Import Tf to make sure that we get the function wrappings defined in + // wrapFunction.cpp. + object tfModule = import("pxr.Tf"); + TF_AXIOM(!tfModule.is_none()); + + // Store our test functions in this dictionary rather than the main module. + dict testEnv; + testEnv.update(import("__builtin__").attr("__dict__")); + + // Expected results of calling functions + const bool expectedBool = true; + const int expectedInt = 13; + const long expectedLong = 17; + const double expectedDouble = 19; + const std::string expectedString = "a string"; + object expectedObject = TfPyEvaluate("object()"); + testEnv["testObject"] = expectedObject; + + // Define and test regular functions + object voidFunc = DefineFunc("VoidFunc", VoidFuncSource, testEnv); + TF_AXIOM(!voidFunc.is_none()); + object boolFunc = DefineFunc("BoolFunc", BoolFuncSource, testEnv); + TF_AXIOM(!boolFunc.is_none()); + object intFunc = DefineFunc("IntFunc", IntFuncSource, testEnv); + TF_AXIOM(!intFunc.is_none()); + object longFunc = DefineFunc("LongFunc", LongFuncSource, testEnv); + TF_AXIOM(!longFunc.is_none()); + object doubleFunc = DefineFunc("DoubleFunc", DoubleFuncSource, testEnv); + TF_AXIOM(!doubleFunc.is_none()); + object stringFunc = DefineFunc("StringFunc", StringFuncSource, testEnv); + TF_AXIOM(!stringFunc.is_none()); + object objectFunc = DefineFunc("ObjectFunc", ObjectFuncSource, testEnv); + TF_AXIOM(!objectFunc.is_none()); + + AssertCallVoid(voidFunc); + AssertCallResult(boolFunc, expectedBool); + AssertCallResult(intFunc, expectedInt); + AssertCallResult(longFunc, expectedLong); + AssertCallResult(doubleFunc, expectedDouble); + AssertCallResult(stringFunc, expectedString); + AssertCallResult(objectFunc, expectedObject); + + // Define and test lambda functions + object voidLambda = TfPyEvaluate("lambda: None"); + TF_AXIOM(!voidLambda.is_none()); + object boolLambda = TfPyEvaluate("lambda: True"); + TF_AXIOM(!boolLambda.is_none()); + object intLambda = TfPyEvaluate("lambda: 13"); + TF_AXIOM(!intLambda.is_none()); + object longLambda = TfPyEvaluate("lambda: 17L"); + TF_AXIOM(!longLambda.is_none()); + object doubleLambda = TfPyEvaluate("lambda: 19.0"); + TF_AXIOM(!doubleLambda.is_none()); + object stringLambda = TfPyEvaluate("lambda: 'a string'"); + TF_AXIOM(!stringLambda.is_none()); + object objectLambda = TfPyEvaluate("lambda: testObject", testEnv); + TF_AXIOM(!objectLambda.is_none()); + + AssertCallVoid(voidLambda); + AssertCallResult(boolLambda, expectedBool); + AssertCallResult(intLambda, expectedInt); + AssertCallResult(longLambda, expectedLong); + AssertCallResult(doubleLambda, expectedDouble); + AssertCallResult(stringLambda, expectedString); + AssertCallResult(objectLambda, expectedObject); +} From e9cbfbff2d2cb465298e60617b62068489a8265d Mon Sep 17 00:00:00 2001 From: takahito-tejima Date: Mon, 19 Sep 2016 09:43:47 -0700 Subject: [PATCH 136/380] [Hd] add a defensive guard Prevent crash in HdResourceRegistry::GetResourceAllocation when a GLSL shader fails to compile but is registered in the program registry. Note that it makes sense to keep an entry for the hash of erroneous GLSL source, to avoid repeated attempt of compilation. (Internal change: 1654551) --- pxr/imaging/lib/hd/resourceRegistry.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/pxr/imaging/lib/hd/resourceRegistry.cpp b/pxr/imaging/lib/hd/resourceRegistry.cpp index 796749507a..f7947c3c72 100644 --- a/pxr/imaging/lib/hd/resourceRegistry.cpp +++ b/pxr/imaging/lib/hd/resourceRegistry.cpp @@ -585,12 +585,14 @@ HdResourceRegistry::GetResourceAllocation() const // glsl program & ubo allocation TF_FOR_ALL (progIt, _glslProgramRegistry) { + HdGLSLProgramSharedPtr const &program = progIt->second; + if (not program) continue; size_t size = - progIt->second->GetProgram().GetSize() + - progIt->second->GetGlobalUniformBuffer().GetSize(); + program->GetProgram().GetSize() + + program->GetGlobalUniformBuffer().GetSize(); // the role of program and global uniform buffer is always same. - std::string const &role = progIt->second->GetProgram().GetRole().GetString(); + std::string const &role = program->GetProgram().GetRole().GetString(); if (result.count(role)) { size_t currentSize = result[role].Get(); result[role] = VtValue(currentSize + size); From 981a81c8a6d64cd23f9d204e7d47532b083c1f0c Mon Sep 17 00:00:00 2001 From: takahito-tejima Date: Mon, 19 Sep 2016 09:44:06 -0700 Subject: [PATCH 137/380] [Hd] fix shader configuration error (Internal change: 1654553) --- pxr/imaging/lib/hdx/shaders/simpleLightingShader.glslfx | 6 ------ 1 file changed, 6 deletions(-) diff --git a/pxr/imaging/lib/hdx/shaders/simpleLightingShader.glslfx b/pxr/imaging/lib/hdx/shaders/simpleLightingShader.glslfx index fa4b2ce7bc..5482f947fd 100644 --- a/pxr/imaging/lib/hdx/shaders/simpleLightingShader.glslfx +++ b/pxr/imaging/lib/hdx/shaders/simpleLightingShader.glslfx @@ -51,9 +51,3 @@ vec3 FallbackLighting(in vec3 Peye, in vec3 Neye, in vec3 color) { return simpleLightingMaterial(vec4(color,1), vec4(Peye,1), Neye, vec4(1)).rgb; } - -// XXX: for short-term compatibility. -vec3 SimpleLighting(in vec3 Peye, in vec3 Neye, in vec3 color) -{ - return FallbackLighting(Peye, Neye, color); -} From 0191d696d07bd0dd74eb6e35475d6e2e0b72c71d Mon Sep 17 00:00:00 2001 From: sunyab Date: Mon, 19 Sep 2016 09:45:50 -0700 Subject: [PATCH 138/380] Avoid interpolating times in clips when possible Modify clip time interpolation code to avoid doing any computations when given times that exactly match what's authored in the clipTimes metadata. This helps avoid floating point precision issues that may appear if consumers use UsdTimeCode::SafeStep to author clipTimes that mimic jump discontinuities (e.g., for looping time-sampled animation from a clip). (Internal change: 1654654) --- pxr/usd/lib/usd/clip.cpp | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/pxr/usd/lib/usd/clip.cpp b/pxr/usd/lib/usd/clip.cpp index 5950587aab..f6c4a986cf 100644 --- a/pxr/usd/lib/usd/clip.cpp +++ b/pxr/usd/lib/usd/clip.cpp @@ -600,9 +600,17 @@ Usd_Clip::_TranslateTimeToInternal(ExternalTime extTime) const TimeMapping m1, m2; _GetBracketingTimeSegment(times, extTime, &m1, &m2); + // Early out in some special cases to avoid unnecessary + // math operations that could introduce precision issues. if (m1.first == m2.first) { return m1.second; } + else if (extTime == m1.first) { + return m1.second; + } + else if (extTime == m2.first) { + return m2.second; + } return (m2.second - m1.second) / (m2.first - m1.first) * (extTime - m1.first) @@ -613,9 +621,17 @@ Usd_Clip::ExternalTime Usd_Clip::_TranslateTimeToExternal( InternalTime intTime, TimeMapping m1, TimeMapping m2) const { + // Early out in some special cases to avoid unnecessary + // math operations that could introduce precision issues. if (m1.second == m2.second) { return m1.first; } + else if (intTime == m1.second) { + return m1.first; + } + else if (intTime == m2.second) { + return m2.first; + } return (m2.first - m1.first) / (m2.second - m1.second) * (intTime - m1.second) From 5c6a25ced8027a41b19403e032bd926b44b344d5 Mon Sep 17 00:00:00 2001 From: mattyjams Date: Mon, 19 Sep 2016 09:46:09 -0700 Subject: [PATCH 139/380] usdImaging: include instanceIndex in pathTranslator for TestIntersectionBatch This change allows clients of TestIntersectionBatch() to differentiate between instances. Otherwise, clients will only see the path to the instancer prim and only a single hit will be returned. (Internal change: 1654681) --- pxr/usdImaging/lib/usdImaging/engine.cpp | 4 ++-- pxr/usdImaging/lib/usdImaging/engine.h | 9 +++++---- pxr/usdImaging/lib/usdImaging/gl.cpp | 2 +- pxr/usdImaging/lib/usdImaging/gl.h | 2 +- pxr/usdImaging/lib/usdImaging/hdEngine.cpp | 4 ++-- pxr/usdImaging/lib/usdImaging/hdEngine.h | 2 +- 6 files changed, 12 insertions(+), 11 deletions(-) diff --git a/pxr/usdImaging/lib/usdImaging/engine.cpp b/pxr/usdImaging/lib/usdImaging/engine.cpp index 9a7add9742..4898071a11 100644 --- a/pxr/usdImaging/lib/usdImaging/engine.cpp +++ b/pxr/usdImaging/lib/usdImaging/engine.cpp @@ -366,7 +366,7 @@ UsdImagingEngine::TestIntersectionBatch( const SdfPathVector& paths, RenderParams params, unsigned int pickResolution, - std::function< SdfPath(const SdfPath&) > pathTranslator, + std::function< SdfPath(const SdfPath&, const int) > pathTranslator, HitBatch *outHit) { // outHit is not optional @@ -571,7 +571,7 @@ UsdImagingEngine::TestIntersectionBatch( // Translate the path. Allows client-side collating of hit prims into // useful bins as needed. The simplest translator returns primPath. // - SdfPath hitPath( pathTranslator(primPath) ); + SdfPath hitPath( pathTranslator(primPath, hitInstanceIndex) ); if( !hitPath.IsEmpty() ) { diff --git a/pxr/usdImaging/lib/usdImaging/engine.h b/pxr/usdImaging/lib/usdImaging/engine.h index 11bfa15b94..8b63f88e6b 100644 --- a/pxr/usdImaging/lib/usdImaging/engine.h +++ b/pxr/usdImaging/lib/usdImaging/engine.h @@ -233,9 +233,10 @@ class UsdImagingEngine : private boost::noncopyable { /// In batched selection scenarios, the path desired may not be as granular as /// the leaf-level prim. For example, one might want to find the closest hit /// for all prims underneath a certain path scope, or ignore others altogether. - /// The \p pathTranslator takes an \c SdfPath pointing to the hit prim, but - /// may return an empty path (signifying an ignored hit), or a different - /// simplified path altogether. + /// The \p pathTranslator takes an \c SdfPath pointing to the hit prim and + /// an integer instance index in the case where the hit is an instanced + /// object, but may return an empty path (signifying an ignored hit), or a + /// different simplified path altogether. /// /// Returned hits are collated by the translated \c SdfPath above, and placed /// in the structure pointed to by \p outHit. For each \c SdfPath in the @@ -254,7 +255,7 @@ class UsdImagingEngine : private boost::noncopyable { const SdfPathVector& paths, RenderParams params, unsigned int pickResolution, - std::function< SdfPath(const SdfPath&) > pathTranslator, + std::function< SdfPath(const SdfPath&, const int) > pathTranslator, HitBatch *outHit); /// Using colors extracted from an Id render, returns the associated diff --git a/pxr/usdImaging/lib/usdImaging/gl.cpp b/pxr/usdImaging/lib/usdImaging/gl.cpp index e5f7b0f189..a67a0ef3c5 100644 --- a/pxr/usdImaging/lib/usdImaging/gl.cpp +++ b/pxr/usdImaging/lib/usdImaging/gl.cpp @@ -307,7 +307,7 @@ UsdImagingGL::TestIntersectionBatch( const SdfPathVector& paths, RenderParams params, unsigned int pickResolution, - std::function< SdfPath(const SdfPath&) > pathTranslator, + std::function< SdfPath(const SdfPath&, const int) > pathTranslator, HitBatch *outHit) { return _engine->TestIntersectionBatch(viewMatrix, projectionMatrix, diff --git a/pxr/usdImaging/lib/usdImaging/gl.h b/pxr/usdImaging/lib/usdImaging/gl.h index c61d7f48d9..99300d1a5f 100644 --- a/pxr/usdImaging/lib/usdImaging/gl.h +++ b/pxr/usdImaging/lib/usdImaging/gl.h @@ -159,7 +159,7 @@ class UsdImagingGL : public UsdImagingEngine { const SdfPathVector& paths, RenderParams params, unsigned int pickResolution, - std::function< SdfPath(const SdfPath&) > pathTranslator, + std::function< SdfPath(const SdfPath&, const int) > pathTranslator, HitBatch *outHit); virtual VtDictionary GetResourceAllocation() const; diff --git a/pxr/usdImaging/lib/usdImaging/hdEngine.cpp b/pxr/usdImaging/lib/usdImaging/hdEngine.cpp index 6204853778..9ff014d5d7 100644 --- a/pxr/usdImaging/lib/usdImaging/hdEngine.cpp +++ b/pxr/usdImaging/lib/usdImaging/hdEngine.cpp @@ -412,7 +412,7 @@ UsdImagingHdEngine::TestIntersectionBatch( const SdfPathVector& paths, RenderParams params, unsigned int pickResolution, - std::function< SdfPath(const SdfPath&) > pathTranslator, + std::function< SdfPath(const SdfPath&, const int) > pathTranslator, HitBatch *outHit) { if (not HdRenderContextCaps::GetInstance().SupportsHydra()) { @@ -467,7 +467,7 @@ UsdImagingHdEngine::TestIntersectionBatch( rprimPath = hit.instancerId; } - HitInfo& info = (*outHit)[pathTranslator(rprimPath)]; + HitInfo& info = (*outHit)[pathTranslator(rprimPath, hit.instanceIndex)]; info.worldSpaceHitPoint = GfVec3d(hit.worldSpaceHitPoint[0], hit.worldSpaceHitPoint[1], hit.worldSpaceHitPoint[2]); diff --git a/pxr/usdImaging/lib/usdImaging/hdEngine.h b/pxr/usdImaging/lib/usdImaging/hdEngine.h index 363067e591..dc11a09d8d 100644 --- a/pxr/usdImaging/lib/usdImaging/hdEngine.h +++ b/pxr/usdImaging/lib/usdImaging/hdEngine.h @@ -128,7 +128,7 @@ class UsdImagingHdEngine : public UsdImagingEngine const SdfPathVector& paths, RenderParams params, unsigned int pickResolution, - std::function< SdfPath(const SdfPath&) > pathTranslator, + std::function< SdfPath(const SdfPath&, const int) > pathTranslator, HitBatch *outHit); virtual VtDictionary GetResourceAllocation() const; From 233a16f9d6e4255ec4c681cf6d001a957c1be140 Mon Sep 17 00:00:00 2001 From: spiffmon Date: Mon, 19 Sep 2016 09:47:39 -0700 Subject: [PATCH 140/380] update testAuthoringProperties for change 1654100 . (Internal change: 1654846) --- extras/usd/tutorials/authoringProperties/authorProperties.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/extras/usd/tutorials/authoringProperties/authorProperties.py b/extras/usd/tutorials/authoringProperties/authorProperties.py index d90d31edc8..cb8f2df60e 100644 --- a/extras/usd/tutorials/authoringProperties/authorProperties.py +++ b/extras/usd/tutorials/authoringProperties/authorProperties.py @@ -31,12 +31,12 @@ sphere = stage.GetPrimAtPath('/hello/world') # section 2 -expected = ['purpose', 'visibility', 'xformOpOrder'] +expected = ['proxyPrim', 'purpose', 'visibility', 'xformOpOrder'] assert xform.GetPropertyNames() == expected expected = ['doubleSided', 'extent', 'orientation', 'primvars:displayColor', 'primvars:displayOpacity', - 'purpose', 'radius', 'visibility', 'xformOpOrder'] + 'proxyPrim', 'purpose', 'radius', 'visibility', 'xformOpOrder'] assert sphere.GetPropertyNames() == expected From 14109e44473f146f1096cd3ebadcf0175095a962 Mon Sep 17 00:00:00 2001 From: mattyjams Date: Mon, 19 Sep 2016 09:48:23 -0700 Subject: [PATCH 141/380] add px_LegacyViewportUtils class with GetViewSelectionMatrices() method There are currently two places in pxrUsdMayaGL that use this logic, so this change consolidates them into a single function. (Internal change: 1654874) --- third_party/maya/lib/px_vp20/CMakeLists.txt | 2 + third_party/maya/lib/px_vp20/utils_legacy.cpp | 67 +++++++++++++++++++ third_party/maya/lib/px_vp20/utils_legacy.h | 52 ++++++++++++++ .../maya/lib/pxrUsdMayaGL/batchRenderer.cpp | 28 ++------ .../maya/lib/pxrUsdMayaGL/hdRenderer.cpp | 31 +++------ 5 files changed, 137 insertions(+), 43 deletions(-) create mode 100644 third_party/maya/lib/px_vp20/utils_legacy.cpp create mode 100644 third_party/maya/lib/px_vp20/utils_legacy.h diff --git a/third_party/maya/lib/px_vp20/CMakeLists.txt b/third_party/maya/lib/px_vp20/CMakeLists.txt index 9205e2c461..40a6179c68 100644 --- a/third_party/maya/lib/px_vp20/CMakeLists.txt +++ b/third_party/maya/lib/px_vp20/CMakeLists.txt @@ -2,6 +2,7 @@ set(PXR_PACKAGE px_vp20) pxr_shared_library(${PXR_PACKAGE} LIBRARIES + gf ${MAYA_OpenMaya_LIBRARY} ${MAYA_OpenMayaRender_LIBRARY} ${OPENGL_gl_LIBRARY} @@ -12,5 +13,6 @@ pxr_shared_library(${PXR_PACKAGE} PUBLIC_CLASSES utils + utils_legacy ) diff --git a/third_party/maya/lib/px_vp20/utils_legacy.cpp b/third_party/maya/lib/px_vp20/utils_legacy.cpp new file mode 100644 index 0000000000..a065dfc697 --- /dev/null +++ b/third_party/maya/lib/px_vp20/utils_legacy.cpp @@ -0,0 +1,67 @@ +// +// 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. +// +#include "px_vp20/utils_legacy.h" + +#include "pxr/base/gf/matrix4d.h" + +#include + +#include + + +/* static */ +void px_LegacyViewportUtils::GetViewSelectionMatrices( + M3dView& view, + GfMatrix4d* viewMatrix, + GfMatrix4d* projectionMatrix) +{ + if (not viewMatrix and not projectionMatrix) { + return; + } + + // We need to get the view and projection matrices for the + // area of the view that the user has clicked or dragged. + // Unfortunately the M3dView does not give us that in an easy way. + // If we extract the view and projection matrices from the M3dView object, + // it is just for the regular camera. MSelectInfo also gives us the + // selection box, so we could use that to construct the correct view + // and projection matrixes, but if we call beginSelect on the view as + // if we were going to use the selection buffer, Maya will do all the + // work for us and we can just extract the matrices from OpenGL. + + // Hit record can just be one because we are not going to draw + // anything anyway. We only want the matrices. + GLuint glHitRecord; + view.beginSelect(&glHitRecord, 1); + + if (viewMatrix) { + glGetDoublev(GL_MODELVIEW_MATRIX, viewMatrix->GetArray()); + } + if (projectionMatrix) { + glGetDoublev(GL_PROJECTION_MATRIX, projectionMatrix->GetArray()); + } + + view.endSelect(); +} + diff --git a/third_party/maya/lib/px_vp20/utils_legacy.h b/third_party/maya/lib/px_vp20/utils_legacy.h new file mode 100644 index 0000000000..ae467881d1 --- /dev/null +++ b/third_party/maya/lib/px_vp20/utils_legacy.h @@ -0,0 +1,52 @@ +// +// 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 __PX_VP20_UTILS_LEGACY_H__ +#define __PX_VP20_UTILS_LEGACY_H__ + +/// \file utils_legacy.h + +#include "pxr/base/gf/matrix4d.h" + +#include + +/// This class contains helper methods and utilities to help with the +/// transition from the Maya legacy viewport to Viewport 2.0. +class px_LegacyViewportUtils +{ +public: + /// Get the view and projection matrices used for selection from the given + /// M3dView \p view. + static void GetViewSelectionMatrices(M3dView& view, + GfMatrix4d* viewMatrix, + GfMatrix4d* projectionMatrix); + +private: + /// Creating instances of this class is disallowed by making the + /// constructor private. + px_LegacyViewportUtils(); + ~px_LegacyViewportUtils(); +}; + + +#endif // __PX_VP20_UTILS_LEGACY_H__ diff --git a/third_party/maya/lib/pxrUsdMayaGL/batchRenderer.cpp b/third_party/maya/lib/pxrUsdMayaGL/batchRenderer.cpp index 72a704ff62..0b9e4d2b3d 100644 --- a/third_party/maya/lib/pxrUsdMayaGL/batchRenderer.cpp +++ b/third_party/maya/lib/pxrUsdMayaGL/batchRenderer.cpp @@ -44,6 +44,7 @@ #include "pxr/base/tf/registryManager.h" #include "px_vp20/utils.h" +#include "px_vp20/utils_legacy.h" #include "pxrUsdMayaGL/batchRenderer.h" @@ -968,37 +969,20 @@ UsdMayaGLBatchRenderer::_GetHitInfo( TF_DEBUG(PXRUSDMAYAGL_QUEUE_INFO).Msg( "____________ SELECTION STAGE START ______________ (singleSelect = %d)\n", singleSelection ); - - // We need to get the view and projection matrices for the - // area of the view that the user has clicked or dragged. - // Unfortunately the view does not give us that in an easy way.. - // If we extract the view and projection matrices from the view object, - // it is just for the regular camera. The selectInfo also gives us the - // selection box, so we could use that to construct the correct view - // and projection matrixes, but if we call beginSelect on the view as - // if we were going to use the selection buffer, maya will do all the - // work for us and we can just extract the matrices from opengl. - + GfMatrix4d viewMatrix; GfMatrix4d projectionMatrix; - GLuint glHitRecord; - + px_LegacyViewportUtils::GetViewSelectionMatrices(view, + &viewMatrix, + &projectionMatrix); + // As Maya doesn't support batched selection, intersection testing is // actually performed in the first selection query that happens after a // render. This query occurs in the local space of SOME object, but // we need results in world space so that we have results for every // node available. worldToLocalSpace removes the local space we // happen to be in for the initial query. - GfMatrix4d worldToLocalSpace(localToWorldSpace.GetInverse()); - - // Hit record can just be one because we are not going to draw - // anything anyway. We only want the matrices :) - - view.beginSelect(&glHitRecord, 1); - glGetDoublev(GL_MODELVIEW_MATRIX, viewMatrix.GetArray()); - glGetDoublev(GL_PROJECTION_MATRIX, projectionMatrix.GetArray()); - view.endSelect(); _intersector->SetResolution(GfVec2i(pickResolution, pickResolution)); diff --git a/third_party/maya/lib/pxrUsdMayaGL/hdRenderer.cpp b/third_party/maya/lib/pxrUsdMayaGL/hdRenderer.cpp index efd5ef9432..a4a63ada54 100644 --- a/third_party/maya/lib/pxrUsdMayaGL/hdRenderer.cpp +++ b/third_party/maya/lib/pxrUsdMayaGL/hdRenderer.cpp @@ -30,6 +30,7 @@ #include "pxr/imaging/glf/glew.h" #include "pxrUsdMayaGL/hdRenderer.h" #include "px_vp20/utils.h" +#include "px_vp20/utils_legacy.h" #include #include @@ -372,32 +373,20 @@ UsdMayaGLHdRenderer::TestIntersection( return false; } - // We need to get the view and projection matrices for the - // area of the view that the user has clicked or dragged. - // Unfortunately the view does not give us that in an easy way.. - // If we extract the view and projection matrices from the view object, - // it is just for the regular camera. The selectInfo also gives us the - // selection box, so we could use that to construct the correct view - // and projection matrixes, but if we call beginSelect on the view as - // if we were going to use the selection buffer, maya will do all the - // work for us and we can just extract the matrices from opengl. GfMatrix4d viewMatrix; GfMatrix4d projectionMatrix; - GLuint glHitRecord; - // Hit record can just be one because we are not going to draw - // anything anyway. We only want the matrices :) - view.beginSelect(&glHitRecord, 1); - glGetDoublev(GL_MODELVIEW_MATRIX, viewMatrix.GetArray()); - glGetDoublev(GL_PROJECTION_MATRIX, projectionMatrix.GetArray()); - view.endSelect(); + px_LegacyViewportUtils::GetViewSelectionMatrices(view, + &viewMatrix, + &projectionMatrix); params.drawMode = UsdImagingGL::DRAW_GEOM_ONLY; - return _renderer->TestIntersection( - viewMatrix, projectionMatrix, - GfMatrix4d().SetIdentity(), - _renderedPrim, params, - hitPoint); + return _renderer->TestIntersection(viewMatrix, + projectionMatrix, + GfMatrix4d().SetIdentity(), + _renderedPrim, + params, + hitPoint); } /* static */ From 5cc18fb62eac374061e9708117d34dc6c4aa6977 Mon Sep 17 00:00:00 2001 From: takahito-tejima Date: Mon, 19 Sep 2016 09:48:41 -0700 Subject: [PATCH 142/380] [Hd] prevent from populating too big instance index buffer in case if instance indirection buffer becomes more than HD_MAX_VBO_SIZE (=1GB by default), stop populating the buffer, set the number of instances to 1, and raise a warning. ideally hydra should split that kind of instance draw into separate drawItems so that it still draws (even if it's slow) (Internal change: 1654947) --- pxr/imaging/lib/hd/bufferArrayRange.h | 3 +++ pxr/imaging/lib/hd/bufferArrayRegistry.cpp | 3 ++- pxr/imaging/lib/hd/dispatchBuffer.cpp | 6 ++++++ pxr/imaging/lib/hd/instancer.cpp | 14 ++++++++++++-- pxr/imaging/lib/hd/interleavedMemoryManager.cpp | 6 ++++++ pxr/imaging/lib/hd/interleavedMemoryManager.h | 3 +++ pxr/imaging/lib/hd/vboMemoryManager.cpp | 6 ++++++ pxr/imaging/lib/hd/vboMemoryManager.h | 3 +++ pxr/imaging/lib/hd/vboSimpleMemoryManager.cpp | 6 ++++++ pxr/imaging/lib/hd/vboSimpleMemoryManager.h | 3 +++ 10 files changed, 50 insertions(+), 3 deletions(-) diff --git a/pxr/imaging/lib/hd/bufferArrayRange.h b/pxr/imaging/lib/hd/bufferArrayRange.h index ac3310a1a9..beadbac2bc 100644 --- a/pxr/imaging/lib/hd/bufferArrayRange.h +++ b/pxr/imaging/lib/hd/bufferArrayRange.h @@ -87,6 +87,9 @@ class HdBufferArrayRange : boost::noncopyable { /// drawbatches to be rebuilt to remove expired BufferArrayRange. virtual void IncrementVersion() = 0; + /// Returns the max number of elements + virtual size_t GetMaxNumElements() const = 0; + /// Returns the GPU resource. If the buffer array contains more than one /// resource, this method raises a coding error. virtual HdBufferResourceSharedPtr GetResource() const = 0; diff --git a/pxr/imaging/lib/hd/bufferArrayRegistry.cpp b/pxr/imaging/lib/hd/bufferArrayRegistry.cpp index 06055d1e3b..d0955e9fe7 100644 --- a/pxr/imaging/lib/hd/bufferArrayRegistry.cpp +++ b/pxr/imaging/lib/hd/bufferArrayRegistry.cpp @@ -138,7 +138,8 @@ HdBufferArrayRegistry::ReallocateAll(HdAggregationStrategy *strategy) size_t numElements = range->GetNumElements(); // numElements in each range should not exceed maxTotalElements - if (not TF_VERIFY(numElements < maxTotalElements)) + if (not TF_VERIFY(numElements < maxTotalElements, + "%lu >= %lu", numElements, maxTotalElements)) continue; // over aggregation check of non-uniform buffer diff --git a/pxr/imaging/lib/hd/dispatchBuffer.cpp b/pxr/imaging/lib/hd/dispatchBuffer.cpp index 256e4bc465..97671d04f5 100644 --- a/pxr/imaging/lib/hd/dispatchBuffer.cpp +++ b/pxr/imaging/lib/hd/dispatchBuffer.cpp @@ -97,6 +97,12 @@ class Hd_DispatchBufferArrayRange : public HdBufferArrayRange { TF_CODING_ERROR("Hd_DispatchBufferArrayRange doesn't support this operation"); } + /// Returns the max number of elements + virtual size_t GetMaxNumElements() const { + TF_CODING_ERROR("Hd_DispatchBufferArrayRange doesn't support this operation"); + return 1; + } + /// Returns the GPU resource. If the buffer array contains more than one /// resource, this method raises a coding error. virtual HdBufferResourceSharedPtr GetResource() const { diff --git a/pxr/imaging/lib/hd/instancer.cpp b/pxr/imaging/lib/hd/instancer.cpp index fea57e7dea..42fc0644fc 100644 --- a/pxr/imaging/lib/hd/instancer.cpp +++ b/pxr/imaging/lib/hd/instancer.cpp @@ -268,14 +268,24 @@ HdInstancer::GetInstanceIndices(SdfPath const &prototypeId) // output : [<0>,0,3,7, <1>,1,3,7, <2>,0,4,7, <3>,1,4,7, // <4>,0,5,7, <5>,1,5,7, <6>,0,3,8, ...] - int nTotal = 1; + size_t nTotal = 1; for (int i = 0; i < instancerNumLevels; ++i) { nTotal *= instanceIndicesArray[i].size(); } int instanceIndexWidth = 1 + instancerNumLevels; + + // if it's going to be too big, issue a warning and just draw the first + // instance. + if ((nTotal*instanceIndexWidth) > indexRange->GetMaxNumElements()) { + TF_WARN("Can't draw prototype %s (too many instances) : " + "nest level=%d, # of instances=%ld", + prototypeId.GetText(), instancerNumLevels, nTotal); + nTotal = 1; + } + VtIntArray instanceIndices(nTotal * instanceIndexWidth); std::vector currents(instancerNumLevels); - for (int j = 0; j < nTotal; ++j) { + for (size_t j = 0; j < nTotal; ++j) { instanceIndices[j*instanceIndexWidth] = j; // global idx for (int i = 0; i < instancerNumLevels; ++i) { instanceIndices[j*instanceIndexWidth + i + 1] = diff --git a/pxr/imaging/lib/hd/interleavedMemoryManager.cpp b/pxr/imaging/lib/hd/interleavedMemoryManager.cpp index 9013624195..06e1d5659a 100644 --- a/pxr/imaging/lib/hd/interleavedMemoryManager.cpp +++ b/pxr/imaging/lib/hd/interleavedMemoryManager.cpp @@ -583,6 +583,12 @@ HdInterleavedMemoryManager::_StripedInterleavedBufferRange::ReadData( return result; } +size_t +HdInterleavedMemoryManager::_StripedInterleavedBufferRange::GetMaxNumElements() const +{ + return _stripedBuffer->GetMaxNumElements(); +} + HdBufferResourceSharedPtr HdInterleavedMemoryManager::_StripedInterleavedBufferRange::GetResource() const { diff --git a/pxr/imaging/lib/hd/interleavedMemoryManager.h b/pxr/imaging/lib/hd/interleavedMemoryManager.h index d563da1816..f847da3522 100644 --- a/pxr/imaging/lib/hd/interleavedMemoryManager.h +++ b/pxr/imaging/lib/hd/interleavedMemoryManager.h @@ -105,6 +105,9 @@ class HdInterleavedMemoryManager : public HdAggregationStrategy { _stripedBuffer->IncrementVersion(); } + /// Returns the max number of elements + virtual size_t GetMaxNumElements() const; + /// Returns the GPU resource. If the buffer array contains more than one /// resource, this method raises a coding error. virtual HdBufferResourceSharedPtr GetResource() const; diff --git a/pxr/imaging/lib/hd/vboMemoryManager.cpp b/pxr/imaging/lib/hd/vboMemoryManager.cpp index 65d05f323e..e634111e36 100644 --- a/pxr/imaging/lib/hd/vboMemoryManager.cpp +++ b/pxr/imaging/lib/hd/vboMemoryManager.cpp @@ -583,6 +583,12 @@ HdVBOMemoryManager::_StripedBufferArrayRange::ReadData(TfToken const &name) cons return result; } +size_t +HdVBOMemoryManager::_StripedBufferArrayRange::GetMaxNumElements() const +{ + return _stripedBufferArray->GetMaxNumElements(); +} + HdBufferResourceSharedPtr HdVBOMemoryManager::_StripedBufferArrayRange::GetResource() const { diff --git a/pxr/imaging/lib/hd/vboMemoryManager.h b/pxr/imaging/lib/hd/vboMemoryManager.h index 97dba6e0c9..ee2db0d1cd 100644 --- a/pxr/imaging/lib/hd/vboMemoryManager.h +++ b/pxr/imaging/lib/hd/vboMemoryManager.h @@ -129,6 +129,9 @@ class HdVBOMemoryManager : public HdAggregationStrategy { _stripedBufferArray->IncrementVersion(); } + /// Returns the max number of elements + virtual size_t GetMaxNumElements() const; + /// Returns the GPU resource. If the buffer array contains more than one /// resource, this method raises a coding error. virtual HdBufferResourceSharedPtr GetResource() const; diff --git a/pxr/imaging/lib/hd/vboSimpleMemoryManager.cpp b/pxr/imaging/lib/hd/vboSimpleMemoryManager.cpp index bbc1e2507d..8384d2b6c5 100644 --- a/pxr/imaging/lib/hd/vboSimpleMemoryManager.cpp +++ b/pxr/imaging/lib/hd/vboSimpleMemoryManager.cpp @@ -386,6 +386,12 @@ HdVBOSimpleMemoryManager::_SimpleBufferArrayRange::ReadData(TfToken const &name) _numElements); } +size_t +HdVBOSimpleMemoryManager::_SimpleBufferArrayRange::GetMaxNumElements() const +{ + return _bufferArray->GetMaxNumElements(); +} + HdBufferResourceSharedPtr HdVBOSimpleMemoryManager::_SimpleBufferArrayRange::GetResource() const { diff --git a/pxr/imaging/lib/hd/vboSimpleMemoryManager.h b/pxr/imaging/lib/hd/vboSimpleMemoryManager.h index b7d063622a..9117847a94 100644 --- a/pxr/imaging/lib/hd/vboSimpleMemoryManager.h +++ b/pxr/imaging/lib/hd/vboSimpleMemoryManager.h @@ -125,6 +125,9 @@ class HdVBOSimpleMemoryManager : public HdAggregationStrategy { _bufferArray->IncrementVersion(); } + /// Returns the max number of elements + virtual size_t GetMaxNumElements() const; + /// Returns the GPU resource. If the buffer array contains more than one /// resource, this method raises a coding error. virtual HdBufferResourceSharedPtr GetResource() const; From 2fd852332012046cc8c446394f5e06ff66b8a20d Mon Sep 17 00:00:00 2001 From: superfunc Date: Mon, 19 Sep 2016 09:48:52 -0700 Subject: [PATCH 143/380] [Pxr] Turn off code validation by default. This is so users aren't bombarded with warnings wrt specific versions of flex and bison. Most(99%) users will not need to edit the ascii parsers for any reason so they shouldn't have to care about the warnings as new code will not be getting generated. (Internal change: 1655084) --- cmake/defaults/Options.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/defaults/Options.cmake b/cmake/defaults/Options.cmake index 840fe53a27..d97f2d7593 100644 --- a/cmake/defaults/Options.cmake +++ b/cmake/defaults/Options.cmake @@ -22,7 +22,7 @@ # language governing permissions and limitations under the Apache License. # option(PXR_STRICT_BUILD_MODE "Turn on additional warnings. Enforce all warnings as errors." OFF) -option(PXR_VALIDATE_GENERATED_CODE "Validate script generated code" ON) +option(PXR_VALIDATE_GENERATED_CODE "Validate script generated code" OFF) option(PXR_BUILD_IMAGING "Build imaging components" ON) option(PXR_BUILD_USD_IMAGING "Build USD imaging components" ON) option(PXR_BUILD_KATANA_PLUGIN "Build usd katana plugin" OFF) From 296bd46b9ac25c73fa23c9630e4999e426ae7cdf Mon Sep 17 00:00:00 2001 From: superfunc Date: Mon, 19 Sep 2016 09:49:18 -0700 Subject: [PATCH 144/380] [Usd] Allow usddiff to compose stages for diffing. (Internal change: 1655086) --- pxr/usd/bin/usddiff/usddiff.py | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/pxr/usd/bin/usddiff/usddiff.py b/pxr/usd/bin/usddiff/usddiff.py index 5c39b9b259..c7017ee980 100644 --- a/pxr/usd/bin/usddiff/usddiff.py +++ b/pxr/usd/bin/usddiff/usddiff.py @@ -28,9 +28,11 @@ # generates a command list representing a call which will generate # a temporary ascii file used during diffing. -def _generateCatCommand(usdcatCmd, inPath, outPath, fmt=None): +def _generateCatCommand(usdcatCmd, inPath, outPath, flatten=None, fmt=None): if os.stat(inPath).st_size > 0: command = [usdcatCmd, inPath, '--out', outPath] + if flatten: + command.append('--flatten') if fmt and os.path.splitext(outPath)[1] == '.usd': command.append('--usdFormat') @@ -72,8 +74,8 @@ def _getFileFormat(path): return None -def _convertTo(inPath, outPath, usdcatCmd, fmt=None): - call(_generateCatCommand(usdcatCmd, inPath, outPath, fmt)) +def _convertTo(inPath, outPath, usdcatCmd, flatten=None, fmt=None): + call(_generateCatCommand(usdcatCmd, inPath, outPath, flatten, fmt)) def main(): import argparse @@ -92,6 +94,8 @@ def main(): help='The usd file to compare against the baseline') parser.add_argument('-n', '--noeffect', action='store_true', help='Do not edit either file.') + parser.add_argument('-c', '--compose', action='store_true', + help='Fully compose both layers as Usd Stages.') results = parser.parse_args() # Generate recognizable suffixes for our files in the temp dir @@ -118,8 +122,10 @@ def main(): sys.exit(pluginError % results.comparison) # Dump the contents of our files into the temporaries - _convertTo(results.baseline, tempBaseline.name, usdcatCmd) - _convertTo(results.comparison, tempComparison.name, usdcatCmd) + _convertTo(results.baseline, tempBaseline.name, usdcatCmd, + flatten=results.compose, fmt=None) + _convertTo(results.comparison, tempComparison.name, usdcatCmd, + flatten=results.compose, fmt=None) tempBaselineTimestamp = os.path.getmtime(tempBaseline.name) tempComparisonTimestamp = os.path.getmtime(tempComparison.name) @@ -139,14 +145,16 @@ def main(): sys.exit(accessError % results.baseline) _convertTo(tempBaseline.name, results.baseline, - usdcatCmd, baselineFileType) + usdcatCmd, flatten=results.compose, + fmt=baselineFileType) if tempComparisonChanged: if not os.access(results.comparison, os.W_OK): sys.exit(accessError % results.comparison) _convertTo(tempComparison.name, results.comparison, - usdcatCmd, comparisonFileType) + usdcatCmd, flatten=results.compose, + fmt=comparisonFileType) sys.exit(diffResult) From 05b586d46311d14197ba5cbac323d8a4d0f46de8 Mon Sep 17 00:00:00 2001 From: superfunc Date: Mon, 19 Sep 2016 09:49:25 -0700 Subject: [PATCH 145/380] [Sdf] Add some convenience to sdfGenAsciiParsers. - Show diffs using diff libs. - Discern arguments wherever possible for the user. - Clearly display what is changed vs unchanged. (Internal change: 1655104) --- pxr/usd/lib/sdf/sdfGenAsciiParsers.py | 407 ++++++++++++++++++-------- 1 file changed, 291 insertions(+), 116 deletions(-) diff --git a/pxr/usd/lib/sdf/sdfGenAsciiParsers.py b/pxr/usd/lib/sdf/sdfGenAsciiParsers.py index 8901a372df..45c725704f 100644 --- a/pxr/usd/lib/sdf/sdfGenAsciiParsers.py +++ b/pxr/usd/lib/sdf/sdfGenAsciiParsers.py @@ -23,29 +23,160 @@ # language governing permissions and limitations under the Apache License. # # A script for generating the ascii parser files for Sdf. -# This takes the lex and yacc sources in Sdf and generates C++ +# This takes the flex and bison sources in Sdf and generates C++ # source files using flex and bison. +from distutils.spawn import find_executable +from tempfile import mkdtemp from argparse import ArgumentParser -from sys import exit, stdout -from os import listdir, mkdir, getcwd, chdir, rename, path -from subprocess import call -from shutil import rmtree +from sys import exit, stdout +from os import listdir, mkdir, getcwd, chdir, rename, access, W_OK +from os.path import abspath, basename, join, splitext, isfile, dirname, exists +from subprocess import call, Popen, PIPE +from shutil import rmtree, copyfile +from difflib import unified_diff +from enum import Enum -def _validateGeneratedFiles(installedFiles, generatedFiles): - assert len(installedFiles) == len(generatedFiles),\ - "Did not generate the correct number of files" +# ----------------------------------------------------------------------------- +# Validation functions. +# This section contains code that will gather/report diffs between the generated +# code and the installed files as well as installing generating files which +# pass validation. +# ----------------------------------------------------------------------------- +def _compareFiles(installedFiles, generatedFiles, configuration): + failOnDiff = configuration[ConfigurationKey.VALIDATE] + if len(installedFiles) != len(generatedFiles): + installedNames = set(map(basename, installedFiles)) + generatedNames = set(map(basename, generatedFiles)) + + if (generatedNames - installedNames): + exit('*** Unknown files generated, please add them to the list of ' + 'base files names in sdfGenAsciiParsers.py') + + exit('*** Missing files:\n' + '\n'.join(installedNames - generatedNames)) + + diffs = {} for i in xrange(0, len(installedFiles)): with open(installedFiles[i], 'r') as installedFile,\ open(generatedFiles[i], 'r') as generatedFile: - if not installedFile.read() == generatedFile.read(): - exit('Generated file %s did not match installed file %s' \ - % (generatedFiles[i], installedFiles[i])) + installedContent = installedFile.read() + generatedContent = generatedFile.read() + + if installedContent != generatedContent: + diff = '\n'.join(unified_diff(installedContent.split('\n'), + generatedContent.split('\n'), + 'Source ' + installedFile.name, + 'Generated ' + generatedFile.name)) + diffs[basename(installedFile.name)] = diff + + if diffs and failOnDiff: + exit('*** Differing Generated Files:\n' + + '\n'.join(diffs.values())) + + return diffs + +def _copyGeneratedFiles(installedFiles, generatedFiles, diffs): + baseNames = map(basename, installedFiles) + for baseName, generatedFile, installedFile in zip(baseNames, + generatedFiles, + installedFiles): + if baseName in diffs: + print('Changed: ' + baseName) + print(diffs[baseName]) + if not access(installedFile, W_OK): + print('Cannot author ' + installedFile + ', (no write access).') + else: + copyfile(generatedFile, installedFile) + else: + print('Unchanged: ' + baseName) + +# ----------------------------------------------------------------------------- +# Code generation functions. +# This section contains the code that will actually generate the C++ source +# and headers from the yy/ll source files as well as the code which will +# curate the generated code. +# ----------------------------------------------------------------------------- +def _runBisonAndFlexCommands(configuration): + # build up collections of all relevant files, these include + # yy/ll source files, as well as the generated C++ header + # and source files. + srcDir = configuration[ConfigurationKey.SRC_DIR] + destDir = configuration[ConfigurationKey.DEST_DIR] + bases = configuration[ConfigurationKey.BASES] + + bisonFiles = [join(srcDir, base + '.yy') for base in bases] + flexFiles = [join(srcDir, base + '.ll') for base in bases] + bisonGenSources = [join(destDir, base + '.tab.cpp') for base in bases] + bisonGenHeaders = [join(destDir, base + '.tab.hpp') for base in bases] + flexGenSources = [join(destDir, base + '.lex.cpp') for base in bases] + + sourceFiles = bisonFiles + flexFiles + generatedFiles = bisonGenHeaders + bisonGenSources + flexGenSources + + # generate all components of a flex/bison command, these + # include the desired executables, flag settings + bisonFlags = lambda base: ['-d', '-p', base + 'Yy', '-o'] + flexFlags = lambda base: ['-P'+ base + "Yy", '-t'] + + bisonExecutable = configuration[ConfigurationKey.BISON_EXE] + flexExecutable = configuration[ConfigurationKey.FLEX_EXE] + + bisonCommand = lambda index: ([bisonExecutable] + + bisonFlags(base) + + [bisonGenSources[index]] + + [bisonFiles[index]]) + + flexCommand = lambda index: ([flexExecutable] + + flexFlags(base) + + [flexFiles[index]]) + + for index, base in enumerate(bases): + print 'Running bison on %s' % (base + '.yy') + call(bisonCommand(index)) + + print 'Running flex on %s' % (base + '.ll') + with open(flexGenSources[index], 'w') as outputFile: + call(flexCommand(index), stdout=outputFile) + + # prepend license header to all generated files. + licenseText = '\n'.join([ + "//" + , "// 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." + , "//\n"]) + + for generatedFile in generatedFiles: + with open(generatedFile, 'r') as f: + lines = f.read() + with open(generatedFile, 'w') as f: + f.write(licenseText) + f.write(lines) + + return sourceFiles, generatedFiles def _canonicalizeFiles(sourceFiles, generatedFiles): - PXR_PREFIX_PATH = "pxr/usd/sdf" + PXR_PREFIX_PATH = 'pxr/usd/sdf' # by default, bison will output hpp header files, we don't want this # as it goes against our convention of .h for headers. More recent @@ -73,8 +204,7 @@ def _canonicalizeFiles(sourceFiles, generatedFiles): identifiers += sourceFiles for index, fileName in enumerate(list(renamed + sourceFiles)): if '/' in fileName: - identifiers[index] = path.join(PXR_PREFIX_PATH, - path.basename(fileName)) + identifiers[index] = join(PXR_PREFIX_PATH, basename(fileName)) # create a list of pairs, representing the things to replace in our # generated files @@ -85,6 +215,8 @@ def _canonicalizeFiles(sourceFiles, generatedFiles): replacements.append((oldFileName, newFileName)) for renamedFile in renamed: + print 'Fixing line directives in ' + basename(renamedFile) + with open(renamedFile, 'r+') as inputFile: data = inputFile.read() @@ -100,132 +232,175 @@ def _canonicalizeFiles(sourceFiles, generatedFiles): return renamed +# ----------------------------------------------------------------------------- +# Configuration info. +# This section of code discerns all the necessary info the run the parser +# and lexical analyzer generators over the source files. +# ----------------------------------------------------------------------------- def _parseArguments(): parser = ArgumentParser(description='Generate Ascii File Parsers for Sdf') - parser.add_argument('--srcDir', required=True, - help='The target directory for the source files.') - parser.add_argument('--bison', required=True, + parser.add_argument('--srcDir', required=False, default=getcwd(), + help='The source directory for sdf.') + parser.add_argument('--bison', required=False, help='The location of the bison executable to be used.') - parser.add_argument('--flex', required=True, + parser.add_argument('--flex', required=False, help='The location of the flex executable to be used.') parser.add_argument('--validate', action='store_true', - help='Generate files in a temporary directory and ' - 'compare against currently installed files.') - parser.add_argument('--bases', required=True, nargs='+', + help='Verify that the source files are unchanged.') + parser.add_argument('--bases', nargs='+', help='Base file identifiers used for generation,' 'for example, textFileFormat') - arguments = parser.parse_args() + return parser.parse_args() + +ConfigurationKey = Enum('ConfigurationKey', + 'DEST_DIR SRC_DIR VALIDATE BASES BISON_EXE FLEX_EXE') - srcDir = path.abspath(arguments.srcDir) +def _getConfiguration(): + arguments = _parseArguments() - if arguments.validate: - import tempfile - destDir = tempfile.mkdtemp() + config = { ConfigurationKey.VALIDATE : arguments.validate, + ConfigurationKey.SRC_DIR : arguments.srcDir, + ConfigurationKey.DEST_DIR : mkdtemp(), + ConfigurationKey.BISON_EXE : arguments.bison, + ConfigurationKey.FLEX_EXE : arguments.flex, + ConfigurationKey.BASES : arguments.bases } + + # Ensure all optional arguments get properly populated + if not arguments.flex: + config[ConfigurationKey.FLEX_EXE] = _getFlex(config) + + if not arguments.bison: + config[ConfigurationKey.BISON_EXE] = _getBison(config) + + if not arguments.bases: + allFiles = listdir(arguments.srcDir) + validExts = ['.yy', '.ll'] + relevantFiles = filter(lambda f: splitext(f)[1] in validExts, allFiles) + bases = list(set(map(lambda f: splitext(f)[0], relevantFiles))) + + if not bases: + exit('*** Unable to find source files for parser. Ensure that they ' + 'are in the source directory(--srcDir). If unspecified, the ' + 'source directory is assumed to be the current directory.') + + config[ConfigurationKey.BASES] = bases + + _validateSourceDirectory(config) + + return config + +def _validateSourceDirectory(configuration): + bases = configuration[ConfigurationKey.BASES] + srcDir = configuration[ConfigurationKey.SRC_DIR] + + allFiles = ([join(srcDir, base + '.yy') for base in bases] + + [join(srcDir, base + '.ll') for base in bases] + + [join(srcDir, base + '.tab.cpp') for base in bases] + + [join(srcDir, base + '.tab.h') for base in bases] + + [join(srcDir, base + '.lex.cpp') for base in bases]) + + if not all(isfile(f) for f in allFiles): + exit('*** Invalid source directory. This directory must ' + 'contain all necessary flex/bison sources.') + +# ----------------------------------------------------------------------------- +# Build system info. +# This is needed for discerning which flex/bison to use when +# running sdfGenAsciiParsers. This works in the context of either a +# SCons build configuration or a CMake build configuration. +# ----------------------------------------------------------------------------- +BuildSystem = Enum('BuildSystem', 'SCONS CMAKE') + +def _determineBuildSystem(configuration): + srcDir = configuration[ConfigurationKey.SRC_DIR] + if isfile(join(srcDir, 'SConscript')): + return BuildSystem.SCONS + elif isfile(join(srcDir, 'CMakeLists.txt')): + return BuildSystem.CMAKE else: - destDir = srcDir + exit('*** Unable to determine build system.') - return {'bison': arguments.bison, - 'flex' : arguments.flex, - 'validate': arguments.validate, - 'srcDir': srcDir, - 'destDir': destDir, - 'bases': list(arguments.bases)} +def _getSconsBuildEnvSetting(environmentVariable, configuration): + command = [find_executable('scons'), '-u', + '-Qq', '--echo=' + environmentVariable] + line, _ = Popen(command, stdout=PIPE).communicate() + _, envSettingValue = line.strip().split(' = ') -def _runYaccAndLexCommands(configuration): - # build up collections of all relevant files, these include - # yy/ll source files, as well as the generated C++ header - # and source files. - srcDir = configuration['srcDir'] - destDir = configuration['destDir'] - bases = configuration['bases'] + if not envSettingValue: + exit('*** Unable to determine ' + environmentVariable + 'from ' + 'SCons build system. Try supplying it through the command line ' + 'options.') - yaccFiles = [path.join(srcDir, base + '.yy') for base in bases] - lexFiles = [path.join(srcDir, base + '.ll') for base in bases] - yaccGenSources = [path.join(destDir, base + '.tab.cpp') for base in bases] - yaccGenHeaders = [path.join(destDir, base + '.tab.hpp') for base in bases] - lexGenSources = [path.join(destDir, base + '.lex.cpp') for base in bases] + return envSettingValue - sourceFiles = yaccFiles + lexFiles - generatedFiles = yaccGenHeaders + yaccGenSources + lexGenSources - # generate all components of a lex/yacc command, these - # include the desired executables, flag settings - yaccFlags = lambda base: ['-d', '-p', base + 'Yy', '-o'] - lexFlags = lambda base: ['-P'+ base + "Yy", '-t'] +def _getCMakeBuildEnvSetting(environmentVariable, configuration): + # Gather the root of our source directory, we'll need to + # point CMake to it to find the cached variables. + srcRootDir = configuration[ConfigurationKey.SRC_DIR] - yaccExecutable = configuration['bison'] - lexExecutable = configuration['flex'] - - yaccCommand = lambda index: ([yaccExecutable] - + yaccFlags(base) - + [yaccGenSources[index]] - + [yaccFiles[index]]) - - lexCommand = lambda index: ([lexExecutable] - + lexFlags(base) - + [lexFiles[index]]) - - for index, base in enumerate(bases): - print 'Running %s on %s' %(yaccExecutable, base) - call(yaccCommand(index)) + foundPxr = lambda d: 'pxr' in map(basename, listdir(d)) + while exists(srcRootDir) and (not foundPxr(srcRootDir)): + srcRootDir = dirname(srcRootDir) - print 'Running %s on %s' %(lexExecutable, base) - with open(lexGenSources[index], 'w') as outputFile: - call(lexCommand(index), stdout=outputFile) + if srcRootDir is None: + exit('*** Unable to find root of this source tree, ' + 'this information is needed for obtaining build environment ' + 'information from CMake.') - # prepend license header to all generated files. - licenseText = '''\ - // - // 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. - // - ''' - import textwrap - licenseText = textwrap.dedent(licenseText) + command = [find_executable('cmake'), '-LA', '-N', srcRootDir] + output, _ = Popen(command, stdout=PIPE).communicate() + line = filter(lambda o: environmentVariable in o, output.split('\n'))[0] + _, envSettingValue = line.strip().split('=') - for generatedFile in generatedFiles: - with open(generatedFile, 'r') as f: - lines = f.read() - with open(generatedFile, 'w') as f: - f.write(licenseText) - f.write(lines) + if not envSettingValue: + exit('*** Unable to determine ' + environmentVariable + 'from ' + 'CMake build system. Try supplying it through the command line ' + 'options.') - return sourceFiles, generatedFiles + return envSettingValue + +def _getFlex(configuration): + buildSystem = _determineBuildSystem(configuration) + + if buildSystem == BuildSystem.SCONS: + return _getSconsBuildEnvSetting('LEX', configuration) + elif buildSystem == BuildSystem.CMAKE: + return _getCMakeBuildEnvSetting('FLEX_EXECUTABLE', configuration) + +def _getBison(configuration): + buildSystem = _determineBuildSystem(configuration) + if buildSystem == BuildSystem.SCONS: + return _getSconsBuildEnvSetting('YACC', configuration) + elif buildSystem == BuildSystem.CMAKE: + return _getCMakeBuildEnvSetting('BISON_EXECUTABLE', configuration) + +# ----------------------------------------------------------------------------- + +def _printSection(sectionInfo): + print '+-------------------------------------------------+' + print sectionInfo + print '+-------------------------------------------------+' if __name__ == '__main__': - configuration = _parseArguments() + configuration = _getConfiguration() - print 'Running lex and yacc on sources' - sourceFiles, generatedFiles = _runYaccAndLexCommands(configuration) + _printSection('Running flex and bison on sources') + sourceFiles, generatedFiles = _runBisonAndFlexCommands(configuration) - print 'Canonicalizing generated files' + _printSection('Canonicalizing generated files') generatedFiles = _canonicalizeFiles(sourceFiles, generatedFiles) - if configuration['validate']: - print 'Validating generated files' - installedFiles = [path.join(configuration['srcDir'], path.basename(f)) - for f in generatedFiles] - _validateGeneratedFiles(installedFiles, generatedFiles) - - # if validation passed, we can clean up our temp dir - rmtree(configuration['destDir']) + diffSectionMsg = 'Checking for diffs' + if configuration[ConfigurationKey.VALIDATE]: + diffSectionMsg = diffSectionMsg + '(validation on)' + + _printSection(diffSectionMsg) + installedFiles = [join(configuration[ConfigurationKey.SRC_DIR], basename(f)) + for f in generatedFiles] + + diffs = _compareFiles(installedFiles, generatedFiles, configuration) + _copyGeneratedFiles(installedFiles, generatedFiles, diffs) + # If validation passed, clean up the generated files + rmtree(configuration[ConfigurationKey.DEST_DIR]) From 2e57bb9413d9484eda71b3706131ec68281d2855 Mon Sep 17 00:00:00 2001 From: mattyjams Date: Mon, 19 Sep 2016 09:49:36 -0700 Subject: [PATCH 146/380] follow-up to change 1654681: make both the hit object path AND the instancer path available. (Internal change: 1655114) --- pxr/usdImaging/lib/usdImaging/engine.cpp | 8 ++++--- pxr/usdImaging/lib/usdImaging/engine.h | 26 ++++++++++++++-------- pxr/usdImaging/lib/usdImaging/gl.cpp | 2 +- pxr/usdImaging/lib/usdImaging/gl.h | 5 ++++- pxr/usdImaging/lib/usdImaging/hdEngine.cpp | 15 +++++-------- pxr/usdImaging/lib/usdImaging/hdEngine.h | 9 +++++--- 6 files changed, 39 insertions(+), 26 deletions(-) diff --git a/pxr/usdImaging/lib/usdImaging/engine.cpp b/pxr/usdImaging/lib/usdImaging/engine.cpp index 4898071a11..777c1d1d54 100644 --- a/pxr/usdImaging/lib/usdImaging/engine.cpp +++ b/pxr/usdImaging/lib/usdImaging/engine.cpp @@ -366,7 +366,7 @@ UsdImagingEngine::TestIntersectionBatch( const SdfPathVector& paths, RenderParams params, unsigned int pickResolution, - std::function< SdfPath(const SdfPath&, const int) > pathTranslator, + PathTranslatorCallback pathTranslator, HitBatch *outHit) { // outHit is not optional @@ -571,7 +571,9 @@ UsdImagingEngine::TestIntersectionBatch( // Translate the path. Allows client-side collating of hit prims into // useful bins as needed. The simplest translator returns primPath. // - SdfPath hitPath( pathTranslator(primPath, hitInstanceIndex) ); + // Note that this non-Hydra implementation has no concept of an + // instancer path. + SdfPath hitPath( pathTranslator(primPath, SdfPath(), hitInstanceIndex) ); if( !hitPath.IsEmpty() ) { @@ -616,7 +618,7 @@ UsdImagingEngine::GetPrimPathFromPrimIdColor(GfVec4i const &/*primIdColor*/, /* virtual */ SdfPath -UsdImagingEngine::GetPrimPathFromInstanceIndex(SdfPath const& instancerPath, +UsdImagingEngine::GetPrimPathFromInstanceIndex(SdfPath const& protoPrimPath, int instanceIndex, int *absoluteInstanceIndex) { diff --git a/pxr/usdImaging/lib/usdImaging/engine.h b/pxr/usdImaging/lib/usdImaging/engine.h index 8b63f88e6b..bff72d3b3e 100644 --- a/pxr/usdImaging/lib/usdImaging/engine.h +++ b/pxr/usdImaging/lib/usdImaging/engine.h @@ -21,6 +21,9 @@ // KIND, either express or implied. See the Apache License for the specific // language governing permissions and limitations under the Apache License. // + +/// \file engine.h + #pragma once #include "pxr/usdImaging/usdImaging/version.h" @@ -215,13 +218,17 @@ class UsdImagingEngine : private boost::noncopyable { const GfMatrix4d &viewMatrix, const GfMatrix4d &projectionMatrix, const GfMatrix4d &worldToLocalSpace, - const UsdPrim& root, + const UsdPrim& root, RenderParams params, GfVec3d *outHitPoint, - SdfPath *outHitPrimPath = NULL, + SdfPath *outHitPrimPath = NULL, SdfPath *outInstancerPath = NULL, - int *outHitInstanceIndex = NULL); - + int *outHitInstanceIndex = NULL); + + /// A callback function to control collating intersection test hits. + /// See the documentation for TestIntersectionBatch() below for more detail. + typedef std::function< SdfPath(const SdfPath&, const SdfPath&, const int) > PathTranslatorCallback; + /// Finds closest point of interesection with a frustum by rendering a batch. /// /// This method uses a PickRender and a customized depth buffer to find an @@ -233,10 +240,11 @@ class UsdImagingEngine : private boost::noncopyable { /// In batched selection scenarios, the path desired may not be as granular as /// the leaf-level prim. For example, one might want to find the closest hit /// for all prims underneath a certain path scope, or ignore others altogether. - /// The \p pathTranslator takes an \c SdfPath pointing to the hit prim and - /// an integer instance index in the case where the hit is an instanced - /// object, but may return an empty path (signifying an ignored hit), or a - /// different simplified path altogether. + /// The \p pathTranslator receives an \c SdfPath pointing to the hit prim + /// as well as an \c SdfPath pointing to the instancer prim and an integer + /// instance index in the case where the hit is an instanced object. It may + /// return an empty path (signifying an ignored hit), or a different + /// simplified path altogether. /// /// Returned hits are collated by the translated \c SdfPath above, and placed /// in the structure pointed to by \p outHit. For each \c SdfPath in the @@ -255,7 +263,7 @@ class UsdImagingEngine : private boost::noncopyable { const SdfPathVector& paths, RenderParams params, unsigned int pickResolution, - std::function< SdfPath(const SdfPath&, const int) > pathTranslator, + PathTranslatorCallback pathTranslator, HitBatch *outHit); /// Using colors extracted from an Id render, returns the associated diff --git a/pxr/usdImaging/lib/usdImaging/gl.cpp b/pxr/usdImaging/lib/usdImaging/gl.cpp index a67a0ef3c5..fc70bf4d6e 100644 --- a/pxr/usdImaging/lib/usdImaging/gl.cpp +++ b/pxr/usdImaging/lib/usdImaging/gl.cpp @@ -307,7 +307,7 @@ UsdImagingGL::TestIntersectionBatch( const SdfPathVector& paths, RenderParams params, unsigned int pickResolution, - std::function< SdfPath(const SdfPath&, const int) > pathTranslator, + PathTranslatorCallback pathTranslator, HitBatch *outHit) { return _engine->TestIntersectionBatch(viewMatrix, projectionMatrix, diff --git a/pxr/usdImaging/lib/usdImaging/gl.h b/pxr/usdImaging/lib/usdImaging/gl.h index 99300d1a5f..fe5138a980 100644 --- a/pxr/usdImaging/lib/usdImaging/gl.h +++ b/pxr/usdImaging/lib/usdImaging/gl.h @@ -21,6 +21,9 @@ // KIND, either express or implied. See the Apache License for the specific // language governing permissions and limitations under the Apache License. // + +/// \file gl.h + #pragma once #include "pxr/usdImaging/usdImaging/engine.h" @@ -159,7 +162,7 @@ class UsdImagingGL : public UsdImagingEngine { const SdfPathVector& paths, RenderParams params, unsigned int pickResolution, - std::function< SdfPath(const SdfPath&, const int) > pathTranslator, + PathTranslatorCallback pathTranslator, HitBatch *outHit); virtual VtDictionary GetResourceAllocation() const; diff --git a/pxr/usdImaging/lib/usdImaging/hdEngine.cpp b/pxr/usdImaging/lib/usdImaging/hdEngine.cpp index 9ff014d5d7..b1848e321c 100644 --- a/pxr/usdImaging/lib/usdImaging/hdEngine.cpp +++ b/pxr/usdImaging/lib/usdImaging/hdEngine.cpp @@ -412,7 +412,7 @@ UsdImagingHdEngine::TestIntersectionBatch( const SdfPathVector& paths, RenderParams params, unsigned int pickResolution, - std::function< SdfPath(const SdfPath&, const int) > pathTranslator, + PathTranslatorCallback pathTranslator, HitBatch *outHit) { if (not HdRenderContextCaps::GetInstance().SupportsHydra()) { @@ -460,18 +460,15 @@ UsdImagingHdEngine::TestIntersectionBatch( } for (const HdxIntersector::Hit& hit : hits) { - // Preserve previous behavior of TestIntersection, returning the - // instancer when a prototype is picked. - SdfPath rprimPath = hit.objectId; - if (not hit.instancerId.IsEmpty()) { - rprimPath = hit.instancerId; - } + const SdfPath primPath = hit.objectId; + const SdfPath instancerPath = hit.instancerId; + const int instanceIndex = hit.instanceIndex; - HitInfo& info = (*outHit)[pathTranslator(rprimPath, hit.instanceIndex)]; + HitInfo& info = (*outHit)[pathTranslator(primPath, instancerPath, instanceIndex)]; info.worldSpaceHitPoint = GfVec3d(hit.worldSpaceHitPoint[0], hit.worldSpaceHitPoint[1], hit.worldSpaceHitPoint[2]); - info.hitInstanceIndex = hit.instanceIndex; + info.hitInstanceIndex = instanceIndex; } return true; diff --git a/pxr/usdImaging/lib/usdImaging/hdEngine.h b/pxr/usdImaging/lib/usdImaging/hdEngine.h index dc11a09d8d..c7bdd3bfb0 100644 --- a/pxr/usdImaging/lib/usdImaging/hdEngine.h +++ b/pxr/usdImaging/lib/usdImaging/hdEngine.h @@ -21,6 +21,9 @@ // KIND, either express or implied. See the Apache License for the specific // language governing permissions and limitations under the Apache License. // + +/// \file hdEngine.h + #pragma once #include "pxr/usdImaging/usdImaging/engine.h" @@ -117,9 +120,9 @@ class UsdImagingHdEngine : public UsdImagingEngine const UsdPrim& root, RenderParams params, GfVec3d *outHitPoint, - SdfPath *outHitPrimPath = NULL, + SdfPath *outHitPrimPath = NULL, SdfPath *outHitInstancerPath = NULL, - int *outHitInstanceIndex = NULL); + int *outHitInstanceIndex = NULL); virtual bool TestIntersectionBatch( const GfMatrix4d &viewMatrix, @@ -128,7 +131,7 @@ class UsdImagingHdEngine : public UsdImagingEngine const SdfPathVector& paths, RenderParams params, unsigned int pickResolution, - std::function< SdfPath(const SdfPath&, const int) > pathTranslator, + PathTranslatorCallback pathTranslator, HitBatch *outHit); virtual VtDictionary GetResourceAllocation() const; From ca9f8ef9ae2944d4fe755e4924e97b22be700fe7 Mon Sep 17 00:00:00 2001 From: mattyjams Date: Mon, 19 Sep 2016 09:49:53 -0700 Subject: [PATCH 147/380] clean up/simplify exporting of normals for polygonal meshes (Internal change: 1655207) --- .../maya/lib/usdMaya/MayaMeshWriter.cpp | 75 ++++++++++++------- third_party/maya/lib/usdMaya/meshUtil.cpp | 15 ++-- third_party/maya/lib/usdMaya/meshUtil.h | 5 +- 3 files changed, 58 insertions(+), 37 deletions(-) diff --git a/third_party/maya/lib/usdMaya/MayaMeshWriter.cpp b/third_party/maya/lib/usdMaya/MayaMeshWriter.cpp index b37c1a34f4..c7ddde8065 100644 --- a/third_party/maya/lib/usdMaya/MayaMeshWriter.cpp +++ b/third_party/maya/lib/usdMaya/MayaMeshWriter.cpp @@ -33,6 +33,7 @@ #include #include +#include #include TF_DEFINE_PRIVATE_TOKENS(_tokens, @@ -77,6 +78,45 @@ UsdPrim MayaMeshWriter::write(const UsdTimeCode &usdTime) return meshPrim; } +static +bool +_GetMeshNormals( + const MFnMesh& mesh, + VtArray* normalsArray, + TfToken* interpolation) +{ + MStatus status; + + // Sanity check first to make sure we can get this mesh's normals. + int numNormals = mesh.numNormals(&status); + if (status != MS::kSuccess or numNormals == 0) { + return false; + } + + const unsigned int numFaceVertices = mesh.numFaceVertices(&status); + if (status != MS::kSuccess) { + return false; + } + + normalsArray->resize(numFaceVertices); + *interpolation = UsdGeomTokens->faceVarying; + + MItMeshFaceVertex itFV(mesh.object()); + unsigned int fvi = 0; + for (itFV.reset(); not itFV.isDone(); itFV.next(), ++fvi) { + MVector normal; + status = itFV.getNormal(normal); + if (status != MS::kSuccess) { + return false; + } + + (*normalsArray)[fvi][0] = normal[0]; + (*normalsArray)[fvi][1] = normal[1]; + (*normalsArray)[fvi][2] = normal[2]; + } + + return true; +} // virtual bool MayaMeshWriter::writeMeshAttrs(const UsdTimeCode &usdTime, UsdGeomMesh &primSchema) @@ -145,33 +185,16 @@ bool MayaMeshWriter::writeMeshAttrs(const UsdTimeCode &usdTime, UsdGeomMesh &pri primSchema.CreateSubdivisionSchemeAttr(VtValue(sdScheme), true); // Polygonal Mesh Case - if (sdScheme==UsdGeomTokens->none) { - // Support for standard USD bool and with Mojito bool tag - TfToken normalInterp=PxrUsdMayaMeshUtil::getEmitNormals(lMesh, UsdGeomTokens->none); - - if (normalInterp==UsdGeomTokens->faceVarying) { - // Get References to members of meshData object - MFloatVectorArray normalArray; - MFloatVectorArray vertexNormalArray; - - lMesh.getNormals(normalArray, MSpace::kObject); - - // Iterate through each face in the mesh. - vertexNormalArray.setLength(lMesh.numFaceVertices()); - VtArray meshNormals(lMesh.numFaceVertices()); - size_t faceVertIdx = 0; - for (MItMeshPolygon faceIter(getDagPath()); !faceIter.isDone(); faceIter.next()) { - // Iterate through each face-vertex. - for (size_t locVertIdx = 0; locVertIdx < faceIter.polygonVertexCount(); - ++locVertIdx, ++faceVertIdx) { - int index=faceIter.normalIndex(locVertIdx); - for (int j=0;j<3;j++) { - meshNormals[faceVertIdx][j]=normalArray[index][j]; - } - } + if (sdScheme == UsdGeomTokens->none) { + // Support for standard USD bool and Mojito bool tags. + if (PxrUsdMayaMeshUtil::getEmitNormals(lMesh)) { + VtArray meshNormals; + TfToken normalInterp; + + if (_GetMeshNormals(lMesh, &meshNormals, &normalInterp)) { + primSchema.GetNormalsAttr().Set(meshNormals, usdTime); + primSchema.SetNormalsInterpolation(normalInterp); } - primSchema.GetNormalsAttr().Set(meshNormals, usdTime); - primSchema.SetNormalsInterpolation(normalInterp); } } else { TfToken sdInterpBound = PxrUsdMayaMeshUtil::getSubdivInterpBoundary( diff --git a/third_party/maya/lib/usdMaya/meshUtil.cpp b/third_party/maya/lib/usdMaya/meshUtil.cpp index 03302a9af4..5b665b0eb8 100644 --- a/third_party/maya/lib/usdMaya/meshUtil.cpp +++ b/third_party/maya/lib/usdMaya/meshUtil.cpp @@ -52,22 +52,17 @@ TF_DEFINE_PRIVATE_TOKENS( // This can be customized for specific pipeline // We read the USD bool attribute, if not present we look for the mojito bool attribute -// If not we return the default value -TfToken PxrUsdMayaMeshUtil::getEmitNormals(const MFnMesh &mesh, TfToken defaultValue) +bool PxrUsdMayaMeshUtil::getEmitNormals(const MFnMesh &mesh) { MPlug plug = mesh.findPlug(MString(_meshTokens->USD_EmitNormals.GetText())); if (plug.isNull()) { plug = mesh.findPlug(MString("mjtoMeshVtxNormals")); } - if (!plug.isNull()) { - if (plug.asBool()) { - return UsdGeomTokens->faceVarying; - } else { - return UsdGeomTokens->none; - } - } else { - return defaultValue; + if (not plug.isNull() and plug.asBool()) { + return true; } + + return false; } TfToken PxrUsdMayaMeshUtil::setEmitNormals(const UsdGeomMesh &primSchema, MFnMesh &meshFn, TfToken defaultValue) diff --git a/third_party/maya/lib/usdMaya/meshUtil.h b/third_party/maya/lib/usdMaya/meshUtil.h index d92d98ac12..3aa74c2e2b 100644 --- a/third_party/maya/lib/usdMaya/meshUtil.h +++ b/third_party/maya/lib/usdMaya/meshUtil.h @@ -21,6 +21,9 @@ // KIND, either express or implied. See the Apache License for the specific // language governing permissions and limitations under the Apache License. // + +/// \file meshUtil.h + #ifndef PXRUSDMAYA_MESH_UTIL_H #define PXRUSDMAYA_MESH_UTIL_H @@ -33,7 +36,7 @@ class UsdGeomMesh; namespace PxrUsdMayaMeshUtil { - TfToken getEmitNormals(const MFnMesh &mesh, TfToken defaultValue); + bool getEmitNormals(const MFnMesh &mesh); TfToken setEmitNormals(const UsdGeomMesh &primSchema, MFnMesh &meshFn, TfToken defaultValue); TfToken getSubdivScheme(const MFnMesh &mesh, TfToken defaultValue); From f26ee3e0af30eaa15195e2150e1d2b6d3ed71c8a Mon Sep 17 00:00:00 2001 From: superfunc Date: Mon, 19 Sep 2016 09:50:02 -0700 Subject: [PATCH 148/380] [UsdUtils] Reorganize stitchClips to allow users to stitch the topology of a set of clips without generating root layer metadata. This is in place to facilitate the upcoming template metadata which will allow users to have the clip metadata generated for them by UsdStage. (Internal change: 1655228) --- pxr/usd/bin/usdstitchclips/usdstitchclips.py | 9 +- pxr/usd/lib/usdUtils/stitchClips.cpp | 345 +++++++++++-------- pxr/usd/lib/usdUtils/stitchClips.h | 14 + pxr/usd/lib/usdUtils/wrapStitchClips.cpp | 14 +- 4 files changed, 225 insertions(+), 157 deletions(-) diff --git a/pxr/usd/bin/usdstitchclips/usdstitchclips.py b/pxr/usd/bin/usdstitchclips/usdstitchclips.py index ea48aa8b43..c532201344 100644 --- a/pxr/usd/bin/usdstitchclips/usdstitchclips.py +++ b/pxr/usd/bin/usdstitchclips/usdstitchclips.py @@ -64,7 +64,9 @@ try: outLayer = Sdf.Layer.FindOrOpen(results.out) + outLayerGenerated = False if not outLayer: + outLayerGenerated = True outLayer = Sdf.Layer.CreateNew(results.out) if results.startTimeCode: @@ -77,7 +79,8 @@ outLayer.comment = 'Generated with ' + ' '.join(sys.argv) outLayer.Save() -# if something in the authoring fails, remove the output file except Tf.ErrorException as e: - print e - sys.exit(1) + # if something in the authoring fails, remove the output file + if outLayerGenerated: + os.remove(results.out) + sys.exit(e) diff --git a/pxr/usd/lib/usdUtils/stitchClips.cpp b/pxr/usd/lib/usdUtils/stitchClips.cpp index 8c41d24c5d..8b636728be 100644 --- a/pxr/usd/lib/usdUtils/stitchClips.cpp +++ b/pxr/usd/lib/usdUtils/stitchClips.cpp @@ -40,6 +40,7 @@ #include "pxr/base/tf/warning.h" #include "pxr/base/tf/pyLock.h" #include "pxr/base/tf/fileUtils.h" +#include "pxr/base/tf/nullPtr.h" #include "pxr/base/gf/vec2d.h" #include "pxr/base/work/loops.h" @@ -50,58 +51,19 @@ #include #include #include +#include namespace { - // internal functions for merging clip data + // typedefs // ------------------------------------------------------------------------ - bool _UsdUtilsStitchClipsImpl(const SdfLayerHandle& resultLayer, - const SdfLayerRefPtr& topologyLayer, - const SdfLayerRefPtrVector& clipLayers, - const SdfPath& clipPath, - const double startTimeCode); - - void _StitchClipAssetPath(const SdfLayerRefPtr&, const SdfLayerRefPtr&, - const SdfPath&); - void _StitchClipTime(const SdfLayerRefPtr&, const SdfLayerRefPtr&, - const SdfPath&); - void _StitchClipActive(const SdfLayerRefPtr&, const SdfLayerRefPtr&, - const SdfPath&); - void _StitchClipPrimPath(const SdfLayerRefPtr&, const SdfPath&); - void _StitchClipTopologyLayerReference(const SdfLayerRefPtr& resultLayer, - const SdfPath& rootPath, - const std::string& topIdentifier); - - void _StitchClipManifest(const SdfLayerRefPtr&, const SdfLayerRefPtr&, - const SdfPath&); - void _StitchClipMetadata(const SdfLayerRefPtr&, const SdfLayerRefPtr&, - const SdfPath&, const double); - void _SetTimeCodeRange(const SdfLayerHandle&, const SdfPath&, - double startTimeCode = - std::numeric_limits::max()); - void _StitchLayers(const SdfLayerHandle&, - const SdfLayerRefPtr&, - const SdfLayerRefPtrVector&, - const SdfPath&); - - // general utilities - std::string _CreateTopologyName(const std::string&); - std::string _GetRelativePathIfPossible(const std::string&, - const std::string&, - const std::string&); - - // validation utilities - bool _ClipLayersAreValid(const SdfLayerRefPtrVector& clipLayers, - const std::vector& clipLayerFiles, - const SdfPath& clipPath); - void _CleanUpGeneratedLayers(const std::string& topologyLayerName, - const std::string& resultLayerName, - const bool topologyWasGenerated); - - // convenience typedefs + using _SdfAssetArray = VtArray; + using _ClipFileVector = std::vector; + + // constants // ------------------------------------------------------------------------ - typedef VtArray _SdfAssetArray; + constexpr double TIME_MAX = std::numeric_limits::max(); - // convenience keys for indexing into the clip info + // keys for indexing into the clip info // XXX: This code is shared in usd/clip.h // ------------------------------------------------------------------------ const TfToken clipActiveKey = TfToken("clipActive"); @@ -110,6 +72,22 @@ namespace { const TfToken clipAssetPathsKey = TfToken("clipAssetPaths"); const TfToken clipManifestAssetPath = TfToken("clipManifestAssetPath"); + // Convenience function for wrapping up nice error message + // when checking os permissions of a layers backing file. + bool + _LayerIsWritable(const SdfLayerHandle& layer) + { + if (layer + and TfIsFile(layer->GetIdentifier()) + and not TfIsWritable(layer->GetIdentifier())) { + TF_RUNTIME_ERROR("Error: Layer %s is unwritable.", + layer->GetIdentifier().c_str()); + return false; + } + + return true; + } + // Private function for simplifying queries // Looks up a value at a prim and converts its type template @@ -161,7 +139,10 @@ namespace { // Retime a set of clipActives that have been joined together with // _MergeRootLayerMetadata. - void _RetimeClipActive(const SdfLayerHandle& layer, const SdfPath& path) { + void + _RetimeClipActive(const SdfLayerHandle& layer, + const SdfPath& path) + { size_t timer = 0; auto result = _GetUnboxedValue(layer, path, clipActiveKey); @@ -173,6 +154,32 @@ namespace { layer->GetPrimAtPath(path)->SetInfo(clipActiveKey, VtValue(result)); } + // Try to determine if we should use a relative path for this + // clip asset path. If the clip's identifier is itself has no + // directory component, assume it's relative to the result layer. + // Otherwise, look at the real paths to see if the clip path + // can be made relative to the result layer. + std::string + _GetRelativePathIfPossible(const std::string& referencedIdentifier, + const std::string& referencedRealPath, + const std::string& resultRealPath) + { + std::string resultingIdentifier; + if (TfGetPathName(referencedIdentifier).empty()) { + resultingIdentifier = "./" + referencedIdentifier; + } else { + std::string resultDir = TfGetPathName(resultRealPath); + if (TfStringStartsWith(referencedRealPath, resultDir)) { + resultingIdentifier = std::string(referencedRealPath).replace(0, + resultDir.length(), "./"); + } + } + + return resultingIdentifier.empty() ? + referencedIdentifier + : resultingIdentifier; + } + // During parallel generation, we will generate non-releative paths // for clipAssetPaths so we need to make a post-processing pass. // We want to respect paths which have already been normalized, @@ -181,9 +188,10 @@ namespace { // in from the current assetPaths in the root layer(note that this // is to be called after parallel stitching). This difference shows // us how many asset paths need to be normalized. - void _NormalizeClipAssetPaths(const SdfLayerHandle& resultLayer, - const SdfLayerRefPtrVector& clipLayers, - const SdfPath& clipPath) + void + _NormalizeClipAssetPaths(const SdfLayerHandle& resultLayer, + const SdfLayerRefPtrVector& clipLayers, + const SdfPath& clipPath) { const auto currentAssetPaths = _GetUnboxedValue<_SdfAssetArray>(resultLayer, clipPath, @@ -221,40 +229,16 @@ namespace { // rhs has a valid x, we'll take that. In this approach, we combine // lhs's x and rhs's x. This is useful when we have multiple root layers // created during parallel stitching. - void _MergeRootLayerMetadata(const SdfLayerRefPtr& lhs, - const SdfLayerRefPtr& rhs, - const SdfPath& clipPath) { + void + _MergeRootLayerMetadata(const SdfLayerRefPtr& lhs, + const SdfLayerRefPtr& rhs, + const SdfPath& clipPath) + { _AppendCollection<_SdfAssetArray>(lhs, rhs, clipPath, clipAssetPathsKey); _AppendCollection(lhs, rhs, clipPath, clipTimeKey); _AppendCollection(lhs, rhs, clipPath, clipActiveKey); } - // Try to determine if we should use a relative path for this - // clip asset path. If the clip's identifier is itself has no - // directory component, assume it's relative to the result layer. - // Otherwise, look at the real paths to see if the clip path - // can be made relative to the result layer. - std::string - _GetRelativePathIfPossible(const std::string& referencedIdentifier, - const std::string& referencedRealPath, - const std::string& resultRealPath) - { - std::string resultingIdentifier; - if (TfGetPathName(referencedIdentifier).empty()) { - resultingIdentifier = "./" + referencedIdentifier; - } else { - std::string resultDir = TfGetPathName(resultRealPath); - if (TfStringStartsWith(referencedRealPath, resultDir)) { - resultingIdentifier = std::string(referencedRealPath).replace(0, - resultDir.length(), "./"); - } - } - - return resultingIdentifier.empty() ? - referencedIdentifier - : resultingIdentifier; - } - // Add the clipPrimPath metadata at the specified \p stitchPath // within the \p resultLayer. The \p startTimeCode is used to determine void @@ -412,7 +396,7 @@ namespace { const std::string& topIdentifier) { if (not resultLayer->GetPrimAtPath(rootPath)) { - TF_CODING_ERROR("Invalid prim path referenced in model clip layer"); + TF_CODING_ERROR("Invalid prim path referenced in result layer"); return; } @@ -564,7 +548,7 @@ namespace { // grab the min at the front and max at the back double endTimeCode = (*currentClipTimes.rbegin())[0]; modelClipLayer->SetEndTimeCode(endTimeCode); - if (startTimeCode == std::numeric_limits::max()) { + if (startTimeCode == TIME_MAX) { startTimeCode = (*currentClipTimes.begin())[0]; } modelClipLayer->SetStartTimeCode(startTimeCode); @@ -592,6 +576,37 @@ namespace { delimiter+topologyFileBaseName); } + std::tuple + _CreateTopologyLayer(const SdfLayerHandle& resultLayer, + const bool reuseExistingTopology) + { + const auto topologyName + = _CreateTopologyName(resultLayer->GetIdentifier()); + + bool topologyWasGenerated = false; + + SdfLayerRefPtr topologyLayer = SdfLayer::FindOrOpen(topologyName); + + if (not _LayerIsWritable(topologyLayer)) { + return std::make_tuple(TfNullPtr, topologyWasGenerated); + } + + if (not reuseExistingTopology) { + topologyWasGenerated = true; + if (topologyLayer) { + topologyLayer->Clear(); + } else { + topologyLayer = SdfLayer::CreateNew(topologyName); + } + + } else if (not topologyLayer) { + topologyWasGenerated = true; + topologyLayer = SdfLayer::CreateNew(topologyName); + } + + return std::make_tuple(topologyLayer, topologyWasGenerated); + } + struct _StitchLayersResult { SdfPath clipPath; SdfLayerRefPtr topology; @@ -615,18 +630,37 @@ namespace { for (const auto& layer : clipLayers) { UsdUtilsStitchLayers(topology, layer, /*ignoreTimeSamples=*/ true); - _StitchClipMetadata(root, layer, clipPath, - _GetStartTimeCode(layer)); + if (clipPath != SdfPath::AbsoluteRootPath()) { + _StitchClipMetadata(root, layer, clipPath, + _GetStartTimeCode(layer)); + } } } void join(_StitchLayersResult& rhs) { UsdUtilsStitchLayers(topology, rhs.topology, /*ignoreTimeSamples=*/ true); - _MergeRootLayerMetadata(root, rhs.root, clipPath); + if (clipPath != SdfPath::AbsoluteRootPath()) { + _MergeRootLayerMetadata(root, rhs.root, clipPath); + } } }; + _StitchLayersResult + _AggregateDataFromClips(const SdfLayerRefPtr& topologyLayer, + const SdfLayerRefPtrVector& clipLayers, + const SdfPath& clipPath=SdfPath::AbsoluteRootPath()) + { + // Create a result which will store the result of the + // successive computations done by parallel_reduce + _StitchLayersResult result(clipPath); + tbb::blocked_range + clipRange(clipLayers.begin(), clipLayers.end()); + tbb::parallel_reduce(clipRange, result); + + return result; + } + // Stitches a manifest file, containing the clip meta data aggregated // from the input \p clipLayers. These include clipPrimPath, clipTimes, // clipManifestAssetPath clipActive and clipAssetPaths as well as an @@ -639,15 +673,8 @@ namespace { const SdfLayerRefPtrVector& clipLayers, const SdfPath& clipPath) { - // Create a result which will store the result of the - // successive computations done by parallel_reduce - _StitchLayersResult result(clipPath); - tbb::blocked_range - clipRange(clipLayers.begin(), clipLayers.end()); - tbb::parallel_reduce(clipRange, result); - - // Combine the temporary result into the real topology layer - // as well as the root layer, which needs special attention(see below). + auto result = _AggregateDataFromClips( + topologyLayer, clipLayers, clipPath); UsdUtilsStitchLayers(topologyLayer, result.topology, true); // if the rootLayer has no clip-metadata authored @@ -664,7 +691,6 @@ namespace { _RetimeClipActive(resultLayer, clipPath); _NormalizeClipAssetPaths(resultLayer, clipLayers, clipPath); - // set the topology reference and manifest path because we // use anonymous layers during parallel reduction _StitchClipManifest(resultLayer, topologyLayer, clipPath); @@ -683,6 +709,18 @@ namespace { } } + bool + _UsdUtilsStitchClipsTopologyImpl(const SdfLayerRefPtr& topologyLayer, + const SdfLayerRefPtrVector& clipLayers) + { + // Note that we don't specify a unique clipPath since we're only + // interested in aggregating topology. + auto result = _AggregateDataFromClips(topologyLayer, clipLayers); + UsdUtilsStitchLayers(topologyLayer, result.topology, true); + topologyLayer->Save(); + return true; + } + bool _UsdUtilsStitchClipsImpl(const SdfLayerHandle& resultLayer, const SdfLayerRefPtr& topologyLayer, @@ -693,8 +731,6 @@ namespace { _StitchLayers(resultLayer, topologyLayer, clipLayers, clipPath); _SetTimeCodeRange(resultLayer, clipPath, startTimeCode); - // save the updated resultLayer, - // and updated/newly created topology layer topologyLayer->Save(); resultLayer->Save(); @@ -703,7 +739,7 @@ namespace { bool _ClipLayersAreValid(const SdfLayerRefPtrVector& clipLayers, - const std::vector& clipLayerFiles, + const _ClipFileVector& clipLayerFiles, const SdfPath& clipPath) { bool somePrimContainsPath = false; @@ -729,84 +765,87 @@ namespace { return true; } - void _CleanUpGeneratedLayers(const std::string& topologyLayerName, - const std::string& resultLayerName, - const bool topologyWasGenerated) - { - // Clean up our generated files upon failure. - if (topologyWasGenerated) { - TfDeleteFile(topologyLayerName); - } - TfDeleteFile(resultLayerName); + bool + _OpenClipLayers(SdfLayerRefPtrVector* clipLayers, + const _ClipFileVector& clipLayerFiles, + const SdfPath& clipPath) + { + // Pre-allocate our destination vector for the clip layer handles + clipLayers->resize(clipLayerFiles.size()); + + // Open the clip layer files in parallel and place them into the vector + WorkParallelForN(clipLayerFiles.size(), + [&clipLayers, &clipLayerFiles](size_t begin, size_t end) + { + for (size_t i = begin; i != end; ++i) { + (*clipLayers)[i] = SdfLayer::FindOrOpen(clipLayerFiles[i]); + } + }); + + return _ClipLayersAreValid(*clipLayers, clipLayerFiles, clipPath); } } // public facing API // ---------------------------------------------------------------------------- -bool -UsdUtilsStitchClips(const SdfLayerHandle& resultLayer, - const std::vector& clipLayerFiles, - const SdfPath& clipPath, - const bool reuseExistingTopology, - const double startTimeCode) +bool +UsdUtilsStitchClipsTopology(const SdfLayerHandle& topologyLayer, + const _ClipFileVector& clipLayerFiles) { // XXX: This is necessary for any C++ API which may be called though // python. Since this will spawn workers(in WorkParallelForN) which // will need to acquire the GIL, we need to explicitly release it. TF_PY_ALLOW_THREADS_IN_SCOPE(); - const auto topologyName = _CreateTopologyName(resultLayer->GetIdentifier()); - bool topologyWasGenerated = false; - SdfLayerRefPtr topologyLayer = SdfLayer::FindOrOpen(topologyName); - - if (not TfIsWritable(resultLayer->GetIdentifier())) { - TF_RUNTIME_ERROR("Error: Result layer is unwritable %s", - resultLayer->GetIdentifier().c_str()); + if (not _LayerIsWritable(topologyLayer)) { return false; } - if (TfIsFile(topologyName) and not TfIsWritable(topologyName)) { - TF_RUNTIME_ERROR("Error: Topology layer is unwritable %s", - topologyName.c_str()); + SdfLayerRefPtrVector clipLayers; + const bool clipLayersAreValid = _OpenClipLayers(&clipLayers, + clipLayerFiles, SdfPath::AbsoluteRootPath()); + + if (not clipLayersAreValid) { return false; } - if (not reuseExistingTopology) { - topologyWasGenerated = true; + return _UsdUtilsStitchClipsTopologyImpl(topologyLayer, clipLayers); +} - if (topologyLayer) { - topologyLayer->Clear(); - } else { - topologyLayer = SdfLayer::CreateNew(topologyName); - } - } else if (not topologyLayer) { - topologyWasGenerated = true; - topologyLayer = SdfLayer::CreateNew(topologyName); +bool +UsdUtilsStitchClips(const SdfLayerHandle& resultLayer, + const _ClipFileVector& clipLayerFiles, + const SdfPath& clipPath, + const bool reuseExistingTopology, + const double startTimeCode) +{ + // XXX: See comment in UsdUtilsStitchClipsTopology above. + TF_PY_ALLOW_THREADS_IN_SCOPE(); + + if (not _LayerIsWritable(resultLayer)) { + return false; } - // Pre-allocate our destination vector for the clip layer handles + SdfLayerRefPtr topologyLayer; + bool topologyWasGenerated; + + std::tie(topologyLayer, topologyWasGenerated) = _CreateTopologyLayer( + resultLayer, reuseExistingTopology); + SdfLayerRefPtrVector clipLayers; - clipLayers.resize(clipLayerFiles.size()); - - // Open the clip layer files in parallel and place them into the vector - WorkParallelForN(clipLayerFiles.size(), - [&clipLayers, &clipLayerFiles](size_t begin, size_t end) { - for (size_t i = begin; i != end; ++i) { - clipLayers[i] - = SdfLayer::FindOrOpen(clipLayerFiles[i]); - } - }); - - // Ensure all layers were opened and some contain the clip path. - if (not _ClipLayersAreValid(clipLayers, clipLayerFiles, clipPath) - or not _UsdUtilsStitchClipsImpl(resultLayer, topologyLayer, clipLayers, - clipPath, startTimeCode)) { - _CleanUpGeneratedLayers(topologyName, resultLayer->GetIdentifier(), - topologyWasGenerated); + const bool clipLayersAreValid = _OpenClipLayers(&clipLayers, + clipLayerFiles, clipPath); + + if (not clipLayersAreValid) { + if (topologyWasGenerated) { + TfDeleteFile(topologyLayer->GetIdentifier()); + } + return false; - } + } - return true; + return _UsdUtilsStitchClipsImpl(resultLayer, topologyLayer, clipLayers, + clipPath, startTimeCode); } diff --git a/pxr/usd/lib/usdUtils/stitchClips.h b/pxr/usd/lib/usdUtils/stitchClips.h index 540d8860f3..4b009a2a21 100644 --- a/pxr/usd/lib/usdUtils/stitchClips.h +++ b/pxr/usd/lib/usdUtils/stitchClips.h @@ -102,4 +102,18 @@ UsdUtilsStitchClips(const SdfLayerHandle& resultLayer, const double startTimeCode = std::numeric_limits::max()); +/// A function which aggregates the topology of a set of \p clipLayerFiles +/// for use in USD's Value Clips system. This aggregated scene topology +/// will only include non-time-varying data, as it is for use in conjunction +/// with the value clip metadata in a manifest layer. +/// +/// \p topologyLayer The layer in which topology of the +/// \p clipLayerFiles will be aggregated and inserted. +/// +/// \p clipLayerFiles The files containing the time varying data. +/// +bool +UsdUtilsStitchClipsTopology(const SdfLayerHandle& topologyLayer, + const std::vector& clipLayerFiles); + #endif // _USDUTILS_STITCH_CLIPS_H_ diff --git a/pxr/usd/lib/usdUtils/wrapStitchClips.cpp b/pxr/usd/lib/usdUtils/wrapStitchClips.cpp index 7ffae04b03..90c394ce29 100644 --- a/pxr/usd/lib/usdUtils/wrapStitchClips.cpp +++ b/pxr/usd/lib/usdUtils/wrapStitchClips.cpp @@ -70,13 +70,25 @@ _ConvertStitchClips(const SdfLayerHandle& resultLayer, _ConvertStartFrame(pyStartFrame)); } +void _ConvertStitchClipsToplogy(const SdfLayerHandle& topologyLayer, + const std::vector& clipLayerFiles) +{ + UsdUtilsStitchClipsTopology(topologyLayer, clipLayerFiles); +} + void wrapStitchClips() { def("StitchClips", _ConvertStitchClips, (arg("resultLayer"), - arg("clipLayerFiles"), arg("clipPath"), + arg("clipLayerFiles"), + arg("clipPath"), arg("reuseExistingTopology")=boost::python::object(), arg("startFrame")=boost::python::object())); + + def("StitchClipsTopology", + _ConvertStitchClipsToplogy, + (arg("topologyLayer"), + arg("clipLayerFiles"))); } From f8ac9f5e835d6b153c3518d736e4fede4ee2737a Mon Sep 17 00:00:00 2001 From: pixar-oss Date: Mon, 19 Sep 2016 09:50:11 -0700 Subject: [PATCH 149/380] Return the current frame if no samples within or spanning the shutter range are found. (Internal change: 1655460) --- .../katana/lib/usdKatana/usdInPrivateData.cpp | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/third_party/katana/lib/usdKatana/usdInPrivateData.cpp b/third_party/katana/lib/usdKatana/usdInPrivateData.cpp index 62daf36d31..b6f05297a7 100644 --- a/third_party/katana/lib/usdKatana/usdInPrivateData.cpp +++ b/third_party/katana/lib/usdKatana/usdInPrivateData.cpp @@ -78,11 +78,12 @@ PxrUsdKatanaUsdInPrivateData::PxrUsdKatanaUsdInPrivateData( const std::vector PxrUsdKatanaUsdInPrivateData::GetMotionSampleTimes(const UsdAttribute& attr) const { + static std::vector noMotion = {0.0}; + double currentTime = _usdInArgs->GetCurrentTime(); if (attr and not PxrUsdKatanaUtils::IsAttributeVarying(attr, currentTime)) { - static std::vector noMotion = {0.0}; return noMotion; } @@ -149,6 +150,12 @@ PxrUsdKatanaUsdInPrivateData::GetMotionSampleTimes(const UsdAttribute& attr) con if (attr.GetBracketingTimeSamples( shutterStartTime, &lower, &upper, &hasTimeSamples)) { + if (lower > shutterStartTime) + { + // Did not find a sample ealier than the shutter start. Return no motion. + return noMotion; + } + // Insert the first sample as long as it is different // than what we already have. if (fabs(lower-firstSample) > epsilon) @@ -168,6 +175,12 @@ PxrUsdKatanaUsdInPrivateData::GetMotionSampleTimes(const UsdAttribute& attr) con if (attr.GetBracketingTimeSamples( shutterCloseTime, &lower, &upper, &hasTimeSamples)) { + if (upper < shutterCloseTime) + { + // Did not find a sample later than the shutter close. Return no motion. + return noMotion; + } + // Append the last sample as long as it is different // than what we already have. if (fabs(upper-lastSample) > epsilon) From 6a4f49de3f7c4f5a9747ef95ecaa623ebe8abd26 Mon Sep 17 00:00:00 2001 From: takahito-tejima Date: Mon, 19 Sep 2016 09:50:23 -0700 Subject: [PATCH 150/380] [Hd, Hdx] move drawTarget to Hdx - HdxDrawTarget inherits from HdSprim - move related drawTarget structs to Hdx - localize all drawTarget tokens and dirtybits - Add general state tracking in HdChangeTracker, to replace drawTargetSetVersion (key: HdxDrawTargetTokens->drawTargetSet) - fix default drawingRange of drawTargetRenderPass to (0.9, -1.0) - add a unit test for HdxDrawTarget and HdxDrawTargetTask. - HD_API 26 to 27 - HDX_API 4 to 5. (Internal change: 1655531) --- pxr/imaging/lib/hd/CMakeLists.txt | 5 - pxr/imaging/lib/hd/changeTracker.cpp | 96 +++----- pxr/imaging/lib/hd/changeTracker.h | 58 ++--- pxr/imaging/lib/hd/engine.cpp | 3 - pxr/imaging/lib/hd/renderIndex.cpp | 72 ------ pxr/imaging/lib/hd/renderIndex.h | 41 ---- pxr/imaging/lib/hd/tokens.h | 4 - pxr/imaging/lib/hd/version.h | 3 +- pxr/imaging/lib/hdx/CMakeLists.txt | 5 + pxr/imaging/lib/{hd => hdx}/drawTarget.cpp | 100 +++++--- pxr/imaging/lib/{hd => hdx}/drawTarget.h | 87 ++++--- .../{hd => hdx}/drawTargetAttachmentDesc.cpp | 32 ++- .../{hd => hdx}/drawTargetAttachmentDesc.h | 28 +-- .../drawTargetAttachmentDescArray.cpp | 42 ++-- .../drawTargetAttachmentDescArray.h | 34 +-- .../lib/{hd => hdx}/drawTargetRenderPass.cpp | 22 +- .../lib/{hd => hdx}/drawTargetRenderPass.h | 26 +-- .../{hd => hdx}/drawTargetRenderPassState.cpp | 16 +- .../{hd => hdx}/drawTargetRenderPassState.h | 18 +- pxr/imaging/lib/hdx/drawTargetTask.cpp | 28 +-- pxr/imaging/lib/hdx/drawTargetTask.h | 19 +- pxr/imaging/lib/hdx/unitTestDelegate.cpp | 218 +++++++++++++++++- pxr/imaging/lib/hdx/unitTestDelegate.h | 36 +++ pxr/imaging/lib/hdx/version.h | 5 +- 24 files changed, 566 insertions(+), 432 deletions(-) rename pxr/imaging/lib/{hd => hdx}/drawTarget.cpp (72%) rename pxr/imaging/lib/{hd => hdx}/drawTarget.h (55%) rename pxr/imaging/lib/{hd => hdx}/drawTargetAttachmentDesc.cpp (71%) rename pxr/imaging/lib/{hd => hdx}/drawTargetAttachmentDesc.h (71%) rename pxr/imaging/lib/{hd => hdx}/drawTargetAttachmentDescArray.cpp (63%) rename pxr/imaging/lib/{hd => hdx}/drawTargetAttachmentDescArray.h (63%) rename pxr/imaging/lib/{hd => hdx}/drawTargetRenderPass.cpp (88%) rename pxr/imaging/lib/{hd => hdx}/drawTargetRenderPass.h (77%) rename pxr/imaging/lib/{hd => hdx}/drawTargetRenderPassState.cpp (77%) rename pxr/imaging/lib/{hd => hdx}/drawTargetRenderPassState.h (88%) diff --git a/pxr/imaging/lib/hd/CMakeLists.txt b/pxr/imaging/lib/hd/CMakeLists.txt index 99e9467509..7726f82d06 100644 --- a/pxr/imaging/lib/hd/CMakeLists.txt +++ b/pxr/imaging/lib/hd/CMakeLists.txt @@ -51,11 +51,6 @@ pxr_shared_library(hd conversions copyComputation debugCodes - drawTarget - drawTargetAttachmentDesc - drawTargetAttachmentDescArray - drawTargetRenderPass - drawTargetRenderPassState dirtyList dispatchBuffer drawingCoord diff --git a/pxr/imaging/lib/hd/changeTracker.cpp b/pxr/imaging/lib/hd/changeTracker.cpp index 054ac51f1c..d02fb78294 100644 --- a/pxr/imaging/lib/hd/changeTracker.cpp +++ b/pxr/imaging/lib/hd/changeTracker.cpp @@ -41,7 +41,6 @@ HdChangeTracker::HdChangeTracker() , _changeCount(1) // changeCount in DirtyList starts from 0. , _visChangeCount(1) // Clients (commandBuffer) start from 0. , _shaderBindingsVersion(1) - , _drawTargetSetVersion(1) // Clients (draw target task) start from 0. { /*NOTHING*/ } @@ -433,64 +432,6 @@ HdChangeTracker::MarkSprimClean(SdfPath const& id, DirtyBits newBits) it->second = newBits; } -// -------------------------------------------------------------------------- // -/// \name Draw Target Object Tracking -// -------------------------------------------------------------------------- // - -void -HdChangeTracker::DrawTargetInserted(SdfPath const& id) -{ - _drawTargetState[id] = AllDirty; - ++_drawTargetSetVersion; -} - -void -HdChangeTracker::DrawTargetRemoved(SdfPath const& id) -{ - _drawTargetState.erase(id); - ++_drawTargetSetVersion; -} - -HdChangeTracker::DirtyBits -HdChangeTracker::GetDrawTargetDirtyBits(SdfPath const& id) -{ - _IDStateMap::iterator it = _drawTargetState.find(id); - if (not TF_VERIFY(it != _drawTargetState.end())) { - return Clean; - } - return it->second; -} - -void -HdChangeTracker::MarkDrawTargetDirty(SdfPath const& id, DirtyBits bits) -{ - _IDStateMap::iterator it = _drawTargetState.find(id); - if (not TF_VERIFY(it != _drawTargetState.end())) { - return; - } - it->second = it->second | bits; - - if (bits & DirtyDTEnable) { - ++_drawTargetSetVersion; - } -} - -unsigned -HdChangeTracker::GetDrawTargetSetVersion() -{ - return _drawTargetSetVersion; -} - -void -HdChangeTracker::MarkDrawTargetClean(SdfPath const& id, DirtyBits newBits) -{ - _IDStateMap::iterator it = _drawTargetState.find(id); - if (not TF_VERIFY(it != _drawTargetState.end())) - return; - // preserve the variability bit - it->second = (it->second & Varying) | newBits; -} - // -------------------------------------------------------------------------- // /// \name RPrim Object Tracking // -------------------------------------------------------------------------- // @@ -822,6 +763,43 @@ HdChangeTracker::GetShaderBindingsVersion() const return _shaderBindingsVersion; } +void +HdChangeTracker::AddState(TfToken const& name) +{ + _GeneralStateMap::iterator it = _generalState.find(name); + if (it != _generalState.end()) { + // mark state dirty + ++it->second; + } else { + _generalState[name] = 1; + } +} + +void +HdChangeTracker::MarkStateDirty(TfToken const& name) +{ + _GeneralStateMap::iterator it = _generalState.find(name); + if (it != _generalState.end()) { + ++it->second; + } else { + TF_CODING_ERROR("Change Tracker unable to find state %s", + name.GetText()); + } +} + +unsigned +HdChangeTracker::GetStateVersion(TfToken const &name) const +{ + _GeneralStateMap::const_iterator it = _generalState.find(name); + if (it != _generalState.end()) { + return it->second; + } else { + TF_CODING_ERROR("Change Tracker unable to find state %s", + name.GetText()); + return 0; + } +} + /*static*/ std::string HdChangeTracker::StringifyDirtyBits(int dirtyBits) diff --git a/pxr/imaging/lib/hd/changeTracker.h b/pxr/imaging/lib/hd/changeTracker.h index 871a5aa92d..2837066cf7 100644 --- a/pxr/imaging/lib/hd/changeTracker.h +++ b/pxr/imaging/lib/hd/changeTracker.h @@ -89,17 +89,6 @@ class HdChangeTracker : public boost::noncopyable { DirtyTexture = 1 << 5, }; - - /// Dirty bits for the HdDrawTarget object - enum DrawTargetDirtyBits { - DirtyDTEnable = 1 << 0, - DirtyDTCamera = 1 << 1, - DirtyDTResolution = 1 << 2, - DirtyDTAttachment = 1 << 3, - DirtyDTDepthClearValue = 1 << 4, - DirtyDTCollection = 1 << 5, - }; - typedef int DirtyBits; HdChangeTracker(); @@ -344,31 +333,6 @@ class HdChangeTracker : public boost::noncopyable { /// Clean the specified dirty bits for the instancer with \p id. void MarkInstancerClean(SdfPath const& id, DirtyBits newBits=Clean); - // ---------------------------------------------------------------------- // - /// @} - /// \name Draw Target Object Tracking - /// @{ - // ---------------------------------------------------------------------- // - - /// Start tracking Draw Target with the given \p id. - void DrawTargetInserted(SdfPath const& id); - - /// Stop tracking Draw Target with the given \p id. - void DrawTargetRemoved(SdfPath const& id); - - /// Get the dirty bits for Draw Target with the given \p id. - DirtyBits GetDrawTargetDirtyBits(SdfPath const& id); - - /// Set the dirty flags to \p bits. - void MarkDrawTargetDirty(SdfPath const& id, DirtyBits bits=AllDirty); - - /// Set the dirty flags to \p newBits. - void MarkDrawTargetClean(SdfPath const& id, DirtyBits newBits=Clean); - - /// Return an version number indicating if the set of - /// draw targets has changed. - unsigned GetDrawTargetSetVersion(); - // ---------------------------------------------------------------------- // /// @} /// \name Sprim (scene state prim: camera, light, ...) state Tracking @@ -452,6 +416,22 @@ class HdChangeTracker : public boost::noncopyable { /// Returns the current shader binding version. unsigned GetShaderBindingsVersion() const; + // ---------------------------------------------------------------------- // + /// @} + /// \name General state tracking + /// @{ + // ---------------------------------------------------------------------- // + + /// Adds a named state for tracking. + void AddState(TfToken const& name); + + /// Marks a named state as being dirty., this bumps the version of the + /// state. + void MarkStateDirty(TfToken const& name); + + /// Returns the current version of the named state. + unsigned GetStateVersion(TfToken const &name) const; + // ---------------------------------------------------------------------- // /// @} /// \name Debug @@ -473,6 +453,7 @@ class HdChangeTracker : public boost::noncopyable { typedef TfHashMap _IDStateMap; typedef TfHashMap _CollectionStateMap; typedef TfHashMap _InstancerRprimMap; + typedef TfHashMap _GeneralStateMap; // Core dirty state. _IDStateMap _rprimState; @@ -480,8 +461,8 @@ class HdChangeTracker : public boost::noncopyable { _IDStateMap _shaderState; _IDStateMap _taskState; _IDStateMap _textureState; - _IDStateMap _drawTargetState; _IDStateMap _sprimState; + _GeneralStateMap _generalState; // Collection versions / state. _CollectionStateMap _collectionState; @@ -508,9 +489,6 @@ class HdChangeTracker : public boost::noncopyable { // Used to validate shader bindings (to validate draw batches) std::atomic_uint _shaderBindingsVersion; - - // Used to detect changes in which set of draw targets are enabled. - unsigned _drawTargetSetVersion; }; #endif //HD_CHANGE_TRACKER_H diff --git a/pxr/imaging/lib/hd/engine.cpp b/pxr/imaging/lib/hd/engine.cpp index 399d8f24f0..f2ebf2b79d 100644 --- a/pxr/imaging/lib/hd/engine.cpp +++ b/pxr/imaging/lib/hd/engine.cpp @@ -137,9 +137,6 @@ HdEngine::Execute(HdRenderIndex& index, HdTaskSharedPtrVector const &tasks) // Sync the scene state prims index.SyncSprims(); - // Sync the draw targets - index.SyncDrawTargets(); - // --------------------------------------------------------------------- // // DATA DISCOVERY PHASE // --------------------------------------------------------------------- // diff --git a/pxr/imaging/lib/hd/renderIndex.cpp b/pxr/imaging/lib/hd/renderIndex.cpp index 417c079c6e..387043187a 100644 --- a/pxr/imaging/lib/hd/renderIndex.cpp +++ b/pxr/imaging/lib/hd/renderIndex.cpp @@ -26,7 +26,6 @@ #include "pxr/imaging/hd/basisCurves.h" #include "pxr/imaging/hd/dirtyList.h" #include "pxr/imaging/hd/drawItem.h" -#include "pxr/imaging/hd/drawTarget.h" #include "pxr/imaging/hd/enums.h" #include "pxr/imaging/hd/instancer.h" #include "pxr/imaging/hd/glslfxShader.h" @@ -420,49 +419,6 @@ HdRenderIndex::RemoveTexture(SdfPath const& id) _textureMap.erase(it); } -// -------------------------------------------------------------------------- // -/// \name Draw Target Support -// -------------------------------------------------------------------------- // - -void -HdRenderIndex::_TrackDelegateDrawTarget(HdSceneDelegate* delegate, - SdfPath const& drawTargetId, - HdDrawTargetSharedPtr const& drawTarget) -{ - - if (drawTargetId == SdfPath()) { - return; - } - _tracker.DrawTargetInserted(drawTargetId); - _drawTargetMap.insert(std::make_pair(drawTargetId, drawTarget)); -} - -void -HdRenderIndex::RemoveDrawTarget(SdfPath const& id) -{ - HD_TRACE_FUNCTION(); - HD_MALLOC_TAG_FUNCTION(); - - _DrawTargetMap::iterator it = _drawTargetMap.find(id); - if (it == _drawTargetMap.end()) { - return; - } - _tracker.DrawTargetRemoved(id); - _drawTargetMap.erase(it); -} - -HdDrawTargetSharedPtr const& -HdRenderIndex::GetDrawTarget(SdfPath const& id) const -{ - _DrawTargetMap::const_iterator it = _drawTargetMap.find(id); - if (it != _drawTargetMap.end()) { - return it->second; - } - - static HdDrawTargetSharedPtr EMPTY; - return EMPTY; -} - // -------------------------------------------------------------------------- // /// \name Sprim Support (scene state prim: light, camera...) // -------------------------------------------------------------------------- // @@ -682,21 +638,6 @@ HdRenderIndex::GetDrawItems(HdRprimCollection const& collection) return finalResult; } -HdRenderIndex::HdDrawTargetView -HdRenderIndex::GetDrawTargets() -{ - HD_TRACE_FUNCTION(); - - HdDrawTargetView result; - result.reserve(_drawTargetMap.size()); - - TF_FOR_ALL (it, _drawTargetMap) { - result.push_back(it->second); - } - - return result; -} - bool HdRenderIndex::IsInCollection(SdfPath const& id, TfToken const& collectionName) const @@ -1046,19 +987,6 @@ HdRenderIndex::SyncSprims() } } -void -HdRenderIndex::SyncDrawTargets() -{ - TF_FOR_ALL(it, _drawTargetMap) { - if (_tracker.GetDrawTargetDirtyBits(it->first) != HdChangeTracker::Clean) { - it->second->Sync(); - - _tracker.MarkDrawTargetClean(it->first); - } - - } -} - void HdRenderIndex::_CompactPrimIds() { diff --git a/pxr/imaging/lib/hd/renderIndex.h b/pxr/imaging/lib/hd/renderIndex.h index 7beff1d2c6..ce8cda583d 100644 --- a/pxr/imaging/lib/hd/renderIndex.h +++ b/pxr/imaging/lib/hd/renderIndex.h @@ -42,7 +42,6 @@ class HdDrawItem; class HdRprimCollection; class HdSceneDelegate; -typedef boost::shared_ptr HdDrawTargetSharedPtr; typedef boost::shared_ptr HdDirtyListSharedPtr; typedef boost::shared_ptr HdRprimSharedPtr; typedef boost::shared_ptr HdRprimConstSharedPtr; @@ -67,7 +66,6 @@ class HdRenderIndex : public boost::noncopyable { // XXX: These should return iterator ranges, not vectors; // they also shouldn't be pointers. typedef std::vector HdDrawItemView; - typedef std::vector HdDrawTargetView; HdRenderIndex(); ~HdRenderIndex(); @@ -86,18 +84,12 @@ class HdRenderIndex : public boost::noncopyable { HdDrawItemView GetDrawItems(HdRprimCollection const& collection); - /// Returns a list of all draw targets in the render index. - HdDrawTargetView GetDrawTargets(); - /// Synchronize all objects in the DirtyList void Sync(HdDirtyListSharedPtr const &dirtyList); /// Processes all pending dirty lists void SyncAll(); - /// Synchronize all draw targets in the render index - void SyncDrawTargets(); - /// Synchronize all scene states in the render index void SyncSprims(); @@ -246,21 +238,6 @@ class HdRenderIndex : public boost::noncopyable { /// Returns the subtree rooted under the given path. SdfPathVector GetSprimSubtree(SdfPath const& root) const; - // ---------------------------------------------------------------------- // - /// \name Draw Target Support - // ---------------------------------------------------------------------- // - - /// Inserts a new draw target into the RenderIndex with an identifier of - /// \p id. - template - void - InsertDrawTarget(HdSceneDelegate* delegate, SdfPath const& id); - - /// Removes the given draw target from the RenderIndex. - void RemoveDrawTarget(SdfPath const& id); - - HdDrawTargetSharedPtr const& GetDrawTarget(SdfPath const& id) const; - private: // ---------------------------------------------------------------------- // // Private Helper methods @@ -293,11 +270,6 @@ class HdRenderIndex : public boost::noncopyable { SdfPath const& textureId, HdTextureSharedPtr const& texture); - // Inserts the draw target into the index and updates tracking state. - void _TrackDelegateDrawTarget(HdSceneDelegate* delegate, - SdfPath const& drawTargetId, - HdDrawTargetSharedPtr const& drawTarget); - // Inserts the scene state prim into the index and updates tracking state. void _TrackDelegateSprim(HdSceneDelegate* delegate, SdfPath const& id, @@ -319,7 +291,6 @@ class HdRenderIndex : public boost::noncopyable { typedef TfHashMap _TextureMap; typedef TfHashMap _RprimMap; typedef TfHashMap _DelegateRprimMap; - typedef TfHashMap _DrawTargetMap; typedef TfHashMap _SprimMap; typedef std::set _RprimIDSet; @@ -335,7 +306,6 @@ class HdRenderIndex : public boost::noncopyable { _ShaderMap _shaderMap; _TaskMap _taskMap; _TextureMap _textureMap; - _DrawTargetMap _drawTargetMap; _SprimMap _sprimMap; _SprimIDSet _sprimIDSet; @@ -409,17 +379,6 @@ HdRenderIndex::InsertTexture(HdSceneDelegate* delegate, SdfPath const& id) _TrackDelegateTexture(delegate, id, texture); } -template -void -HdRenderIndex::InsertDrawTarget(HdSceneDelegate* delegate, SdfPath const& id) -{ - HD_TRACE_FUNCTION(); - HD_MALLOC_TAG_FUNCTION(); - - boost::shared_ptr drawTarget = boost::make_shared(delegate, id); - _TrackDelegateDrawTarget(delegate, id, drawTarget); -} - template void HdRenderIndex::InsertSprim(HdSceneDelegate* delegate, SdfPath const& id) diff --git a/pxr/imaging/lib/hd/tokens.h b/pxr/imaging/lib/hd/tokens.h index f94961c346..f76f85fe69 100644 --- a/pxr/imaging/lib/hd/tokens.h +++ b/pxr/imaging/lib/hd/tokens.h @@ -29,7 +29,6 @@ #define HD_TOKENS \ (adjacency) \ - (attachments) \ (bboxLocalMin) \ (bboxLocalMax) \ (bbox) \ @@ -45,7 +44,6 @@ (cubic) \ (culledInstanceIndices) \ (cullStyle) \ - (depthClearValue) \ (doubleSided) \ (dispatchBuffer) \ (drawDispatch) \ @@ -57,7 +55,6 @@ (drawingCoord0) \ (drawingCoord1) \ (drawingCoordI) \ - (enable) \ (extent) \ (faceColors) \ (geometry) \ @@ -97,7 +94,6 @@ (ulocResetPass) \ (ulocCullMatrix) \ (ulocDrawRangeNDC) \ - (resolution) \ (rightHanded) \ (segmented) \ (smoothHull) \ diff --git a/pxr/imaging/lib/hd/version.h b/pxr/imaging/lib/hd/version.h index 22fae5e182..314e44910f 100644 --- a/pxr/imaging/lib/hd/version.h +++ b/pxr/imaging/lib/hd/version.h @@ -33,7 +33,8 @@ // 23 -> 24: GetPathForInstanceIndex returns absolute instance index. // 24 -> 25: move simpleLightingShader to Hdx. // 25 -> 26: move camera and light to Hdx. -#define HD_API 26 +// 26 -> 27: move drawTarget to Hdx. +#define HD_API 27 // 1 -> 2: SimpleLighting -> FallbackLighting #define HD_SHADER_API 2 diff --git a/pxr/imaging/lib/hdx/CMakeLists.txt b/pxr/imaging/lib/hdx/CMakeLists.txt index de1ce8ebd4..c60c2ac2ff 100644 --- a/pxr/imaging/lib/hdx/CMakeLists.txt +++ b/pxr/imaging/lib/hdx/CMakeLists.txt @@ -21,6 +21,11 @@ pxr_shared_library(hdx PUBLIC_CLASSES camera debugCodes + drawTarget + drawTargetAttachmentDesc + drawTargetAttachmentDescArray + drawTargetRenderPass + drawTargetRenderPassState drawTargetTask intersector light diff --git a/pxr/imaging/lib/hd/drawTarget.cpp b/pxr/imaging/lib/hdx/drawTarget.cpp similarity index 72% rename from pxr/imaging/lib/hd/drawTarget.cpp rename to pxr/imaging/lib/hdx/drawTarget.cpp index fd87897382..c379c1b801 100644 --- a/pxr/imaging/lib/hd/drawTarget.cpp +++ b/pxr/imaging/lib/hdx/drawTarget.cpp @@ -21,10 +21,10 @@ // KIND, either express or implied. See the Apache License for the specific // language governing permissions and limitations under the Apache License. // -#include "pxr/imaging/hd/drawTarget.h" +#include "pxr/imaging/hdx/drawTarget.h" +#include "pxr/imaging/hdx/drawTargetAttachmentDescArray.h" #include "pxr/imaging/hd/conversions.h" -#include "pxr/imaging/hd/drawTargetAttachmentDescArray.h" #include "pxr/imaging/hd/perfLog.h" #include "pxr/imaging/hd/sceneDelegate.h" #include "pxr/imaging/hd/sprim.h" @@ -35,9 +35,10 @@ static const std::string DEPTH_ATTACHMENT_NAME = "depth"; -HdDrawTarget::HdDrawTarget(HdSceneDelegate *delegate, SdfPath const &id) - : _delegate(delegate) - , _id(id) +TF_DEFINE_PUBLIC_TOKENS(HdxDrawTargetTokens, HDX_DRAW_TARGET_TOKENS); + +HdxDrawTarget::HdxDrawTarget(HdSceneDelegate *delegate, SdfPath const &id) + : HdSprim(delegate, id) , _version(1) // Clients tacking start at 0. , _enabled(true) , _cameraId() @@ -50,74 +51,76 @@ HdDrawTarget::HdDrawTarget(HdSceneDelegate *delegate, SdfPath const &id) { } -HdDrawTarget::~HdDrawTarget() +HdxDrawTarget::~HdxDrawTarget() { } +/*virtual*/ void -HdDrawTarget::Sync() +HdxDrawTarget::Sync() { HD_TRACE_FUNCTION(); HD_MALLOC_TAG_FUNCTION(); - if (!TF_VERIFY(_delegate)) { - return; - } + SdfPath const &id = GetID(); + HdSceneDelegate *delegate = GetDelegate(); + if (!TF_VERIFY(delegate)) { + return; + } HdChangeTracker& changeTracker = - _delegate->GetRenderIndex().GetChangeTracker(); - HdChangeTracker::DirtyBits bits = changeTracker.GetDrawTargetDirtyBits(_id); + delegate->GetRenderIndex().GetChangeTracker(); + HdChangeTracker::DirtyBits bits = changeTracker.GetSprimDirtyBits(id); - if (bits & HdChangeTracker::DirtyDTEnable) { - VtValue vtValue = _delegate->Get(_id, HdTokens->enable); + if (bits & DirtyDTEnable) { + VtValue vtValue = delegate->Get(id, HdxDrawTargetTokens->enable); // Optional attribute. _enabled = vtValue.GetWithDefault(true); } - if (bits & HdChangeTracker::DirtyDTCamera) { - VtValue vtValue = _delegate->Get(_id, HdTokens->camera); + if (bits & DirtyDTCamera) { + VtValue vtValue = delegate->Get(id, HdxDrawTargetTokens->camera); _cameraId = vtValue.Get(); _renderPassState.SetCamera(_cameraId); } - if (bits & HdChangeTracker::DirtyDTResolution) { - VtValue vtValue = _delegate->Get(_id, HdTokens->resolution); + if (bits & DirtyDTResolution) { + VtValue vtValue = delegate->Get(id, HdxDrawTargetTokens->resolution); _resolution = vtValue.Get(); // No point in Resizing the textures if new ones are going to // be created (see _SetAttachments()) - if (_drawTarget && - HdChangeTracker::IsClean(bits & HdChangeTracker::DirtyDTAttachment)) { + if (_drawTarget && ((bits & DirtyDTAttachment) == Clean)) { _ResizeDrawTarget(); } } - if (bits & HdChangeTracker::DirtyDTAttachment) { + if (bits & DirtyDTAttachment) { // Depends on resolution being set correctly. - VtValue vtValue = _delegate->Get(_id, HdTokens->attachments); + VtValue vtValue = delegate->Get(id, HdxDrawTargetTokens->attachments); - const HdDrawTargetAttachmentDescArray &attachments = - vtValue.GetWithDefault( - HdDrawTargetAttachmentDescArray()); + const HdxDrawTargetAttachmentDescArray &attachments = + vtValue.GetWithDefault( + HdxDrawTargetAttachmentDescArray()); _SetAttachments(attachments); } - if (bits & HdChangeTracker::DirtyDTDepthClearValue) { - VtValue vtValue = _delegate->Get(_id, HdTokens->depthClearValue); + if (bits & DirtyDTDepthClearValue) { + VtValue vtValue = delegate->Get(id, HdxDrawTargetTokens->depthClearValue); float depthClearValue = vtValue.GetWithDefault(1.0f); _renderPassState.SetDepthClearValue(depthClearValue); } - if (bits & HdChangeTracker::DirtyDTCollection) { - VtValue vtValue = _delegate->Get(_id, HdTokens->collection); + if (bits & DirtyDTCollection) { + VtValue vtValue = delegate->Get(id, HdxDrawTargetTokens->collection); const HdRprimCollectionVector &collections = vtValue.GetWithDefault( @@ -148,9 +151,18 @@ HdDrawTarget::Sync() } } +/*virtual*/ +VtValue +HdxDrawTarget::Get(TfToken const &token) const +{ + // nothing here, since right now all draw target tasks accessing + // HdxDrawTarget perform downcast from Sprim To HdxDrawTarget + // and use the C++ interface (e.g. IsEnabled(), GetRenderPassState()). + return VtValue(); +} bool -HdDrawTarget::WriteToFile(const std::string &attachment, +HdxDrawTarget::WriteToFile(const std::string &attachment, const std::string &path) { // Check the draw targets been allocated @@ -197,7 +209,7 @@ HdDrawTarget::WriteToFile(const std::string &attachment, void -HdDrawTarget::_SetAttachments(const HdDrawTargetAttachmentDescArray &attachments) +HdxDrawTarget::_SetAttachments(const HdxDrawTargetAttachmentDescArray &attachments) { if (!_drawTargetContext) { // Use one of the shared contexts as the master. @@ -222,7 +234,7 @@ HdDrawTarget::_SetAttachments(const HdDrawTargetAttachmentDescArray &attachments for (size_t attachmentNum = 0; attachmentNum < numAttachments; ++attachmentNum) { - const HdDrawTargetAttachmentDesc &desc = + const HdxDrawTargetAttachmentDesc &desc = attachments.GetAttachment(attachmentNum); GLenum format = GL_RGBA; @@ -258,13 +270,13 @@ HdDrawTarget::_SetAttachments(const HdDrawTargetAttachmentDescArray &attachments HdSprimSharedPtr -HdDrawTarget::_GetCamera() const +HdxDrawTarget::_GetCamera() const { - return _delegate->GetRenderIndex().GetSprim(_cameraId); + return GetDelegate()->GetRenderIndex().GetSprim(_cameraId); } void -HdDrawTarget::_ResizeDrawTarget() +HdxDrawTarget::_ResizeDrawTarget() { // Make sure all draw target operations happen on the same // context. @@ -281,3 +293,21 @@ HdDrawTarget::_ResizeDrawTarget() GlfGLContext::MakeCurrent(oldContext); } + +/*static*/ +void +HdxDrawTarget::GetDrawTargets(HdSceneDelegate *delegate, + HdxDrawTargetSharedPtrVector *drawTargets) +{ + SdfPathVector sprimPaths = delegate->GetRenderIndex().GetSprimSubtree( + SdfPath::AbsoluteRootPath()); + TF_FOR_ALL (it, sprimPaths) { + // XXX: same downcast problem as in simpleLight and shadow. + HdSprimSharedPtr const &sprim + = delegate->GetRenderIndex().GetSprim(*it); + if (HdxDrawTargetSharedPtr drawTarget + = boost::dynamic_pointer_cast(sprim)) { + drawTargets->push_back(drawTarget); + } + } +} diff --git a/pxr/imaging/lib/hd/drawTarget.h b/pxr/imaging/lib/hdx/drawTarget.h similarity index 55% rename from pxr/imaging/lib/hd/drawTarget.h rename to pxr/imaging/lib/hdx/drawTarget.h index abe9467e4f..17ab65511d 100644 --- a/pxr/imaging/lib/hd/drawTarget.h +++ b/pxr/imaging/lib/hdx/drawTarget.h @@ -21,49 +21,70 @@ // KIND, either express or implied. See the Apache License for the specific // language governing permissions and limitations under the Apache License. // -#ifndef HD_DRAW_TARGET_H -#define HD_DRAW_TARGET_H +#ifndef HDX_DRAW_TARGET_H +#define HDX_DRAW_TARGET_H #include "pxr/imaging/hd/enums.h" #include "pxr/imaging/hd/rprimCollection.h" -#include "pxr/imaging/hd/drawTargetRenderPassState.h" - +#include "pxr/imaging/hd/sprim.h" +#include "pxr/imaging/hdx/drawTargetRenderPassState.h" #include "pxr/imaging/glf/drawTarget.h" #include "pxr/usd/sdf/path.h" +#include "pxr/base/tf/staticTokens.h" #include #include +#define HDX_DRAW_TARGET_TOKENS \ + (attachments) \ + (camera) \ + (collection) \ + (depthClearValue) \ + (drawTargetSet) \ + (enable) \ + (resolution) + +TF_DECLARE_PUBLIC_TOKENS(HdxDrawTargetTokens, HDX_DRAW_TARGET_TOKENS); + class HdSceneDelegate; -class HdDrawTargetAttachmentDescArray; +class HdxDrawTargetAttachmentDescArray; -typedef boost::shared_ptr HdDrawTargetSharedPtr; +typedef boost::shared_ptr HdxDrawTargetSharedPtr; typedef boost::shared_ptr HdSprimSharedPtr; typedef boost::shared_ptr GlfGLContextSharedPtr; -typedef std::vector HdDrawTargetSharedPtrVector; +typedef std::vector HdxDrawTargetSharedPtrVector; -/// \class HdDrawTarget +/// \class HdxDrawTarget /// /// Represents an render to texture render pass. /// /// \note This is a temporary API to aid transition to hydra, and is subject /// to major changes. /// -class HdDrawTarget final { +class HdxDrawTarget : public HdSprim { public: - HdDrawTarget(HdSceneDelegate* delegate, SdfPath const & id); - ~HdDrawTarget(); // note: not virtual as final class - - /// Returns the HdSceneDelegate which backs this draw target. - HdSceneDelegate* GetDelegate() const { return _delegate; } - - /// Returns the identifer by which this draw target is known. This - /// identifier is a common associative key used by the SceneDelegate, - /// RenderIndex, and for binding to the draw target - SdfPath const& GetID() const { return _id; } + HdxDrawTarget(HdSceneDelegate* delegate, SdfPath const & id); + virtual ~HdxDrawTarget(); + + /// Dirty bits for the HdxDrawTarget object + enum DirtyBits { + Clean = 0, + DirtyDTEnable = 1 << 0, + DirtyDTCamera = 1 << 1, + DirtyDTResolution = 1 << 2, + DirtyDTAttachment = 1 << 3, + DirtyDTDepthClearValue = 1 << 4, + DirtyDTCollection = 1 << 5, + AllDirty = (DirtyDTEnable + |DirtyDTCamera + |DirtyDTResolution + |DirtyDTAttachment + |DirtyDTDepthClearValue + |DirtyDTCollection) + }; /// Returns the version of the under-lying GlfDrawTarget. /// The version changes if the draw target attachments texture ids @@ -73,24 +94,28 @@ class HdDrawTarget final { /// texture resources change unsigned int GetVersion() const { return _version; } - /// Synchronizes state from the delegate to Hydra, for example, allocating - /// parameters into GPU memory. - void Sync(); + /// Synchronizes state from the delegate to this object. + virtual void Sync(); + + /// Accessor for tasks to get the parameters cached in this object. + virtual VtValue Get(TfToken const &token) const; // ---------------------------------------------------------------------- // /// \name Draw Target API // ---------------------------------------------------------------------- // bool IsEnabled() const { return _enabled; } const GlfDrawTargetRefPtr &GetGlfDrawTarget() const { return _drawTarget; } - HdDrawTargetRenderPassState *GetRenderPassState() { return &_renderPassState; } + HdxDrawTargetRenderPassState *GetRenderPassState() { return &_renderPassState; } /// Debug api to output the contents of the draw target to a png file. bool WriteToFile(const std::string &attachment, const std::string &path); + /// returns all HdxDrawTargets in the render index + static void GetDrawTargets(HdSceneDelegate *delegate, + HdxDrawTargetSharedPtrVector *drawTargets); + private: - HdSceneDelegate* _delegate; - SdfPath _id; unsigned int _version; bool _enabled; @@ -98,13 +123,13 @@ class HdDrawTarget final { GfVec2i _resolution; HdRprimCollectionVector _collections; - HdDrawTargetRenderPassState _renderPassState; + HdxDrawTargetRenderPassState _renderPassState; /// The context which owns the draw target object. GlfGLContextSharedPtr _drawTargetContext; GlfDrawTargetRefPtr _drawTarget; - void _SetAttachments(const HdDrawTargetAttachmentDescArray &attachments); + void _SetAttachments(const HdxDrawTargetAttachmentDescArray &attachments); void _SetCamera(const SdfPath &cameraPath); HdSprimSharedPtr _GetCamera() const; @@ -112,9 +137,9 @@ class HdDrawTarget final { void _ResizeDrawTarget(); // No copy - HdDrawTarget() = delete; - HdDrawTarget(const HdDrawTarget &) = delete; - HdDrawTarget &operator =(const HdDrawTarget &) = delete; + HdxDrawTarget() = delete; + HdxDrawTarget(const HdxDrawTarget &) = delete; + HdxDrawTarget &operator =(const HdxDrawTarget &) = delete; }; -#endif // HD_DRAW_TARGET_H +#endif // HDX_DRAW_TARGET_H diff --git a/pxr/imaging/lib/hd/drawTargetAttachmentDesc.cpp b/pxr/imaging/lib/hdx/drawTargetAttachmentDesc.cpp similarity index 71% rename from pxr/imaging/lib/hd/drawTargetAttachmentDesc.cpp rename to pxr/imaging/lib/hdx/drawTargetAttachmentDesc.cpp index 770ebfc4c8..9d3ffa829f 100644 --- a/pxr/imaging/lib/hd/drawTargetAttachmentDesc.cpp +++ b/pxr/imaging/lib/hdx/drawTargetAttachmentDesc.cpp @@ -21,11 +21,9 @@ // KIND, either express or implied. See the Apache License for the specific // language governing permissions and limitations under the Apache License. // -#include "pxr/imaging/hd/drawTargetAttachmentDesc.h" +#include "pxr/imaging/hdx/drawTargetAttachmentDesc.h" - - -HdDrawTargetAttachmentDesc::HdDrawTargetAttachmentDesc() +HdxDrawTargetAttachmentDesc::HdxDrawTargetAttachmentDesc() : _name() , _format(HdFormatUnknown) , _clearColor() @@ -34,7 +32,7 @@ HdDrawTargetAttachmentDesc::HdDrawTargetAttachmentDesc() } -HdDrawTargetAttachmentDesc::HdDrawTargetAttachmentDesc(const std::string &name, +HdxDrawTargetAttachmentDesc::HdxDrawTargetAttachmentDesc(const std::string &name, HdFormat format, const VtValue &clearColor) : _name(name) @@ -45,8 +43,8 @@ HdDrawTargetAttachmentDesc::HdDrawTargetAttachmentDesc(const std::string &name, } -HdDrawTargetAttachmentDesc::HdDrawTargetAttachmentDesc( - const HdDrawTargetAttachmentDesc ©) +HdxDrawTargetAttachmentDesc::HdxDrawTargetAttachmentDesc( + const HdxDrawTargetAttachmentDesc ©) : _name(copy._name) , _format(copy._format) , _clearColor(copy._clearColor) @@ -55,8 +53,8 @@ HdDrawTargetAttachmentDesc::HdDrawTargetAttachmentDesc( } -HdDrawTargetAttachmentDesc & -HdDrawTargetAttachmentDesc::operator =(const HdDrawTargetAttachmentDesc ©) +HdxDrawTargetAttachmentDesc & +HdxDrawTargetAttachmentDesc::operator =(const HdxDrawTargetAttachmentDesc ©) { _name = copy._name; _format = copy._format; @@ -67,7 +65,7 @@ HdDrawTargetAttachmentDesc::operator =(const HdDrawTargetAttachmentDesc ©) size_t -HdDrawTargetAttachmentDesc::GetHash() const +HdxDrawTargetAttachmentDesc::GetHash() const { size_t hash = boost::hash_value(_name); boost::hash_combine(hash, _format); @@ -78,7 +76,7 @@ HdDrawTargetAttachmentDesc::GetHash() const void -HdDrawTargetAttachmentDesc::Dump(std::ostream &out) const +HdxDrawTargetAttachmentDesc::Dump(std::ostream &out) const { out << _name << " " << _format << " " @@ -87,8 +85,8 @@ HdDrawTargetAttachmentDesc::Dump(std::ostream &out) const bool -HdDrawTargetAttachmentDesc::operator==( - const HdDrawTargetAttachmentDesc &other) const +HdxDrawTargetAttachmentDesc::operator==( + const HdxDrawTargetAttachmentDesc &other) const { return ((_name == other._name) && (_format == other._format) && @@ -97,8 +95,8 @@ HdDrawTargetAttachmentDesc::operator==( bool -HdDrawTargetAttachmentDesc::operator!=( - const HdDrawTargetAttachmentDesc &other) const +HdxDrawTargetAttachmentDesc::operator!=( + const HdxDrawTargetAttachmentDesc &other) const { return ((_name != other._name) || (_format != other._format) || @@ -106,13 +104,13 @@ HdDrawTargetAttachmentDesc::operator!=( } -size_t hash_value(HdDrawTargetAttachmentDesc const &attachment) +size_t hash_value(HdxDrawTargetAttachmentDesc const &attachment) { return attachment.GetHash(); } std::ostream &operator <<(std::ostream &out, - const HdDrawTargetAttachmentDesc &pv) + const HdxDrawTargetAttachmentDesc &pv) { pv.Dump(out); diff --git a/pxr/imaging/lib/hd/drawTargetAttachmentDesc.h b/pxr/imaging/lib/hdx/drawTargetAttachmentDesc.h similarity index 71% rename from pxr/imaging/lib/hd/drawTargetAttachmentDesc.h rename to pxr/imaging/lib/hdx/drawTargetAttachmentDesc.h index 0b2a888626..c735a5a3bd 100644 --- a/pxr/imaging/lib/hd/drawTargetAttachmentDesc.h +++ b/pxr/imaging/lib/hdx/drawTargetAttachmentDesc.h @@ -21,8 +21,8 @@ // KIND, either express or implied. See the Apache License for the specific // language governing permissions and limitations under the Apache License. // -#ifndef HD_DRAW_TARGET_ATTACHMENT_DESC_H -#define HD_DRAW_TARGET_ATTACHMENT_DESC_H +#ifndef HDX_DRAW_TARGET_ATTACHMENT_DESC_H +#define HDX_DRAW_TARGET_ATTACHMENT_DESC_H #include "pxr/imaging/hd/version.h" #include "pxr/imaging/hd/enums.h" @@ -31,28 +31,28 @@ #include -/// \class HdDrawTargetAttachmentDesc +/// \class HdxDrawTargetAttachmentDesc /// /// Represents an render to texture render pass. /// /// \note This is a temporary API to aid transition to hydra, and is subject /// to major changes. /// -class HdDrawTargetAttachmentDesc final +class HdxDrawTargetAttachmentDesc final { public: /// default constructor - only for use by containers. - HdDrawTargetAttachmentDesc(); + HdxDrawTargetAttachmentDesc(); /// Construct a draw target attachment description - HdDrawTargetAttachmentDesc(const std::string &name, + HdxDrawTargetAttachmentDesc(const std::string &name, HdFormat format, const VtValue &clearColor); - ~HdDrawTargetAttachmentDesc() = default; + ~HdxDrawTargetAttachmentDesc() = default; // Copy for container support. - HdDrawTargetAttachmentDesc(const HdDrawTargetAttachmentDesc ©); - HdDrawTargetAttachmentDesc &operator =(const HdDrawTargetAttachmentDesc ©); + HdxDrawTargetAttachmentDesc(const HdxDrawTargetAttachmentDesc ©); + HdxDrawTargetAttachmentDesc &operator =(const HdxDrawTargetAttachmentDesc ©); const std::string &GetName() const { return _name; } HdFormat GetFormat() const { return _format; } @@ -61,8 +61,8 @@ class HdDrawTargetAttachmentDesc final // VtValue requirements size_t GetHash() const; void Dump(std::ostream &out) const; - bool operator==(const HdDrawTargetAttachmentDesc &other) const; - bool operator!=(const HdDrawTargetAttachmentDesc &other) const; + bool operator==(const HdxDrawTargetAttachmentDesc &other) const; + bool operator!=(const HdxDrawTargetAttachmentDesc &other) const; private: std::string _name; @@ -70,7 +70,7 @@ class HdDrawTargetAttachmentDesc final VtValue _clearColor; }; -size_t hash_value(HdDrawTargetAttachmentDesc const &attachment); -std::ostream &operator <<(std::ostream &out, const HdDrawTargetAttachmentDesc &pv); +size_t hash_value(HdxDrawTargetAttachmentDesc const &attachment); +std::ostream &operator <<(std::ostream &out, const HdxDrawTargetAttachmentDesc &pv); -#endif // HD_DRAW_TARGET_ATTACHMENT_DESC_H +#endif // HDX_DRAW_TARGET_ATTACHMENT_DESC_H diff --git a/pxr/imaging/lib/hd/drawTargetAttachmentDescArray.cpp b/pxr/imaging/lib/hdx/drawTargetAttachmentDescArray.cpp similarity index 63% rename from pxr/imaging/lib/hd/drawTargetAttachmentDescArray.cpp rename to pxr/imaging/lib/hdx/drawTargetAttachmentDescArray.cpp index 2dbac2cbe3..6f4cc5a749 100644 --- a/pxr/imaging/lib/hd/drawTargetAttachmentDescArray.cpp +++ b/pxr/imaging/lib/hdx/drawTargetAttachmentDescArray.cpp @@ -21,15 +21,15 @@ // KIND, either express or implied. See the Apache License for the specific // language governing permissions and limitations under the Apache License. // -#include "pxr/imaging/hd/drawTargetAttachmentDescArray.h" +#include "pxr/imaging/hdx/drawTargetAttachmentDescArray.h" -HdDrawTargetAttachmentDescArray::HdDrawTargetAttachmentDescArray() +HdxDrawTargetAttachmentDescArray::HdxDrawTargetAttachmentDescArray() : _attachments() { } -HdDrawTargetAttachmentDescArray::HdDrawTargetAttachmentDescArray( +HdxDrawTargetAttachmentDescArray::HdxDrawTargetAttachmentDescArray( size_t attachmentCount) : _attachments() { @@ -37,17 +37,17 @@ HdDrawTargetAttachmentDescArray::HdDrawTargetAttachmentDescArray( } -HdDrawTargetAttachmentDescArray::HdDrawTargetAttachmentDescArray( - const HdDrawTargetAttachmentDescArray ©) +HdxDrawTargetAttachmentDescArray::HdxDrawTargetAttachmentDescArray( + const HdxDrawTargetAttachmentDescArray ©) : _attachments(copy._attachments) { } -HdDrawTargetAttachmentDescArray & -HdDrawTargetAttachmentDescArray::operator =( - const HdDrawTargetAttachmentDescArray ©) +HdxDrawTargetAttachmentDescArray & +HdxDrawTargetAttachmentDescArray::operator =( + const HdxDrawTargetAttachmentDescArray ©) { _attachments = copy._attachments; @@ -56,7 +56,7 @@ HdDrawTargetAttachmentDescArray::operator =( void -HdDrawTargetAttachmentDescArray::AddAttachment(const std::string &name, +HdxDrawTargetAttachmentDescArray::AddAttachment(const std::string &name, HdFormat format, const VtValue &clearColor) { @@ -65,21 +65,21 @@ HdDrawTargetAttachmentDescArray::AddAttachment(const std::string &name, size_t -HdDrawTargetAttachmentDescArray::GetNumAttachments() const +HdxDrawTargetAttachmentDescArray::GetNumAttachments() const { return _attachments.size(); } -const HdDrawTargetAttachmentDesc & -HdDrawTargetAttachmentDescArray::GetAttachment(size_t idx) const +const HdxDrawTargetAttachmentDesc & +HdxDrawTargetAttachmentDescArray::GetAttachment(size_t idx) const { return _attachments[idx]; } size_t -HdDrawTargetAttachmentDescArray::GetHash() const +HdxDrawTargetAttachmentDescArray::GetHash() const { size_t hash = boost::hash_value(_attachments); @@ -88,7 +88,7 @@ HdDrawTargetAttachmentDescArray::GetHash() const void -HdDrawTargetAttachmentDescArray::Dump(std::ostream &out) const +HdxDrawTargetAttachmentDescArray::Dump(std::ostream &out) const { size_t numAttachments = _attachments.size(); @@ -97,35 +97,35 @@ HdDrawTargetAttachmentDescArray::Dump(std::ostream &out) const for (size_t attachmentNum = 0; attachmentNum < numAttachments; ++attachmentNum) { - const HdDrawTargetAttachmentDesc &desc = _attachments[attachmentNum]; + const HdxDrawTargetAttachmentDesc &desc = _attachments[attachmentNum]; out << desc; } } bool -HdDrawTargetAttachmentDescArray::operator==( - const HdDrawTargetAttachmentDescArray &other) const +HdxDrawTargetAttachmentDescArray::operator==( + const HdxDrawTargetAttachmentDescArray &other) const { return (_attachments == other._attachments); } bool -HdDrawTargetAttachmentDescArray::operator!=( - const HdDrawTargetAttachmentDescArray &other) const +HdxDrawTargetAttachmentDescArray::operator!=( + const HdxDrawTargetAttachmentDescArray &other) const { return (_attachments != other._attachments); } -size_t hash_value(HdDrawTargetAttachmentDescArray const &attachments) +size_t hash_value(HdxDrawTargetAttachmentDescArray const &attachments) { return attachments.GetHash(); } std::ostream &operator <<(std::ostream &out, - const HdDrawTargetAttachmentDescArray &pv) + const HdxDrawTargetAttachmentDescArray &pv) { pv.Dump(out); diff --git a/pxr/imaging/lib/hd/drawTargetAttachmentDescArray.h b/pxr/imaging/lib/hdx/drawTargetAttachmentDescArray.h similarity index 63% rename from pxr/imaging/lib/hd/drawTargetAttachmentDescArray.h rename to pxr/imaging/lib/hdx/drawTargetAttachmentDescArray.h index d3d8512be9..4cbca76e2e 100644 --- a/pxr/imaging/lib/hd/drawTargetAttachmentDescArray.h +++ b/pxr/imaging/lib/hdx/drawTargetAttachmentDescArray.h @@ -21,14 +21,14 @@ // KIND, either express or implied. See the Apache License for the specific // language governing permissions and limitations under the Apache License. // -#ifndef HD_DRAW_TARGET_ATTACHMENT_DESC_ARRAY_H -#define HD_DRAW_TARGET_ATTACHMENT_DESC_ARRAY_H +#ifndef HDX_DRAW_TARGET_ATTACHMENT_DESC_ARRAY_H +#define HDX_DRAW_TARGET_ATTACHMENT_DESC_ARRAY_H -#include "pxr/imaging/hd/drawTargetAttachmentDesc.h" +#include "pxr/imaging/hdx/drawTargetAttachmentDesc.h" #include -/// \class HdDrawTargetAttachmentDescArray +/// \class HdxDrawTargetAttachmentDescArray /// /// Describes all the color buffer attachments for a draw target. /// The array should not contain a depth buffer - that is managed @@ -39,17 +39,17 @@ /// /// class is derivable for TfAny support. /// -class HdDrawTargetAttachmentDescArray +class HdxDrawTargetAttachmentDescArray { public: /// Default constructor for container purposes. - HdDrawTargetAttachmentDescArray(); + HdxDrawTargetAttachmentDescArray(); - HdDrawTargetAttachmentDescArray(size_t attachmentCount); - virtual ~HdDrawTargetAttachmentDescArray() = default; + HdxDrawTargetAttachmentDescArray(size_t attachmentCount); + virtual ~HdxDrawTargetAttachmentDescArray() = default; - HdDrawTargetAttachmentDescArray(const HdDrawTargetAttachmentDescArray ©); - HdDrawTargetAttachmentDescArray &operator =(const HdDrawTargetAttachmentDescArray ©); + HdxDrawTargetAttachmentDescArray(const HdxDrawTargetAttachmentDescArray ©); + HdxDrawTargetAttachmentDescArray &operator =(const HdxDrawTargetAttachmentDescArray ©); /// Pushes a new attachment onto the end of the list of attachments. void AddAttachment(const std::string &name, @@ -57,22 +57,22 @@ class HdDrawTargetAttachmentDescArray const VtValue &clearColor); size_t GetNumAttachments() const; - const HdDrawTargetAttachmentDesc &GetAttachment(size_t idx) const; + const HdxDrawTargetAttachmentDesc &GetAttachment(size_t idx) const; // VtValue requirements size_t GetHash() const; void Dump(std::ostream &out) const; - bool operator==(const HdDrawTargetAttachmentDescArray &other) const; - bool operator!=(const HdDrawTargetAttachmentDescArray &other) const; + bool operator==(const HdxDrawTargetAttachmentDescArray &other) const; + bool operator!=(const HdxDrawTargetAttachmentDescArray &other) const; private: - typedef std::vector _AttachmentDescArray; + typedef std::vector _AttachmentDescArray; _AttachmentDescArray _attachments; }; -size_t hash_value(const HdDrawTargetAttachmentDescArray &attachments); -std::ostream &operator <<(std::ostream &out, const HdDrawTargetAttachmentDescArray &pv); +size_t hash_value(const HdxDrawTargetAttachmentDescArray &attachments); +std::ostream &operator <<(std::ostream &out, const HdxDrawTargetAttachmentDescArray &pv); -#endif // HD_DRAW_TARGET_ATTACHMENT_DESC_ARRAY_H +#endif // HDX_DRAW_TARGET_ATTACHMENT_DESC_ARRAY_H diff --git a/pxr/imaging/lib/hd/drawTargetRenderPass.cpp b/pxr/imaging/lib/hdx/drawTargetRenderPass.cpp similarity index 88% rename from pxr/imaging/lib/hd/drawTargetRenderPass.cpp rename to pxr/imaging/lib/hdx/drawTargetRenderPass.cpp index 208b4f5809..e7737e2a79 100644 --- a/pxr/imaging/lib/hd/drawTargetRenderPass.cpp +++ b/pxr/imaging/lib/hdx/drawTargetRenderPass.cpp @@ -24,8 +24,8 @@ #include "pxr/imaging/glf/glew.h" #include "pxr/imaging/glf/glContext.h" -#include "pxr/imaging/hd/drawTargetRenderPass.h" -#include "pxr/imaging/hd/drawTargetRenderPassState.h" +#include "pxr/imaging/hdx/drawTargetRenderPass.h" +#include "pxr/imaging/hdx/drawTargetRenderPassState.h" #include "pxr/imaging/hd/renderPassState.h" static @@ -55,7 +55,7 @@ _ClearBuffer(GLenum buffer, GLint drawBuffer, const VtValue &value) } } -HdDrawTargetRenderPass::HdDrawTargetRenderPass(HdRenderIndex *index) +HdxDrawTargetRenderPass::HdxDrawTargetRenderPass(HdRenderIndex *index) : _renderPass(index) , _drawTargetRenderPassState(nullptr) , _drawTarget() @@ -65,12 +65,12 @@ HdDrawTargetRenderPass::HdDrawTargetRenderPass(HdRenderIndex *index) } -HdDrawTargetRenderPass::~HdDrawTargetRenderPass() +HdxDrawTargetRenderPass::~HdxDrawTargetRenderPass() { } void -HdDrawTargetRenderPass::SetDrawTarget(const GlfDrawTargetRefPtr &drawTarget) +HdxDrawTargetRenderPass::SetDrawTarget(const GlfDrawTargetRefPtr &drawTarget) { // XXX: The Draw Target may have been created on a different GL // context, so create a local copy here to use on this context. @@ -80,20 +80,20 @@ HdDrawTargetRenderPass::SetDrawTarget(const GlfDrawTargetRefPtr &drawTarget) } void -HdDrawTargetRenderPass::SetRenderPassState( - HdDrawTargetRenderPassState *drawTargetRenderPassState) +HdxDrawTargetRenderPass::SetRenderPassState( + HdxDrawTargetRenderPassState *drawTargetRenderPassState) { _drawTargetRenderPassState = drawTargetRenderPassState; } void -HdDrawTargetRenderPass::SetRprimCollection(HdRprimCollection const& col) +HdxDrawTargetRenderPass::SetRprimCollection(HdRprimCollection const& col) { _renderPass.SetRprimCollection(col); } void -HdDrawTargetRenderPass::Sync() +HdxDrawTargetRenderPass::Sync() { // Update the collection object if necessary. unsigned int newCollectionVersion = @@ -114,7 +114,7 @@ HdDrawTargetRenderPass::Sync() } void -HdDrawTargetRenderPass::Execute( +HdxDrawTargetRenderPass::Execute( HdRenderPassStateSharedPtr const &renderPassState) { if (!_drawTarget) { @@ -140,7 +140,7 @@ HdDrawTargetRenderPass::Execute( } void -HdDrawTargetRenderPass::_ClearBuffers() +HdxDrawTargetRenderPass::_ClearBuffers() { float depthValue = _drawTargetRenderPassState->GetDepthClearValue(); glClearBufferfv(GL_DEPTH, 0, &depthValue); diff --git a/pxr/imaging/lib/hd/drawTargetRenderPass.h b/pxr/imaging/lib/hdx/drawTargetRenderPass.h similarity index 77% rename from pxr/imaging/lib/hd/drawTargetRenderPass.h rename to pxr/imaging/lib/hdx/drawTargetRenderPass.h index 6a831e2e19..d484c31f6a 100644 --- a/pxr/imaging/lib/hd/drawTargetRenderPass.h +++ b/pxr/imaging/lib/hdx/drawTargetRenderPass.h @@ -21,8 +21,8 @@ // KIND, either express or implied. See the Apache License for the specific // language governing permissions and limitations under the Apache License. // -#ifndef HD_DRAW_TARGET_RENDER_PASS_H -#define HD_DRAW_TARGET_RENDER_PASS_H +#ifndef HDX_DRAW_TARGET_RENDER_PASS_H +#define HDX_DRAW_TARGET_RENDER_PASS_H #include "pxr/imaging/hd/renderPass.h" #include "pxr/imaging/hd/rprimCollection.h" @@ -33,9 +33,9 @@ typedef boost::shared_ptr GlfGLContextSharedPtr; -class HdDrawTargetRenderPassState; +class HdxDrawTargetRenderPassState; -/// \class HdDrawTargetRenderPass +/// \class HdxDrawTargetRenderPass /// /// Represents an render pass that renders to a draw target. /// @@ -43,10 +43,10 @@ class HdDrawTargetRenderPassState; /// to major changes. It is likely this functionality will be absorbed into /// the base class. /// -class HdDrawTargetRenderPass : boost::noncopyable { +class HdxDrawTargetRenderPass : boost::noncopyable { public: - HdDrawTargetRenderPass(HdRenderIndex *index); - virtual ~HdDrawTargetRenderPass(); + HdxDrawTargetRenderPass(HdRenderIndex *index); + virtual ~HdxDrawTargetRenderPass(); /// Sets the target draw object of this render pass containing /// the color buffers and depth buffer to use. @@ -54,7 +54,7 @@ class HdDrawTargetRenderPass : boost::noncopyable { /// Sets the non-context dependent state. The object is expected to /// live longer than this class. - void SetRenderPassState(HdDrawTargetRenderPassState *renderPassState); + void SetRenderPassState(HdxDrawTargetRenderPassState *renderPassState); void SetRprimCollection(HdRprimCollection const& col); @@ -69,7 +69,7 @@ class HdDrawTargetRenderPass : boost::noncopyable { HdRenderPass _renderPass; /// drawtarget renderPass state - HdDrawTargetRenderPassState *_drawTargetRenderPassState; + HdxDrawTargetRenderPassState *_drawTargetRenderPassState; /// Local copy of the draw target object. GlfDrawTargetRefPtr _drawTarget; @@ -83,9 +83,9 @@ class HdDrawTargetRenderPass : boost::noncopyable { void _ClearBuffers(); // No default/copy - HdDrawTargetRenderPass() = delete; - HdDrawTargetRenderPass(const HdDrawTargetRenderPass &) = delete; - HdDrawTargetRenderPass &operator =(const HdDrawTargetRenderPass &) = delete; + HdxDrawTargetRenderPass() = delete; + HdxDrawTargetRenderPass(const HdxDrawTargetRenderPass &) = delete; + HdxDrawTargetRenderPass &operator =(const HdxDrawTargetRenderPass &) = delete; }; -#endif // HD_DRAW_TARGET_RENDER_PASS_H +#endif // HDX_DRAW_TARGET_RENDER_PASS_H diff --git a/pxr/imaging/lib/hd/drawTargetRenderPassState.cpp b/pxr/imaging/lib/hdx/drawTargetRenderPassState.cpp similarity index 77% rename from pxr/imaging/lib/hd/drawTargetRenderPassState.cpp rename to pxr/imaging/lib/hdx/drawTargetRenderPassState.cpp index a5e54622a6..2c8a16de59 100644 --- a/pxr/imaging/lib/hd/drawTargetRenderPassState.cpp +++ b/pxr/imaging/lib/hdx/drawTargetRenderPassState.cpp @@ -21,10 +21,10 @@ // KIND, either express or implied. See the Apache License for the specific // language governing permissions and limitations under the Apache License. // -#include "drawTargetRenderPassState.h" +#include "pxr/imaging/hdx/drawTargetRenderPassState.h" #include "pxr/base/vt/value.h" -HdDrawTargetRenderPassState::HdDrawTargetRenderPassState() +HdxDrawTargetRenderPassState::HdxDrawTargetRenderPassState() : _colorClearValues() , _depthClearValue(1.0f) , _cameraId() @@ -34,19 +34,19 @@ HdDrawTargetRenderPassState::HdDrawTargetRenderPassState() } -HdDrawTargetRenderPassState::~HdDrawTargetRenderPassState() +HdxDrawTargetRenderPassState::~HdxDrawTargetRenderPassState() { } void -HdDrawTargetRenderPassState::SetNumColorAttachments(size_t numAttachments) +HdxDrawTargetRenderPassState::SetNumColorAttachments(size_t numAttachments) { _colorClearValues.resize(numAttachments); } void -HdDrawTargetRenderPassState::SetColorClearValue(size_t attachmentIdx, +HdxDrawTargetRenderPassState::SetColorClearValue(size_t attachmentIdx, const VtValue &clearValue) { TF_DEV_AXIOM(attachmentIdx < _colorClearValues.size()); @@ -54,19 +54,19 @@ HdDrawTargetRenderPassState::SetColorClearValue(size_t attachmentIdx, } void -HdDrawTargetRenderPassState::SetDepthClearValue(float clearValue) +HdxDrawTargetRenderPassState::SetDepthClearValue(float clearValue) { _depthClearValue = clearValue; } void -HdDrawTargetRenderPassState::SetCamera(const SdfPath &cameraId) +HdxDrawTargetRenderPassState::SetCamera(const SdfPath &cameraId) { _cameraId = cameraId; } -void HdDrawTargetRenderPassState::SetRprimCollection( +void HdxDrawTargetRenderPassState::SetRprimCollection( HdRprimCollection const& col) { _rprimCollection = col; diff --git a/pxr/imaging/lib/hd/drawTargetRenderPassState.h b/pxr/imaging/lib/hdx/drawTargetRenderPassState.h similarity index 88% rename from pxr/imaging/lib/hd/drawTargetRenderPassState.h rename to pxr/imaging/lib/hdx/drawTargetRenderPassState.h index 2caf78feeb..af0d1cfa60 100644 --- a/pxr/imaging/lib/hd/drawTargetRenderPassState.h +++ b/pxr/imaging/lib/hdx/drawTargetRenderPassState.h @@ -21,15 +21,15 @@ // KIND, either express or implied. See the Apache License for the specific // language governing permissions and limitations under the Apache License. // -#ifndef HD_DRAW_TARGET_RENDER_PASS_STATE_H -#define HD_DRAW_TARGET_RENDER_PASS_STATE_H +#ifndef HDX_DRAW_TARGET_RENDER_PASS_STATE_H +#define HDX_DRAW_TARGET_RENDER_PASS_STATE_H #include "pxr/usd/sdf/path.h" #include "pxr/imaging/hd/rprimCollection.h" class VtValue; -/// \class HdDrawTargetRenderPassState +/// \class HdxDrawTargetRenderPassState /// /// Represents common non-gl context specific render pass state for a draw /// target. @@ -38,10 +38,10 @@ class VtValue; /// to major changes. It is likely this functionality will be absorbed into /// the base class. /// -class HdDrawTargetRenderPassState final { +class HdxDrawTargetRenderPassState final { public: - HdDrawTargetRenderPassState(); - ~HdDrawTargetRenderPassState(); // final no need to be virtual + HdxDrawTargetRenderPassState(); + ~HdxDrawTargetRenderPassState(); // final no need to be virtual /// Set the number of color buffer's to use. void SetNumColorAttachments(size_t numAttachments); @@ -105,8 +105,8 @@ class HdDrawTargetRenderPassState final { HdRprimCollection _rprimCollection; unsigned int _rprimCollectionVersion; - HdDrawTargetRenderPassState(const HdDrawTargetRenderPassState &) = delete; - HdDrawTargetRenderPassState &operator =(const HdDrawTargetRenderPassState &) = delete; + HdxDrawTargetRenderPassState(const HdxDrawTargetRenderPassState &) = delete; + HdxDrawTargetRenderPassState &operator =(const HdxDrawTargetRenderPassState &) = delete; }; -#endif // HD_DRAW_TARGET_RENDER_PASS_STATE_H +#endif // HDX_DRAW_TARGET_RENDER_PASS_STATE_H diff --git a/pxr/imaging/lib/hdx/drawTargetTask.cpp b/pxr/imaging/lib/hdx/drawTargetTask.cpp index f7b562994c..5d4195172e 100644 --- a/pxr/imaging/lib/hdx/drawTargetTask.cpp +++ b/pxr/imaging/lib/hdx/drawTargetTask.cpp @@ -24,13 +24,13 @@ #include "pxr/imaging/glf/glew.h" #include "pxr/imaging/hdx/camera.h" +#include "pxr/imaging/hdx/drawTarget.h" +#include "pxr/imaging/hdx/drawTargetRenderPass.h" #include "pxr/imaging/hdx/drawTargetTask.h" #include "pxr/imaging/hdx/simpleLightingShader.h" #include "pxr/imaging/hdx/tokens.h" #include "pxr/imaging/hdx/debugCodes.h" -#include "pxr/imaging/hd/drawTarget.h" -#include "pxr/imaging/hd/drawTargetRenderPass.h" #include "pxr/imaging/hd/renderPassState.h" #include "pxr/imaging/hd/sprim.h" @@ -104,25 +104,27 @@ HdxDrawTargetTask::_Sync(HdTaskContext* ctx) HdRenderIndex &renderIndex = delegate->GetRenderIndex(); HdChangeTracker& changeTracker = renderIndex.GetChangeTracker(); - unsigned drawTargetVersion = changeTracker.GetDrawTargetSetVersion(); + unsigned drawTargetVersion + = changeTracker.GetStateVersion(HdxDrawTargetTokens->drawTargetSet); + if (_currentDrawTargetSetVersion != drawTargetVersion) { - const HdRenderIndex::HdDrawTargetView &drawTargets = - renderIndex.GetDrawTargets(); + HdxDrawTargetSharedPtrVector drawTargets; + HdxDrawTarget::GetDrawTargets(delegate, &drawTargets); _renderPasses.clear(); - size_t numDrawTargets = drawTargets.size(); + size_t numDrawTargets = drawTargets.size(); _renderPasses.reserve(numDrawTargets); for (size_t drawTargetNum = 0; drawTargetNum < numDrawTargets; ++drawTargetNum) { - HdDrawTargetSharedPtr drawTarget = drawTargets[drawTargetNum]; + HdxDrawTargetSharedPtr drawTarget = drawTargets[drawTargetNum]; if (drawTarget) { if (drawTarget->IsEnabled()) { - HdDrawTargetRenderPassUniquePtr pass( - new HdDrawTargetRenderPass(&renderIndex)); + HdxDrawTargetRenderPassUniquePtr pass( + new HdxDrawTargetRenderPass(&renderIndex)); pass->SetDrawTarget(drawTarget->GetGlfDrawTarget()); pass->SetRenderPassState(drawTarget->GetRenderPassState()); @@ -152,7 +154,7 @@ HdxDrawTargetTask::_Sync(HdTaskContext* ctx) renderPassIdx < numRenderPasses; ++renderPassIdx) { RenderPassInfo &renderPassInfo = _renderPasses[renderPassIdx]; - HdDrawTargetSharedPtr target = renderPassInfo.target.lock(); + HdxDrawTargetSharedPtr target = renderPassInfo.target.lock(); unsigned int targetVersion = target->GetVersion(); if (renderPassInfo.version != targetVersion) { @@ -178,9 +180,9 @@ HdxDrawTargetTask::_Sync(HdTaskContext* ctx) ++renderPassIdx) { RenderPassInfo &renderPassInfo = _renderPasses[renderPassIdx]; - HdDrawTargetRenderPass *renderPass = renderPassInfo.pass.get(); + HdxDrawTargetRenderPass *renderPass = renderPassInfo.pass.get(); HdRenderPassStateSharedPtr &renderPassState = renderPassInfo.renderPassState; - HdDrawTargetSharedPtr drawTarget = renderPassInfo.target.lock(); + HdxDrawTargetSharedPtr drawTarget = renderPassInfo.target.lock(); const SdfPath &cameraId = drawTarget->GetRenderPassState()->GetCamera(); @@ -301,7 +303,7 @@ HdxDrawTargetTask::_Execute(HdTaskContext* ctx) renderPassIdx < numRenderPasses; ++renderPassIdx) { - HdDrawTargetRenderPass *renderPass = + HdxDrawTargetRenderPass *renderPass = _renderPasses[renderPassIdx].pass.get(); HdRenderPassStateSharedPtr renderPassState = _renderPasses[renderPassIdx].renderPassState; diff --git a/pxr/imaging/lib/hdx/drawTargetTask.h b/pxr/imaging/lib/hdx/drawTargetTask.h index e7d4e2964a..c7992cb54a 100644 --- a/pxr/imaging/lib/hdx/drawTargetTask.h +++ b/pxr/imaging/lib/hdx/drawTargetTask.h @@ -25,15 +25,15 @@ #define HDX_DRAW_TARGET_TASK_H #include "pxr/imaging/hdx/version.h" +#include "pxr/imaging/hdx/drawTargetRenderPass.h" #include "pxr/imaging/hd/task.h" -#include "pxr/imaging/hd/drawTargetRenderPass.h" #include "pxr/base/gf/vec2f.h" #include "pxr/base/gf/vec4f.h" -typedef boost::weak_ptr HdDrawTargetWeakPtr; -typedef std::unique_ptr HdDrawTargetRenderPassUniquePtr; +typedef boost::weak_ptr HdxDrawTargetWeakPtr; +typedef std::unique_ptr HdxDrawTargetRenderPassUniquePtr; typedef boost::shared_ptr HdxSimpleLightingShaderSharedPtr; // Not strictly necessary here. @@ -56,13 +56,12 @@ class HdxDrawTargetTask : public HdSceneTask { // use by std::vector::reserve(). struct RenderPassInfo { - HdDrawTargetRenderPassUniquePtr pass; - HdRenderPassStateSharedPtr renderPassState; - HdxSimpleLightingShaderSharedPtr simpleLightingShader; - HdDrawTargetWeakPtr target; - unsigned int version; + HdxDrawTargetRenderPassUniquePtr pass; + HdRenderPassStateSharedPtr renderPassState; + HdxSimpleLightingShaderSharedPtr simpleLightingShader; + HdxDrawTargetWeakPtr target; + unsigned int version; }; - bool _enableDrawTargets; unsigned _currentDrawTargetSetVersion; @@ -113,7 +112,7 @@ struct HdxDrawTargetTaskParams , enableLighting(false) , alphaThreshold(0.0) , tessLevel(1.0) - , drawingRange(0.0) + , drawingRange(0.9, -1.0) , depthBiasUseDefault(true) , depthBiasEnable(false) , depthBiasConstantFactor(0.0f) diff --git a/pxr/imaging/lib/hdx/unitTestDelegate.cpp b/pxr/imaging/lib/hdx/unitTestDelegate.cpp index f640ad5184..cc2fe38ad1 100644 --- a/pxr/imaging/lib/hdx/unitTestDelegate.cpp +++ b/pxr/imaging/lib/hdx/unitTestDelegate.cpp @@ -23,20 +23,27 @@ // #include "pxr/imaging/hdx/unitTestDelegate.h" +#include "pxr/base/gf/frustum.h" + #include "pxr/imaging/hd/engine.h" #include "pxr/imaging/hd/mesh.h" #include "pxr/imaging/hd/sprim.h" +#include "pxr/imaging/hd/surfaceShader.h" +#include "pxr/imaging/hd/texture.h" +#include "pxr/imaging/hd/textureResource.h" #include "pxr/imaging/hdx/camera.h" +#include "pxr/imaging/hdx/drawTarget.h" +#include "pxr/imaging/hdx/drawTargetAttachmentDescArray.h" +#include "pxr/imaging/hdx/drawTargetTask.h" #include "pxr/imaging/hdx/light.h" #include "pxr/imaging/hdx/renderTask.h" #include "pxr/imaging/hdx/selectionTask.h" #include "pxr/imaging/hdx/simpleLightTask.h" #include "pxr/imaging/hdx/shadowTask.h" #include "pxr/imaging/hdx/shadowMatrixComputation.h" +#include "pxr/imaging/glf/drawTarget.h" #include "pxr/imaging/pxOsd/tokens.h" -#include "pxr/base/gf/frustum.h" - TF_DEFINE_PRIVATE_TOKENS( _tokens, (rotate) @@ -104,6 +111,41 @@ class ShadowMatrix : public HdxShadowMatrixComputation private: GfMatrix4d _shadowMatrix; }; + +class DrawTargetTextureResource : public HdTextureResource +{ +public: + DrawTargetTextureResource(GlfDrawTargetRefPtr const &drawTarget) + : _drawTarget(drawTarget) { + } + virtual ~DrawTargetTextureResource() { + }; + + virtual bool IsPtex() const { + return false; + } + + virtual GLuint GetTexelsTextureId() { + return _drawTarget->GetAttachment("color")->GetGlTextureName(); + } + virtual GLuint GetTexelsSamplerId() { + return 0; + } + virtual GLuint64EXT GetTexelsTextureHandle() { + return 0; + } + + virtual GLuint GetLayoutTextureId() { + return 0; + } + virtual GLuint64EXT GetLayoutTextureHandle() { + return 0; + } + +private: + GlfDrawTargetRefPtr _drawTarget; +}; + } // ------------------------------------------------------------------------ @@ -111,6 +153,8 @@ class ShadowMatrix : public HdxShadowMatrixComputation Hdx_UnitTestDelegate::Hdx_UnitTestDelegate() : Hdx_UnitTestDelegate(HdRenderIndexSharedPtr(new HdRenderIndex())) { + GetRenderIndex().GetChangeTracker().AddState( + HdxDrawTargetTokens->drawTargetSet); } Hdx_UnitTestDelegate::Hdx_UnitTestDelegate(HdRenderIndexSharedPtr const &index) @@ -220,6 +264,57 @@ Hdx_UnitTestDelegate::SetLight(SdfPath const &id, TfToken const &key, } } +void +Hdx_UnitTestDelegate::AddDrawTarget(SdfPath const &id) +{ + GetRenderIndex().InsertSprim(this, id); + _ValueCache &cache = _valueCacheMap[id]; + + HdxDrawTargetAttachmentDescArray attachments; + attachments.AddAttachment("color", HdFormatR8G8B8A8UNorm, VtValue(GfVec4f(1,1,0,1))); + + cache[HdxDrawTargetTokens->enable] = VtValue(true); + cache[HdxDrawTargetTokens->camera] = VtValue(SdfPath()); + cache[HdxDrawTargetTokens->resolution] = VtValue(GfVec2i(256, 256)); + cache[HdxDrawTargetTokens->attachments] = VtValue(attachments); + cache[HdxDrawTargetTokens->depthClearValue] = VtValue(1.0f); + cache[HdxDrawTargetTokens->collection] = + VtValue(HdRprimCollection(HdTokens->geometry, HdTokens->hull)); + + GetRenderIndex().InsertTexture(this, id); + _drawTargets[id] = _DrawTarget(); + + GetRenderIndex().GetChangeTracker().MarkStateDirty( + HdxDrawTargetTokens->drawTargetSet); +} + +void +Hdx_UnitTestDelegate::SetDrawTarget(SdfPath const &id, TfToken const &key, + VtValue value) +{ + _ValueCache &cache = _valueCacheMap[id]; + cache[key] = value; + if (key == HdxDrawTargetTokens->enable) { + GetRenderIndex().GetChangeTracker().MarkSprimDirty( + id, HdxDrawTarget::DirtyDTEnable); + } else if (key == HdxDrawTargetTokens->camera) { + GetRenderIndex().GetChangeTracker().MarkSprimDirty( + id, HdxDrawTarget::DirtyDTCamera); + } else if (key == HdxDrawTargetTokens->resolution) { + GetRenderIndex().GetChangeTracker().MarkSprimDirty( + id, HdxDrawTarget::DirtyDTResolution); + } else if (key == HdxDrawTargetTokens->attachments) { + GetRenderIndex().GetChangeTracker().MarkSprimDirty( + id, HdxDrawTarget::DirtyDTAttachment); + } else if (key == HdxDrawTargetTokens->depthClearValue) { + GetRenderIndex().GetChangeTracker().MarkSprimDirty( + id, HdxDrawTarget::DirtyDTDepthClearValue); + } else if (key == HdxDrawTargetTokens->collection) { + GetRenderIndex().GetChangeTracker().MarkSprimDirty( + id, HdxDrawTarget::DirtyDTCollection); + } +} + void Hdx_UnitTestDelegate::AddRenderTask(SdfPath const &id) { @@ -278,6 +373,20 @@ Hdx_UnitTestDelegate::AddSelectionTask(SdfPath const &id) cache[HdTokens->children] = VtValue(SdfPathVector()); } +void +Hdx_UnitTestDelegate::AddDrawTargetTask(SdfPath const &id) +{ + GetRenderIndex().InsertTask(this, id); + _ValueCache &cache = _valueCacheMap[id]; + cache[HdTokens->children] = VtValue(SdfPathVector()); + + HdxDrawTargetTaskParams params; + params.enableDrawTargets = true; + params.enableLighting = true; + cache[HdTokens->params] = params; + +} + void Hdx_UnitTestDelegate::SetTaskParam( SdfPath const &id, TfToken const &name, VtValue val) @@ -349,7 +458,9 @@ Hdx_UnitTestDelegate::AddGrid(SdfPath const &id, GfMatrix4d const &transform, _CreateGrid(10, 10, &points, &numVerts, &verts); _meshes[id] = _Mesh(transform, points, numVerts, verts, guide); - GetRenderIndex().InsertRprim(this, id, SdfPath(), instancerId); + SdfPath shaderId; + TfMapLookup(_surfaceShaderBindings, id, &shaderId); + GetRenderIndex().InsertRprim(this, id, shaderId, instancerId); if (not instancerId.IsEmpty()) { _instancers[instancerId].prototypes.push_back(id); } @@ -386,7 +497,9 @@ Hdx_UnitTestDelegate::AddCube(SdfPath const &id, GfMatrix4d const &transform, guide); _meshes[id].color = GfVec4f(1,1,1,1); - GetRenderIndex().InsertRprim(this, id, SdfPath(), instancerId); + SdfPath shaderId; + TfMapLookup(_surfaceShaderBindings, id, &shaderId); + GetRenderIndex().InsertRprim(this, id, shaderId, instancerId); if (not instancerId.IsEmpty()) { _instancers[instancerId].prototypes.push_back(id); } @@ -436,7 +549,9 @@ Hdx_UnitTestDelegate::AddTet(SdfPath const &id, GfMatrix4d const &transform, guide); _meshes[id].color = GfVec4f(1,1,1,1); - GetRenderIndex().InsertRprim(this, id, SdfPath(), instancerId); + SdfPath shaderId; + TfMapLookup(_surfaceShaderBindings, id, &shaderId); + GetRenderIndex().InsertRprim(this, id, shaderId, instancerId); if (not instancerId.IsEmpty()) { _instancers[instancerId].prototypes.push_back(id); } @@ -523,7 +638,10 @@ Hdx_UnitTestDelegate::Get(SdfPath const& id, TfToken const& key) return VtValue(_instancers[id].translate); } } else if (key == HdShaderTokens->surfaceShader) { - return VtValue(SdfPath()); + SdfPath shaderId; + TfMapLookup(_surfaceShaderBindings, id, &shaderId); + + return VtValue(shaderId); } return VtValue(); } @@ -633,3 +751,91 @@ Hdx_UnitTestDelegate::GetPrimVarInstanceNames(SdfPath const &id) } return names; } + +void +Hdx_UnitTestDelegate::AddSurfaceShader(SdfPath const &id, + std::string const &source, + HdShaderParamVector const ¶ms) +{ + HdRenderIndex& index = GetRenderIndex(); + index.InsertShader(this, id); + _surfaceShaders[id] = _SurfaceShader(source, params); +} + +void +Hdx_UnitTestDelegate::BindSurfaceShader(SdfPath const &rprimId, + SdfPath const &shaderId) +{ + _surfaceShaderBindings[rprimId] = shaderId; +} + +/*virtual*/ +std::string +Hdx_UnitTestDelegate::GetSurfaceShaderSource(SdfPath const &shaderId) +{ + if (_SurfaceShader *shader = TfMapLookupPtr(_surfaceShaders, shaderId)) { + return shader->source; + } else { + return TfToken(); + } +} + +/*virtual*/ +TfTokenVector +Hdx_UnitTestDelegate::GetSurfaceShaderParamNames(SdfPath const &shaderId) +{ + TfTokenVector names; + if (_SurfaceShader *shader = TfMapLookupPtr(_surfaceShaders, shaderId)) { + TF_FOR_ALL(paramIt, shader->params) { + names.push_back(TfToken(paramIt->GetName())); + } + } + return names; +} + +/*virtual*/ +HdShaderParamVector +Hdx_UnitTestDelegate::GetSurfaceShaderParams(SdfPath const &shaderId) +{ + if (_SurfaceShader *shader = TfMapLookupPtr(_surfaceShaders, shaderId)) { + return shader->params; + } + return HdShaderParamVector(); +} + +/*virtual*/ +VtValue +Hdx_UnitTestDelegate::GetSurfaceShaderParamValue(SdfPath const &shaderId, + TfToken const ¶mName) +{ + if (_SurfaceShader *shader = TfMapLookupPtr(_surfaceShaders, shaderId)) { + TF_FOR_ALL(paramIt, shader->params) { + if (paramIt->GetName() == paramName) + return paramIt->GetFallbackValue(); + } + } + return VtValue(); +} + +HdTextureResourceSharedPtr +Hdx_UnitTestDelegate::GetTextureResource(SdfPath const& textureId) +{ + if (_drawTargets.find(textureId) != _drawTargets.end()) { + HdSprimSharedPtr const &sprim = GetRenderIndex().GetSprim(textureId); + if (HdxDrawTargetSharedPtr drawTarget + = boost::dynamic_pointer_cast(sprim)) { + + HdTextureResourceSharedPtr texResource( + new DrawTargetTextureResource( + drawTarget->GetGlfDrawTarget())); + return texResource; + } + } + return HdTextureResourceSharedPtr(); +} + +HdTextureResource::ID +Hdx_UnitTestDelegate::GetTextureResourceID(SdfPath const& textureId) +{ + return SdfPath::Hash()(textureId); +} diff --git a/pxr/imaging/lib/hdx/unitTestDelegate.h b/pxr/imaging/lib/hdx/unitTestDelegate.h index e346474617..5e72a16ff5 100644 --- a/pxr/imaging/lib/hdx/unitTestDelegate.h +++ b/pxr/imaging/lib/hdx/unitTestDelegate.h @@ -59,12 +59,17 @@ class Hdx_UnitTestDelegate : public HdSceneDelegate void AddLight(SdfPath const &id, GlfSimpleLight const &light); void SetLight(SdfPath const &id, TfToken const &key, VtValue value); + // draw target + void AddDrawTarget(SdfPath const &id); + void SetDrawTarget(SdfPath const &id, TfToken const &key, VtValue value); + // tasks void AddRenderTask(SdfPath const &id); void AddRenderSetupTask(SdfPath const &id); void AddSimpleLightTask(SdfPath const &id); void AddShadowTask(SdfPath const &id); void AddSelectionTask(SdfPath const &id); + void AddDrawTargetTask(SdfPath const &id); void SetTaskParam(SdfPath const &id, TfToken const &name, VtValue val); VtValue GetTaskParam(SdfPath const &id, TfToken const &name); @@ -80,6 +85,12 @@ class Hdx_UnitTestDelegate : public HdSceneDelegate VtVec4fArray const &rotate, VtVec3fArray const &translate); + /// Shader + void AddSurfaceShader(SdfPath const &id, + std::string const &source, + HdShaderParamVector const ¶ms); + void BindSurfaceShader(SdfPath const &rprimId, SdfPath const &shaderId); + // prims void AddGrid(SdfPath const &id, GfMatrix4d const &transform, bool guide=false, SdfPath const &instancerId=SdfPath()); @@ -106,6 +117,14 @@ class Hdx_UnitTestDelegate : public HdSceneDelegate virtual int GetRefineLevel(SdfPath const& id); virtual bool IsInCollection(SdfPath const& id, TfToken const& collectionName); + virtual std::string GetSurfaceShaderSource(SdfPath const &shaderId); + virtual TfTokenVector GetSurfaceShaderParamNames(SdfPath const &shaderId); + virtual HdShaderParamVector GetSurfaceShaderParams(SdfPath const &shaderId); + virtual VtValue GetSurfaceShaderParamValue(SdfPath const &shaderId, + TfToken const ¶mName); + virtual HdTextureResource::ID GetTextureResourceID(SdfPath const& textureId); + virtual HdTextureResourceSharedPtr GetTextureResource(SdfPath const& textureId); + private: struct _Mesh { _Mesh() { } @@ -143,11 +162,28 @@ class Hdx_UnitTestDelegate : public HdSceneDelegate std::vector prototypes; }; + struct _SurfaceShader { + _SurfaceShader() { } + _SurfaceShader(std::string const &src, HdShaderParamVector const &pms) + : source(src) + , params(pms) { + } + + std::string source; + HdShaderParamVector params; + }; + struct _DrawTarget { + }; std::map _meshes; std::map _instancers; + std::map _surfaceShaders; std::map _refineLevels; + std::map _drawTargets; int _refineLevel; + typedef std::map SdfPathMap; + SdfPathMap _surfaceShaderBindings; + typedef TfHashMap _ValueCache; typedef TfHashMap _ValueCacheMap; _ValueCacheMap _valueCacheMap; diff --git a/pxr/imaging/lib/hdx/version.h b/pxr/imaging/lib/hdx/version.h index f4956448dc..7d8c4b1e57 100644 --- a/pxr/imaging/lib/hdx/version.h +++ b/pxr/imaging/lib/hdx/version.h @@ -26,7 +26,8 @@ // 1 -> 2 : split HdxRenderSetupTask out of HdxRenderTask // 2 -> 3 : move simpleLightingShader to Hdx. -// 3 -> 4: move camera and light to Hdx. -#define HDX_API 4 +// 3 -> 4 : move camera and light to Hdx. +// 4 -> 5 : move drawTarget to Hdx. +#define HDX_API 5 #endif // HDX_VERSION_H From 54a7d9fe901ad3a2e670ff1b2adcd4a3904acaab Mon Sep 17 00:00:00 2001 From: takahito-tejima Date: Mon, 19 Sep 2016 09:51:52 -0700 Subject: [PATCH 151/380] [UsdImaging] fix "Display Prim Id" in usdview PrimId display was not working, since HdRenderPassState overrides ALPHA_TO_COVERAGE to be enabled even in ID Rendering. adding unit test. (Internal change: 1655532) --- pxr/usdImaging/lib/usdImaging/defaultTaskDelegate.cpp | 11 ++++++++++- pxr/usdImaging/lib/usdImaging/defaultTaskDelegate.h | 3 +++ pxr/usdImaging/lib/usdImaging/hdEngine.cpp | 4 +++- .../usdImaging/testenv/testUsdImagingBasicDrawing.cpp | 3 ++- pxr/usdImaging/lib/usdImaging/unitTestGLDrawing.cpp | 7 ++++++- pxr/usdImaging/lib/usdImaging/unitTestGLDrawing.h | 2 ++ 6 files changed, 26 insertions(+), 4 deletions(-) diff --git a/pxr/usdImaging/lib/usdImaging/defaultTaskDelegate.cpp b/pxr/usdImaging/lib/usdImaging/defaultTaskDelegate.cpp index dba55751da..0d3f5b81c0 100644 --- a/pxr/usdImaging/lib/usdImaging/defaultTaskDelegate.cpp +++ b/pxr/usdImaging/lib/usdImaging/defaultTaskDelegate.cpp @@ -568,7 +568,16 @@ UsdImaging_DefaultTaskDelegate::IsConverged() const return true; } - +/* virtual */ +bool +UsdImaging_DefaultTaskDelegate::IsEnabled(TfToken const& option) const +{ + if (option == HdxOptionTokens->taskSetAlphaToCoverage) { + // UsdImagingHdEngine enables ALPHA_TO_COVERAGE as needed. + return true; + } + return HdSceneDelegate::IsEnabled(option); +} /* virtual */ std::vector diff --git a/pxr/usdImaging/lib/usdImaging/defaultTaskDelegate.h b/pxr/usdImaging/lib/usdImaging/defaultTaskDelegate.h index a2d3406334..c05cd21db0 100644 --- a/pxr/usdImaging/lib/usdImaging/defaultTaskDelegate.h +++ b/pxr/usdImaging/lib/usdImaging/defaultTaskDelegate.h @@ -75,6 +75,9 @@ class UsdImaging_DefaultTaskDelegate : public UsdImagingTaskDelegate { // returns true if the image is converged. virtual bool IsConverged() const; + /// Returns true if the named option is enabled by the delegate. + virtual bool IsEnabled(TfToken const& option) const; + // returns the root namespace scope which tasks, camera and lights // belong to. SdfPath const &GetRootID() const { return _rootId; } diff --git a/pxr/usdImaging/lib/usdImaging/hdEngine.cpp b/pxr/usdImaging/lib/usdImaging/hdEngine.cpp index b1848e321c..c68dcb7247 100644 --- a/pxr/usdImaging/lib/usdImaging/hdEngine.cpp +++ b/pxr/usdImaging/lib/usdImaging/hdEngine.cpp @@ -507,7 +507,9 @@ UsdImagingHdEngine::Render(HdRenderIndex& index, RenderParams params) // note: to get benefit of alpha-to-coverage, the target framebuffer // has to be a MSAA buffer. - if (params.enableSampleAlphaToCoverage) { + if (params.enableIdRender) { + glDisable(GL_SAMPLE_ALPHA_TO_COVERAGE); + } else if (params.enableSampleAlphaToCoverage) { glEnable(GL_SAMPLE_ALPHA_TO_COVERAGE); } diff --git a/pxr/usdImaging/lib/usdImaging/testenv/testUsdImagingBasicDrawing.cpp b/pxr/usdImaging/lib/usdImaging/testenv/testUsdImagingBasicDrawing.cpp index ca72c2e8c0..ff13c408c5 100644 --- a/pxr/usdImaging/lib/usdImaging/testenv/testUsdImagingBasicDrawing.cpp +++ b/pxr/usdImaging/lib/usdImaging/testenv/testUsdImagingBasicDrawing.cpp @@ -226,7 +226,8 @@ My_TestGLDrawing::DrawTest(bool offscreen) } UsdImagingEngine::RenderParams params; params.drawMode = GetDrawMode(); - params.enableLighting = IsEnabledTestLighting(); + params.enableLighting = IsEnabledTestLighting(); + params.enableIdRender = IsEnabledIdRender(); params.frame = time; params.complexity = _GetComplexity(); params.cullStyle = IsEnabledCullBackfaces() ? diff --git a/pxr/usdImaging/lib/usdImaging/unitTestGLDrawing.cpp b/pxr/usdImaging/lib/usdImaging/unitTestGLDrawing.cpp index b638b46e5f..d6d271135b 100644 --- a/pxr/usdImaging/lib/usdImaging/unitTestGLDrawing.cpp +++ b/pxr/usdImaging/lib/usdImaging/unitTestGLDrawing.cpp @@ -249,6 +249,7 @@ UsdImaging_UnitTestDrawingQGLWidget::mouseMoveEvent(QMouseEvent * event) UsdImaging_UnitTestGLDrawing::UsdImaging_UnitTestGLDrawing() : _widget(NULL) , _testLighting(false) + , _testIdRender(false) , _complexity(1.0f) , _drawMode(UsdImagingEngine::DRAW_SHADED_SMOOTH) , _shouldFrameAll(false) @@ -325,7 +326,7 @@ static void Usage(int argc, char *argv[]) { static const char usage[] = "%s [-stage filePath] [-write filePath]\n" -" [-offscreen] [-lighting]\n" +" [-offscreen] [-lighting] [-idRender]\n" " [-complexity complexity]\n" " [-shading [flat|smooth|wire|wireOnSurface]]\n" " [-frameAll]\n" @@ -340,6 +341,7 @@ static void Usage(int argc, char *argv[]) " -write filePath name of image file to write (suffix determines type) []\n" " -offscreen execute without mapping a window\n" " -lighting use simple lighting override shader\n" +" -idRender ID rendering\n" " -complexity complexity\n" " Set the fallback complexity [1]\n" " -shading [flat|smooth|wire|wireOnSurface]\n" @@ -431,6 +433,9 @@ UsdImaging_UnitTestGLDrawing::_Parse(int argc, char *argv[], _Args* args) else if (strcmp(argv[i], "-lighting") == 0) { _testLighting = true; } + else if (strcmp(argv[i], "-idRender") == 0) { + _testIdRender = true; + } else if (strcmp(argv[i], "-stage") == 0) { CheckForMissingArguments(i, 1, argc, argv); args->unresolvedStageFilePath = argv[++i]; diff --git a/pxr/usdImaging/lib/usdImaging/unitTestGLDrawing.h b/pxr/usdImaging/lib/usdImaging/unitTestGLDrawing.h index 457264c199..1f720ebecd 100644 --- a/pxr/usdImaging/lib/usdImaging/unitTestGLDrawing.h +++ b/pxr/usdImaging/lib/usdImaging/unitTestGLDrawing.h @@ -49,6 +49,7 @@ class UsdImaging_UnitTestGLDrawing { bool IsEnabledTestLighting() const { return _testLighting; } bool IsEnabledCullBackfaces() const { return _cullBackfaces; } + bool IsEnabledIdRender() const { return _testIdRender; } UsdImagingEngine::DrawMode GetDrawMode() const { return _drawMode; } @@ -82,6 +83,7 @@ class UsdImaging_UnitTestGLDrawing { private: UsdImaging_UnitTestDrawingQGLWidget *_widget; bool _testLighting; + bool _testIdRender; std::string _stageFilePath; std::string _outputFilePath; From d5ddc4ce5866626d60804649b1c9142ef523bd51 Mon Sep 17 00:00:00 2001 From: dakrunch Date: Mon, 19 Sep 2016 09:52:08 -0700 Subject: [PATCH 152/380] add warning (Internal change: 1655663) --- third_party/katana/python/nodetypes/PxrUsdIn.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/third_party/katana/python/nodetypes/PxrUsdIn.py b/third_party/katana/python/nodetypes/PxrUsdIn.py index 490534e849..608894b57f 100644 --- a/third_party/katana/python/nodetypes/PxrUsdIn.py +++ b/third_party/katana/python/nodetypes/PxrUsdIn.py @@ -54,7 +54,14 @@ def getScenegraphLocation(self, frameTime): gb.set('variants', '') nb.setHintsForParameter('variants', { - 'help' : 'Specify variant selections. Variant selections are specified via whitespace-separated variant selection paths. Example: /Foo{X=Y} /Bar{Z=w}', + # 'conditionalVisOp': 'notEqualTo', + # 'conditionalVisPath': '../variants', # can't really point to self... :( + # 'conditionalVisValue': '', + 'helpAlert': 'warning', + 'help' : 'DEPRECATED! Use PxrUsdInVariantSelect instead.'\ + ' Specify variant '\ + 'selections. Variant selections are specified via whitespace-separated'\ + ' variant selection paths. Example: /Foo{X=Y} /Bar{Z=w}', }) gb.set('ignoreLayerRegex', '') From 63b1ab43fa9e4bfbdf1c200927f0dcfbe55db824 Mon Sep 17 00:00:00 2001 From: takahito-tejima Date: Mon, 19 Sep 2016 09:52:50 -0700 Subject: [PATCH 153/380] [Hd] drop the GIL in HdRenderIndex::SyncAll() ideally, or at least, we like to put this lock in UsdImagingDelegate, but instancer rprim syncing is a special case which we haven't split delegate query into two-step sync (delegate sync, then rprim sync), so it goes all the way down to UsdStage directly from HdRenderIndex::Sync in parallel (i.e. _UpdateSingleValue). (Internal change: 1655762) --- pxr/imaging/lib/hd/renderIndex.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/pxr/imaging/lib/hd/renderIndex.cpp b/pxr/imaging/lib/hd/renderIndex.cpp index 387043187a..abe4fe2f2e 100644 --- a/pxr/imaging/lib/hd/renderIndex.cpp +++ b/pxr/imaging/lib/hd/renderIndex.cpp @@ -46,6 +46,7 @@ #include "pxr/base/work/arenaDispatcher.h" #include "pxr/base/work/loops.h" +#include "pxr/base/tf/pyLock.h" #include #include @@ -897,7 +898,12 @@ HdRenderIndex::SyncAll() ((float )numSkipped / (float)dirtyIds.size()) > 0.9f; } - } { + } + + // Drop the GIL before we spawn parallel tasks. + TF_PY_ALLOW_THREADS_IN_SCOPE(); + + { TRACE_SCOPE("Delegate Sync"); // Dispatch synchronization work to each delegate. _Worker worker(&syncMap); From 9ef58b36d3edf7833a6d1457b3554672a9c28e1f Mon Sep 17 00:00:00 2001 From: mrawde Date: Mon, 19 Sep 2016 09:54:13 -0700 Subject: [PATCH 154/380] Fix for shader bindings on instances. (Internal change: 1655955) --- .../lib/usdImaging/instanceAdapter.cpp | 42 +++++++++++-------- 1 file changed, 25 insertions(+), 17 deletions(-) diff --git a/pxr/usdImaging/lib/usdImaging/instanceAdapter.cpp b/pxr/usdImaging/lib/usdImaging/instanceAdapter.cpp index 887727a7c4..caa35a0d90 100644 --- a/pxr/usdImaging/lib/usdImaging/instanceAdapter.cpp +++ b/pxr/usdImaging/lib/usdImaging/instanceAdapter.cpp @@ -92,19 +92,28 @@ UsdImagingInstanceAdapter::Populate(UsdPrim const& prim, return SdfPath(); } + // This is a shared_ptr to the prim adapter for the current instancePrim. + const UsdImagingPrimAdapterSharedPtr instancedPrimAdapter = + _GetPrimAdapter(prim, /* ignoreInstancing = */ true); + + // This is a shared_ptr to ourself. The InstancerContext requires the + // adapter shared_ptr. + UsdImagingPrimAdapterSharedPtr const& instancerAdapter = + _GetSharedFromThis(); + + // If the current prim is drawable (instancedPrimAdapter is non-NULL), we + // ask it to give us the shader binding. Otherwise, this + // (instancerAdapter) will provide the shader binding. + const SdfPath& instanceShaderBinding = (instancedPrimAdapter + ? instancedPrimAdapter : instancerAdapter)->GetShaderBinding(prim); + // Store away the path of the given instance prim to use as the // instancer for Hydra if this is the first time we've seen this // (master, shader binding) pair. - const SdfPath& instanceShaderBinding = GetShaderBinding(prim); const SdfPath& instancerPath = _masterToInstancerMap[masterPrim.GetPath()].insert( std::make_pair(instanceShaderBinding, instancePath)).first->second; - // This is a shared_ptr to ourself. The InstancerContext requires the - // adapter shared_ptr. - UsdImagingPrimAdapterSharedPtr const& instancerAdapter = - _GetSharedFromThis(); - _InstancerData& instancerData = _instancerData[instancerPath]; instancerData.dirtyBits = HdChangeTracker::AllDirty; @@ -203,14 +212,12 @@ UsdImagingInstanceAdapter::Populate(UsdPrim const& prim, // // In this case, we dispatch to the underlying PrimAdapter and disable // instancing. - if (const UsdImagingPrimAdapterSharedPtr instanceAdapter = - _GetPrimAdapter(prim, /* ignoreInstancing = */ true)) { - + if (instancedPrimAdapter) { UsdTreeIterator treeIt(prim); const SdfPath protoPath = _InsertProtoRprim(&treeIt, TfToken(), instanceShaderBinding, - SdfPath(), instanceAdapter, index); + SdfPath(), instancedPrimAdapter, index); instancePath = SdfPath(); } @@ -275,15 +282,20 @@ UsdImagingInstanceAdapter::_InsertProtoRprim(UsdTreeIterator* it, UsdPrim const& prim = **it; SdfPath protoPath; - // If this prim is an instance, we can use the given instanceShaderBinding. + // Talk to the prim's native adapter to do population and ShaderBinding + // queries on our behalf. + UsdImagingPrimAdapterSharedPtr const& adapter = + _GetPrimAdapter(prim, /* ignoreInstancing = */ true); + + // If this prim is an instance, we can use the given instanceShaderBinding // Otherwise, this is a prim in a master; we need to see if there's any // applicable bindings authored and only fallback to the instance binding // if there isn't one. - auto getShaderForPrim = [this, instanceShaderBinding](UsdPrim const& prim) { + auto getShaderForPrim = [adapter, instanceShaderBinding](UsdPrim const& prim) { if (prim.IsInstance()) { return instanceShaderBinding; } - SdfPath shaderId = this->GetShaderBinding(prim); + SdfPath shaderId = adapter->GetShaderBinding(prim); return shaderId.IsEmpty() ? instanceShaderBinding : shaderId; }; @@ -302,10 +314,6 @@ UsdImagingInstanceAdapter::_InsertProtoRprim(UsdTreeIterator* it, getShaderForPrim(prim), instancerAdapter }; - // Talk to the prim's native adapter to do population on our behalf. - UsdImagingPrimAdapterSharedPtr const& adapter = - _GetPrimAdapter(prim, /* ignoreInstancing = */ true); - // There is no need to call AddDependency, as it will be picked up via the // instancer context. SdfPath populatedPath = adapter->Populate(prim, index, &ctx); From 2f09df5e973a68b49e960d37b73ad0a16a735f53 Mon Sep 17 00:00:00 2001 From: sunyab Date: Mon, 19 Sep 2016 09:55:34 -0700 Subject: [PATCH 155/380] Enable testTfPyFunction in the build, also add copyright notice. (Internal change: 1655968) --- pxr/base/lib/tf/CMakeLists.txt | 11 ++++++++++ pxr/base/lib/tf/testenv/testTfPyFunction.cpp | 23 ++++++++++++++++++++ 2 files changed, 34 insertions(+) diff --git a/pxr/base/lib/tf/CMakeLists.txt b/pxr/base/lib/tf/CMakeLists.txt index 66629d9a7e..7852d715de 100644 --- a/pxr/base/lib/tf/CMakeLists.txt +++ b/pxr/base/lib/tf/CMakeLists.txt @@ -196,6 +196,14 @@ pxr_shared_library(tf testenv/testTfScriptModuleLoader_Unknown.py ) +pxr_build_test(testTfPyFunction + LIBRARIES + tf + ${Boost_PYTHON_LIBRARY} + CPPFILES + testenv/testTfPyFunction.cpp +) + pxr_build_test(testTfPyInterpreter LIBRARIES tf @@ -565,6 +573,9 @@ pxr_register_test(testTfPython PYTHON COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testTfPython" ) +pxr_register_test(testTfPyFunction + COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testTfPyFunction" +) pxr_register_test(testTfPyNotice PYTHON COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testTfPyNotice" diff --git a/pxr/base/lib/tf/testenv/testTfPyFunction.cpp b/pxr/base/lib/tf/testenv/testTfPyFunction.cpp index 727fbe0b14..89ccbfcfc3 100644 --- a/pxr/base/lib/tf/testenv/testTfPyFunction.cpp +++ b/pxr/base/lib/tf/testenv/testTfPyFunction.cpp @@ -1,3 +1,26 @@ +// +// 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. +// #include "pxr/base/tf/pyFunction.h" #include "pxr/base/tf/pyInterpreter.h" #include "pxr/base/tf/pyUtils.h" From a4bfa200e5669a77237cfade563987c3425cd870 Mon Sep 17 00:00:00 2001 From: sunyab Date: Mon, 19 Sep 2016 10:05:17 -0700 Subject: [PATCH 156/380] Revert to using -j4 for builds on Travis. Using -j seems to have hurt build times, which caused CI builds to time out. (Internal change: 1655977) --- .travis.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index bc1e919711..a8b5528367 100644 --- a/.travis.yml +++ b/.travis.yml @@ -149,9 +149,10 @@ cache: script: - mkdir build && cd build - cmake -DTBB_ROOT_DIR=$HOME/tbb43_20141023oss -DOPENEXR_LOCATION=$HOME/openexr -DOIIO_LOCATION=$HOME/oiio -DOPENSUBDIV_ROOT_DIR=$HOME/osd -DPTEX_LOCATION=$HOME/ptex -DPXR_VALIDATE_GENERATED_CODE=OFF .. + - echo 'Building with -j4' # XXX: Need to explicitly build cameraUtil before hd due to missing dependency declaration. # This is fixed in commit 880b04. - - make -j cameraUtil - - make -j + - make -j4 cameraUtil + - make -j4 # Default install location is /usr/local; we need sudo access to write there. - sudo make install From eff4a96e02074c463bc89481dfc1cabbd68796fb Mon Sep 17 00:00:00 2001 From: superfunc Date: Wed, 21 Sep 2016 20:16:54 -0700 Subject: [PATCH 157/380] [Pxr] Fix readme typo. (Internal change: 1656079) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 4be88bdf34..dcbb57878a 100644 --- a/README.md +++ b/README.md @@ -147,7 +147,7 @@ Launch usdview with a sample asset. ```bash $ export PYTHONPATH=$PYTHONPATH:USD_INSTALL_ROOT/lib/python -$ usdview extras/usd/tutorials/convertingLayerFormats/sphere.usda +$ usdview extras/usd/tutorials/convertingLayerFormats/Sphere.usda ``` > Note: Replace ```USD_INSTALL_ROOT``` with the location set in your build, From f38a92f48f1e48be4cc0c6f6125ea8c82a803ba2 Mon Sep 17 00:00:00 2001 From: sunyab Date: Wed, 21 Sep 2016 20:22:33 -0700 Subject: [PATCH 158/380] Clean up installation of optional USD plugins Add the USD plugin install directory to the plugin search path. This ensures that plugins like usdAbc are usable without having to manually specify the plugin directory via an environment variable at runtime. USD plugins are now installed under the "plugin/usd" directory instead of just "plugin". This avoids collisions with other contents of that directory, and also provides a clear location to install other USD plugins. (Internal change: 1656966) --- cmake/macros/Public.cmake | 20 +++++++++++++------- pxr/base/lib/plug/initConfig.cpp | 11 +++++++---- 2 files changed, 20 insertions(+), 11 deletions(-) diff --git a/cmake/macros/Public.cmake b/cmake/macros/Public.cmake index d90e994ecd..6478505614 100644 --- a/cmake/macros/Public.cmake +++ b/cmake/macros/Public.cmake @@ -204,7 +204,7 @@ function(pxr_shared_library LIBRARY_NAME) set_target_properties(${LIBRARY_NAME} PROPERTIES COMPILE_DEFINITIONS - "MFB_PACKAGE_NAME=${PXR_PACKAGE};MFB_ALT_PACKAGE_NAME=${PXR_PACKAGE};MFB_PACKAGE_MODULE=${pyModuleName};PXR_USER_LOCATION=/usr/local/share/usd/plugins;PXR_BUILD_LOCATION=${CMAKE_INSTALL_PREFIX}/${PLUGINS_PREFIX};PXR_INSTALL_LOCATION=${installLocation}" + "MFB_PACKAGE_NAME=${PXR_PACKAGE};MFB_ALT_PACKAGE_NAME=${PXR_PACKAGE};MFB_PACKAGE_MODULE=${pyModuleName};PXR_USER_LOCATION=/usr/local/share/usd/plugins;PXR_BUILD_LOCATION=${CMAKE_INSTALL_PREFIX}/${PLUGINS_PREFIX};PXR_PLUGIN_BUILD_LOCATION=${CMAKE_INSTALL_PREFIX}/plugin/usd;PXR_INSTALL_LOCATION=${installLocation}" ) # Always bake the rpath. @@ -503,7 +503,7 @@ function(pxr_plugin PLUGIN_NAME) set(HEADER_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}/${PXR_INSTALL_SUBDIR}/include/${PXR_PREFIX}/${PLUGIN_NAME}") else() - set(PLUGIN_INSTALL_PREFIX "plugin") + set(PLUGIN_INSTALL_PREFIX "plugin/usd") set(HEADER_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}/include/${PXR_PREFIX}/${PLUGIN_NAME}") endif() @@ -525,9 +525,15 @@ function(pxr_plugin PLUGIN_NAME) else() # Ensure this plugin can find the libs for its matching component, e.g. # maya/plugin/px_usdIO.so can find maya/lib/*.so - set_target_properties(${PLUGIN_NAME} - PROPERTIES INSTALL_RPATH "${CMAKE_INSTALL_RPATH}:$ORIGIN/../lib" - ) + if (PXR_INSTALL_SUBDIR) + set_target_properties(${PLUGIN_NAME} + PROPERTIES INSTALL_RPATH "${CMAKE_INSTALL_RPATH}:$ORIGIN/../lib" + ) + else() + set_target_properties(${PLUGIN_NAME} + PROPERTIES INSTALL_RPATH "${CMAKE_INSTALL_RPATH}:$ORIGIN/../../lib" + ) + endif() endif() set_target_properties(${PLUGIN_NAME} @@ -612,7 +618,7 @@ function(pxr_plugin PLUGIN_NAME) ) endif() - _get_install_dir(plugin PLUGINS_PREFIX) + set(PLUGINS_PREFIX ${PLUGIN_INSTALL_PREFIX}) set(LIBRARY_NAME ${PLUGIN_NAME}) _get_library_file(${LIBRARY_NAME} LIBRARY_FILE) @@ -869,7 +875,7 @@ function(pxr_setup_plugins) "file(WRITE \"${CMAKE_INSTALL_PREFIX}/${SHARE_INSTALL_PREFIX}/plugins/plugInfo.json\" ${plugInfoContents})" ) install(CODE - "file(WRITE \"${CMAKE_INSTALL_PREFIX}/plugin/plugInfo.json\" ${plugInfoContents})" + "file(WRITE \"${CMAKE_INSTALL_PREFIX}/plugin/usd/plugInfo.json\" ${plugInfoContents})" ) endfunction() # pxr_setup_plugins diff --git a/pxr/base/lib/plug/initConfig.cpp b/pxr/base/lib/plug/initConfig.cpp index 97e225fc9d..ca225575ee 100644 --- a/pxr/base/lib/plug/initConfig.cpp +++ b/pxr/base/lib/plug/initConfig.cpp @@ -29,10 +29,12 @@ namespace { -const char* pathEnvVarName = BOOST_PP_STRINGIZE(PXR_PLUGINPATH_NAME); -const char* buildLocation = BOOST_PP_STRINGIZE(PXR_BUILD_LOCATION); -const char* userLocation = BOOST_PP_STRINGIZE(PXR_USER_LOCATION); -const char* installLocation = BOOST_PP_STRINGIZE(PXR_INSTALL_LOCATION); +const char* pathEnvVarName = BOOST_PP_STRINGIZE(PXR_PLUGINPATH_NAME); +const char* buildLocation = BOOST_PP_STRINGIZE(PXR_BUILD_LOCATION); +const char* pluginBuildLocation = BOOST_PP_STRINGIZE(PXR_PLUGIN_BUILD_LOCATION); +const char* userLocation = BOOST_PP_STRINGIZE(PXR_USER_LOCATION); +const char* installLocation = BOOST_PP_STRINGIZE(PXR_INSTALL_LOCATION); + void _AppendPathList(std::vector* result, const std::string& paths) { @@ -56,6 +58,7 @@ Plug_InitConfig() // Fallback locations. _AppendPathList(&result, userLocation); _AppendPathList(&result, buildLocation); + _AppendPathList(&result, pluginBuildLocation); _AppendPathList(&result, installLocation); Plug_SetPaths(result); From 1fdc2e875c21cdb9ce134b461c2b48befe61cbda Mon Sep 17 00:00:00 2001 From: sunyab Date: Thu, 22 Sep 2016 14:29:28 -0700 Subject: [PATCH 159/380] Adding CHANGELOG.md (Internal change: 1657174) --- CHANGELOG.md | 60 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) create mode 100644 CHANGELOG.md diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000000..a2f880a352 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,60 @@ +# Change Log + +## [0.7.1] - 2016-09-21 + +### Added +- UsdMaterial schema for shading, intended to replace UsdLook. Also added + support for this new schema to Hydra. +- Initial version of UsdUI schema library, intended for encoding GUI + information on USD prims. +- Parallel teardown of some data members in UsdStage, speeding up overall + teardown by ~2x. +- Support for packed vertex normals to Hydra, reducing GPU memory consumption + by 20-30% in some cases. +- Ability to compare two composed stages to usddiff by specifying the + "--compose" or "-c" options. +- Support for soft-selection for collapsed USD assemblies in Maya. +- Support for exporting color sets and UV sets as indexed primvars from Maya. + +### Changed +- Refactored Hydra libraries to move higher-level concepts out of the core + hd library and into hdx. +- Removed use of opensubdiv3/ include path from imaging code in favor of + standard opensubdiv/ include. +- Modified UsdStage to automatically load newly-discovered payloads if + their nearest ancestor's payload was also loaded. For example, consumers + will no longer have to explicitly call UsdStage::Load to ensure payloads + are loaded when switching variants on a prim, so long as their nearest + ancestor is also loaded. +- Refactoring and other changes to help with Mac and Windows ports. +- Updated doxygen and other documentation. + +### Fixed +- Fixed issue that caused Alembic plugin (usdAbc) to be misconfigured at + build time, which required users to manually update its plugInfo.json + and set an environment variable at runtime to make it work. This plugin + is now installed to $PREFIX/plugin/usd/ and requires no additional + steps to use once it has been built. +- Fixed issue with .usdc files that resulted in corrupted files on Windows. + The file structure was changed, so the .usdc version has been bumped + from 0.0.1 to 0.1.0. USD will continue to write 0.0.1 files by default, + but will begin writing 0.1.0 files in the near future. + + Users may choose to write files with the new version immediately + by setting the environment variable `USD_WRITE_NEW_USDC_FILES_AS_VERSION` + to "0.1.0". + + Note that 0.0.1 files are still readable using this release, + except for those that have been generated on Windows using 0.7.0. + Early testers on Windows will need to regenerate those files + with this release. +- Fixed issue that caused usdGenSchema to generate files that could + not be compiled. +- Added a workaround for TBB-related issue in Maya that caused hangs when + using the USD Maya plugin. This can be enabled at build time by + specifying the `PXR_MAYA_TBB_BUG_WORKAROUND` option to CMake. +- Various other bug fixes and performance improvements. + +## [0.7.0] - 2016-08-01 + +Initial release From 5847fbfab6b51d676733f09a7ad9bdf9af98794e Mon Sep 17 00:00:00 2001 From: sunyab Date: Thu, 22 Sep 2016 15:19:51 -0700 Subject: [PATCH 160/380] Add Travis build status to README.md. (Internal change: 1657247) --- README.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index dcbb57878a..6f1fa20cca 100644 --- a/README.md +++ b/README.md @@ -7,6 +7,13 @@ interchange between graphics applications. For more details, please visit the web site [here](http://openusd.org). +Build Status +------------ + +| | master | dev | +| ----- | ------ | --- | +| Linux | [![Build Status](https://travis-ci.org/PixarAnimationStudios/USD.svg?branch=master)](https://travis-ci.org/PixarAnimationStudios/USD) | [![Build Status](https://travis-ci.org/PixarAnimationStudios/USD.svg?branch=dev)](https://travis-ci.org/PixarAnimationStudios/USD) | + Additional Documentation ------------------------ @@ -14,7 +21,6 @@ Additional Documentation * [API Documentation](http://openusd.org/docs/api/index.html) * [Advanced Build Configuration](BUILDING.md) - Getting Help ------------ From 38f6baa28c1093248583b8f71b545a4335dc5193 Mon Sep 17 00:00:00 2001 From: mattyjams Date: Thu, 22 Sep 2016 23:55:00 -0700 Subject: [PATCH 161/380] add handling of USD_faceVaryingLinearInterpolation Maya attribute for subdiv mesh export The Maya export code already exports using the OSD3-style face varying linear interpolation attribute in USD rather than the now deprecated face varying interpolate boundary attribute from OSD2. This change adds a Maya attribute for specifying the value directly. We still consider the old attribute if it is present for backwards compatibility. (Internal change: 1656200) --- .../maya/lib/usdMaya/MayaMeshWriter.cpp | 12 +- third_party/maya/lib/usdMaya/meshUtil.cpp | 127 ++++++++++++------ third_party/maya/lib/usdMaya/meshUtil.h | 4 +- .../maya/lib/usdMaya/translatorMesh.cpp | 2 +- 4 files changed, 96 insertions(+), 49 deletions(-) diff --git a/third_party/maya/lib/usdMaya/MayaMeshWriter.cpp b/third_party/maya/lib/usdMaya/MayaMeshWriter.cpp index c7ddde8065..1c74544e52 100644 --- a/third_party/maya/lib/usdMaya/MayaMeshWriter.cpp +++ b/third_party/maya/lib/usdMaya/MayaMeshWriter.cpp @@ -202,13 +202,15 @@ bool MayaMeshWriter::writeMeshAttrs(const UsdTimeCode &usdTime, UsdGeomMesh &pri primSchema.CreateInterpolateBoundaryAttr(VtValue(sdInterpBound), true); - TfToken sdFVInterpBound = PxrUsdMayaMeshUtil::getSubdivFVInterpBoundary( - lMesh); + TfToken sdFVLinearInterpolation = + PxrUsdMayaMeshUtil::getSubdivFVLinearInterpolation(lMesh); - primSchema.CreateFaceVaryingLinearInterpolationAttr( - VtValue(sdFVInterpBound), true); + if (not sdFVLinearInterpolation.IsEmpty()) { + primSchema.CreateFaceVaryingLinearInterpolationAttr( + VtValue(sdFVLinearInterpolation), true); + } - assignSubDivTagsToUSDPrim( lMesh, primSchema); + assignSubDivTagsToUSDPrim(lMesh, primSchema); } // Holes - we treat InvisibleFaces as holes diff --git a/third_party/maya/lib/usdMaya/meshUtil.cpp b/third_party/maya/lib/usdMaya/meshUtil.cpp index 5b665b0eb8..0d9b09f264 100644 --- a/third_party/maya/lib/usdMaya/meshUtil.cpp +++ b/third_party/maya/lib/usdMaya/meshUtil.cpp @@ -47,6 +47,11 @@ TF_DEFINE_PRIVATE_TOKENS( _subdivTokens, (USD_subdivisionScheme) (USD_interpolateBoundary) + (USD_faceVaryingLinearInterpolation) + + // This token is deprecated as it is from OpenSubdiv 2 and the USD + // schema now conforms to OpenSubdiv 3, but we continue to look for it + // and translate to the equivalent new value for backwards compatibility. (USD_faceVaryingInterpolateBoundary) ); @@ -187,58 +192,97 @@ TfToken PxrUsdMayaMeshUtil::getSubdivInterpBoundary(const MFnMesh &mesh, TfToken } } -// This can be customize for specific pipeline -// We read the USD string attribute, if not present we look for the mojito int attribute -// If not present we look for the renderman for maya int attribute -// XXX Maybe we should come up with a OSD centric nomenclature ?? -TfToken PxrUsdMayaMeshUtil::getSubdivFVInterpBoundary(const MFnMesh &mesh) +// XXX: Note that this function is not exposed publicly since the USD schema +// has been updated to conform to OpenSubdiv 3. We still look for this attribute +// on Maya nodes specifying this value from OpenSubdiv 2, but we translate the +// value to OpenSubdiv 3. This is to support legacy assets authored against +// OpenSubdiv 2. +static +TfToken _getSubdivFVInterpBoundary(const MFnMesh& mesh) { - MString sdFVInterpBound; + TfToken sdFVInterpBound; MPlug plug = mesh.findPlug(MString(_subdivTokens->USD_faceVaryingInterpolateBoundary.GetText())); if (!plug.isNull()) { - sdFVInterpBound = plug.asString(); + sdFVInterpBound = TfToken(plug.asString().asChar()); + + // Translate OSD2 values to OSD3. + if (sdFVInterpBound == UsdGeomTokens->bilinear) { + sdFVInterpBound = UsdGeomTokens->all; + } else if (sdFVInterpBound == UsdGeomTokens->edgeAndCorner) { + sdFVInterpBound = UsdGeomTokens->cornersPlus1; + } else if (sdFVInterpBound == UsdGeomTokens->alwaysSharp) { + sdFVInterpBound = UsdGeomTokens->boundaries; + } else if (sdFVInterpBound == UsdGeomTokens->edgeOnly) { + sdFVInterpBound = UsdGeomTokens->none; + } } else { plug = mesh.findPlug(MString("mjtoSdSmoothFVInterp")); if (!plug.isNull()) { switch(plug.asInt()) { - case 1: sdFVInterpBound = "cornersPlus1"; break; - case 2: sdFVInterpBound = "all"; break; - case 3: sdFVInterpBound = "boundaries"; break; - default: break; + case 1: + sdFVInterpBound = UsdGeomTokens->cornersPlus1; + break; + case 2: + sdFVInterpBound = UsdGeomTokens->all; + break; + case 3: + sdFVInterpBound = UsdGeomTokens->boundaries; + break; + default: + break; } } else { plug = mesh.findPlug(MString("rman__torattr___subdivFacevaryingInterp")); if (!plug.isNull()) { switch(plug.asInt()) { - case 0: sdFVInterpBound = "all"; break; - case 1: sdFVInterpBound = "cornersPlus1"; break; - case 2: sdFVInterpBound = "none"; break; - case 3: sdFVInterpBound = "boundaries"; break; - default: break; + case 0: + sdFVInterpBound = UsdGeomTokens->all; + break; + case 1: + sdFVInterpBound = UsdGeomTokens->cornersPlus1; + break; + case 2: + sdFVInterpBound = UsdGeomTokens->none; + break; + case 3: + sdFVInterpBound = UsdGeomTokens->boundaries; + break; + default: + break; } } } } - if (sdFVInterpBound=="") { - return UsdGeomTokens->cornersPlus1; - } else if (sdFVInterpBound == "all" - or sdFVInterpBound == "bilinear") { - return UsdGeomTokens->all; - } else if (sdFVInterpBound == "cornersPlus1" - or sdFVInterpBound == "edgeAndCorner") { - return UsdGeomTokens->cornersPlus1; - } else if (sdFVInterpBound == "none" - or sdFVInterpBound == "edgeOnly") { - return UsdGeomTokens->none; - } else if (sdFVInterpBound == "boundaries" - or sdFVInterpBound == "alwaysSharp") { - return UsdGeomTokens->boundaries; + + return sdFVInterpBound; +} + +TfToken PxrUsdMayaMeshUtil::getSubdivFVLinearInterpolation(const MFnMesh& mesh) +{ + TfToken sdFVLinearInterpolation; + MPlug plug = mesh.findPlug(MString(_subdivTokens->USD_faceVaryingLinearInterpolation.GetText())); + if (!plug.isNull()) { + sdFVLinearInterpolation = TfToken(plug.asString().asChar()); } else { - MGlobal::displayError("Unsupported Face Varying InterpBoundary Attribute:" + - sdFVInterpBound + " on mesh:" + MString(mesh.fullPathName()) + - ". Defaulting to cornersPlus1"); - return UsdGeomTokens->cornersPlus1; + // If the OpenSubdiv 3-style face varying linear interpolation value + // wasn't specified, fall back to the old OpenSubdiv 2-style face + // varying interpolate boundary value if we have that. + sdFVLinearInterpolation = _getSubdivFVInterpBoundary(mesh); } + + if (not sdFVLinearInterpolation.IsEmpty() and + sdFVLinearInterpolation != UsdGeomTokens->all and + sdFVLinearInterpolation != UsdGeomTokens->none and + sdFVLinearInterpolation != UsdGeomTokens->boundaries and + sdFVLinearInterpolation != UsdGeomTokens->cornersOnly and + sdFVLinearInterpolation != UsdGeomTokens->cornersPlus1 and + sdFVLinearInterpolation != UsdGeomTokens->cornersPlus2) { + MGlobal::displayError("Unsupported Face Varying Linear Interpolation Attribute: " + + MString(sdFVLinearInterpolation.GetText()) + " on mesh: " + MString(mesh.fullPathName())); + sdFVLinearInterpolation = TfToken(); + } + + return sdFVLinearInterpolation; } TfToken PxrUsdMayaMeshUtil::setSubdivScheme(const UsdGeomMesh &primSchema, MFnMesh &meshFn, TfToken defaultValue) @@ -294,22 +338,23 @@ TfToken PxrUsdMayaMeshUtil::setSubdivInterpBoundary(const UsdGeomMesh &primSchem return interpBoundary; } -TfToken PxrUsdMayaMeshUtil::setSubdivFVInterpBoundary(const UsdGeomMesh &primSchema, MFnMesh &meshFn) +TfToken PxrUsdMayaMeshUtil::setSubdivFVLinearInterpolation(const UsdGeomMesh &primSchema, MFnMesh &meshFn) { MStatus status; - - TfToken fvInterpBoundary = + + TfToken fvLinearInterpolation = primSchema.GetFaceVaryingLinearInterpolation(); - - if (fvInterpBoundary != UsdGeomTokens->cornersPlus1) { + + if (fvLinearInterpolation != UsdGeomTokens->cornersPlus1) { MFnTypedAttribute stringAttr; MFnStringData stringData; - MObject stringVal = stringData.create(fvInterpBoundary.GetText()); + MObject stringVal = stringData.create(fvLinearInterpolation.GetText()); MObject attr = stringAttr.create(_subdivTokens->USD_faceVaryingInterpolateBoundary.GetText(), "", MFnData::kString, stringVal, &status); if (status == MS::kSuccess) { meshFn.addAttribute(attr); } } - return fvInterpBoundary; + + return fvLinearInterpolation; } diff --git a/third_party/maya/lib/usdMaya/meshUtil.h b/third_party/maya/lib/usdMaya/meshUtil.h index 3aa74c2e2b..49a2ca5584 100644 --- a/third_party/maya/lib/usdMaya/meshUtil.h +++ b/third_party/maya/lib/usdMaya/meshUtil.h @@ -45,8 +45,8 @@ namespace PxrUsdMayaMeshUtil TfToken getSubdivInterpBoundary(const MFnMesh &mesh, TfToken defaultValue); TfToken setSubdivInterpBoundary(const UsdGeomMesh &primSchema, MFnMesh &meshFn, TfToken defaultValue); - TfToken getSubdivFVInterpBoundary(const MFnMesh &mesh); - TfToken setSubdivFVInterpBoundary(const UsdGeomMesh &primSchema, MFnMesh &meshFn); + TfToken getSubdivFVLinearInterpolation(const MFnMesh& mesh); + TfToken setSubdivFVLinearInterpolation(const UsdGeomMesh& primSchema, MFnMesh& meshFn); } // namespace PxrUsdMayaMeshUtil diff --git a/third_party/maya/lib/usdMaya/translatorMesh.cpp b/third_party/maya/lib/usdMaya/translatorMesh.cpp index 7e6203099f..58148d89bf 100644 --- a/third_party/maya/lib/usdMaya/translatorMesh.cpp +++ b/third_party/maya/lib/usdMaya/translatorMesh.cpp @@ -211,7 +211,7 @@ PxrUsdMayaTranslatorMesh::Create( } } else { PxrUsdMayaMeshUtil::setSubdivInterpBoundary(mesh, meshFn, UsdGeomTokens->edgeAndCorner); - PxrUsdMayaMeshUtil::setSubdivFVInterpBoundary(mesh, meshFn); + PxrUsdMayaMeshUtil::setSubdivFVLinearInterpolation(mesh, meshFn); _AssignSubDivTagsToMesh(mesh, meshObj, meshFn); } From 89cbcef9d2814c6e7c049d3df52c1b0244d5b55a Mon Sep 17 00:00:00 2001 From: pixar-oss Date: Thu, 22 Sep 2016 23:55:17 -0700 Subject: [PATCH 162/380] During NURBS conversion, if normalizeNurbs is turned on then we can get a rounding error when the knot vectors are scaled (for example, an order-2 knot vector can look like (-0.99999999999 0 0.99999999999 1.999999999 despite the double precision math). However, the knot ranges are always forced to [0,1] when normalized, so the result is that you can get a uRange or vRange that exceeds the actual knots by some extremely small amount. This results in validation errors downstream in Presto, and currently causes some sort of presto memory corruption (bugs 136704 and 136705) although it seems OK in other parts of the pipeline. This fix is to actually change the boundary knot values so that they do not fall inside the [0,1] normalized range. (Internal change: 1656282) --- .../lib/usdMaya/MayaNurbsSurfaceWriter.cpp | 38 +++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/third_party/maya/lib/usdMaya/MayaNurbsSurfaceWriter.cpp b/third_party/maya/lib/usdMaya/MayaNurbsSurfaceWriter.cpp index 0433bd9943..4fb6712048 100644 --- a/third_party/maya/lib/usdMaya/MayaNurbsSurfaceWriter.cpp +++ b/third_party/maya/lib/usdMaya/MayaNurbsSurfaceWriter.cpp @@ -44,6 +44,38 @@ MayaNurbsSurfaceWriter::MayaNurbsSurfaceWriter( { } +static void +_FixNormalizedKnotRange( + VtArray & knots, + const unsigned int numKnots, + const unsigned int degree, + const double startVal, + const double endVal) +{ + // ensure we've produced valid knot ranges; the data coming + // from Maya is fine but sometimes rounding errors in the normalization + // cause problems. So we change the knots on the boundaries + // (whether single or multiple) to match the u/v range. + double changeVal; + + if (startVal < knots[degree]) { + changeVal = knots[degree]; + for (int i=0; i<=degree; ++i) { + if (knots[i] == changeVal) { + knots[i] = startVal; + } + } + } + if (endVal > knots[numKnots - (degree + 1)]) { + changeVal = knots[numKnots - (degree+1)]; + for (int i=numKnots - (degree+1); i Date: Thu, 22 Sep 2016 23:55:48 -0700 Subject: [PATCH 163/380] When creating a new file via the ofstream wrapper, the temporary file is created by ArchMakeTmpFile, which creates files with permissions 0640, and is then renamed into place. If there is an existing file at the rename destination, the permissions of the temporary file are adjusted to match the destination. However, if no file exists at the destination, the permissions are left as returned by ArchMakeTmpFile, which means that the files are only readable by the owner and group. This change modifies the wrapper to set the permissions for new files to the default file permissions with the current umask applied. This ensures that if the system umask specifies that new files should be readable by others, files created by the wrapper adhere to this. (Internal change: 1656307) --- pxr/base/lib/tf/atomicOfstreamWrapper.cpp | 18 ++++++++++++------ .../lib/tf/testenv/atomicOfstreamWrapper.cpp | 19 +++++++++++++------ 2 files changed, 25 insertions(+), 12 deletions(-) diff --git a/pxr/base/lib/tf/atomicOfstreamWrapper.cpp b/pxr/base/lib/tf/atomicOfstreamWrapper.cpp index ee03d49138..3caf603a56 100644 --- a/pxr/base/lib/tf/atomicOfstreamWrapper.cpp +++ b/pxr/base/lib/tf/atomicOfstreamWrapper.cpp @@ -165,14 +165,20 @@ TfAtomicOfstreamWrapper::Commit( // before calling rename. _stream.close(); - // The default file mode for new files is user r/w and group r/w, subject - // to the process umask. If the file already exists, renaming the - // temporary file results in temporary file permissions, which doesn't - // allow the group to write. - mode_t fileMode = S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP; + // The mode of the temporary file is set by ArchMakeTmpFile, which tries + // to be slightly less restrictive by setting the mode to 0660, whereas + // the underlying temporary file API used by arch creates files with mode + // 0600. When renaming our temporary file into place, we either want the + // permissions to match that of an existing target file, or to be created + // with default permissions modulo umask. + mode_t fileMode = 0; struct stat st; if (stat(_filePath.c_str(), &st) != -1) { - fileMode = st.st_mode & 0777; + fileMode = st.st_mode & DEFFILEMODE; + } else { + const mode_t mask = umask(0); + umask(mask); + fileMode = DEFFILEMODE - mask; } if (chmod(_tmpFilePath.c_str(), fileMode) != 0) { diff --git a/pxr/base/lib/tf/testenv/atomicOfstreamWrapper.cpp b/pxr/base/lib/tf/testenv/atomicOfstreamWrapper.cpp index 397e7eba3e..3488b9e7e9 100644 --- a/pxr/base/lib/tf/testenv/atomicOfstreamWrapper.cpp +++ b/pxr/base/lib/tf/testenv/atomicOfstreamWrapper.cpp @@ -235,6 +235,10 @@ TestAutoCancel() static void TestFilePermissions() { + // Set the umask for this duration of this test to a predictable value. + const mode_t testUmask = 00002; + const mode_t mask = umask(testUmask); + { unlink("testTf_NewFilePerm.txt"); TfAtomicOfstreamWrapper wrapper("testTf_NewFilePerm.txt"); @@ -243,9 +247,9 @@ TestFilePermissions() struct stat st; TF_AXIOM(stat("testTf_NewFilePerm.txt", &st) != -1); - mode_t fileMode = st.st_mode & 0777; - fprintf(stderr, "testTf_NewFilePerm: fileMode = %03o\n", fileMode); - TF_AXIOM(fileMode == (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP)); + mode_t perms = st.st_mode & ACCESSPERMS; + fprintf(stderr, "testTf_NewFilePerm: fileMode = 0%03o\n", perms); + TF_AXIOM(perms == (DEFFILEMODE - testUmask)); } { @@ -253,7 +257,7 @@ TestFilePermissions() int fd = open("testTf_ExistingFilePerm.txt", O_CREAT, S_IRUSR|S_IWUSR); struct stat est; TF_AXIOM(fstat(fd, &est) != -1); - TF_AXIOM((est.st_mode & 0777) == 0600); + TF_AXIOM((est.st_mode & ACCESSPERMS) == (S_IRUSR|S_IWUSR)); close(fd); TfAtomicOfstreamWrapper wrapper("testTf_ExistingFilePerm.txt"); @@ -263,10 +267,13 @@ TestFilePermissions() struct stat st; TF_AXIOM(stat("testTf_ExistingFilePerm.txt", &st) != -1); - mode_t fileMode = st.st_mode & 0777; - fprintf(stderr, "testTf_ExistingFilePerm: fileMode = %03o\n", fileMode); + mode_t fileMode = st.st_mode & ACCESSPERMS; + fprintf(stderr, "testTf_ExistingFilePerm: fileMode = 0%03o\n", fileMode); TF_AXIOM(not (fileMode & (S_IRGRP|S_IWGRP))); } + + // Restore umask to whatever it was. + umask(mask); } static bool From 1490e00844521ec179dea927850c93fecf873aec Mon Sep 17 00:00:00 2001 From: gitamohr Date: Thu, 22 Sep 2016 23:55:55 -0700 Subject: [PATCH 164/380] usdGeom: Fix concurrency bug where we used the stdlibc++ hash_map's [] operator where we didn't intend to modify the hash table. Even though our code guarantees that using [] won't logically mutate the container, the [] implementation speculatively grows the table before attempting to find the element, so it's never safe to invoke concurrently without locking. Use find() instead. (Internal change: 1656375) --- pxr/usd/lib/usdGeom/bboxCache.cpp | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/pxr/usd/lib/usdGeom/bboxCache.cpp b/pxr/usd/lib/usdGeom/bboxCache.cpp index acc1a07369..346d0367c9 100644 --- a/pxr/usd/lib/usdGeom/bboxCache.cpp +++ b/pxr/usd/lib/usdGeom/bboxCache.cpp @@ -172,13 +172,15 @@ class UsdGeomBBoxCache::_MasterBBoxResolver _owner, xfCaches); tbb::task::spawn_root_and_wait(rootTask); - // Update all of the master prims that depended on the completed - // master and dispatch new tasks for those whose dependencies have - // been resolved. - const _MasterTask& masterData = (*masterTasks)[master]; + // Update all of the master prims that depended on the completed master + // and dispatch new tasks for those whose dependencies have been + // resolved. We're guaranteed that all the entries were populated by + // _PopulateTasksForMaster, so we don't check the result of 'find()'. + const _MasterTask& masterData = masterTasks->find(master)->second; BOOST_FOREACH(const UsdPrim& dependentMaster, masterData.dependentMasters) { - _MasterTask& dependentMasterData = (*masterTasks)[dependentMaster]; + _MasterTask& dependentMasterData = + masterTasks->find(dependentMaster)->second; if (dependentMasterData.numDependencies.fetch_and_decrement() == 1){ dispatcher->Run( &_MasterBBoxResolver::_ExecuteTaskForMaster, From a065daf9374699087d6ebfe63f2ba75edddda65a Mon Sep 17 00:00:00 2001 From: spiffmon Date: Thu, 22 Sep 2016 23:56:05 -0700 Subject: [PATCH 165/380] Fix unusual, possibly broken, construction introduced in change a schema-generated header, which does not involve nesting class declarations inside other classes. Caught the current issue because it made doxygen complain. (Internal change: 1656512) --- pxr/usd/lib/usdGeom/mesh.h | 4 ++-- pxr/usd/lib/usdGeom/schema.usda | 4 ++++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/pxr/usd/lib/usdGeom/mesh.h b/pxr/usd/lib/usdGeom/mesh.h index d666ef932f..e5cac7482c 100644 --- a/pxr/usd/lib/usdGeom/mesh.h +++ b/pxr/usd/lib/usdGeom/mesh.h @@ -31,6 +31,8 @@ #include "pxr/usd/usd/stage.h" #include "pxr/usd/usdGeom/tokens.h" +#include "pxr/usd/usd/timeCode.h" + #include "pxr/base/vt/value.h" #include "pxr/base/gf/vec3d.h" @@ -417,8 +419,6 @@ class UsdGeomMesh : public UsdGeomPointBased // ===================================================================== // // --(BEGIN CUSTOM CODE)-- -#include "pxr/usd/usd/timeCode.h" - public: /// \var const float SHARPNESS_INFINITE /// As an element of a 'creaseSharpness' or 'cornerSharpness' array, diff --git a/pxr/usd/lib/usdGeom/schema.usda b/pxr/usd/lib/usdGeom/schema.usda index 47894c1cec..20cee71da0 100644 --- a/pxr/usd/lib/usdGeom/schema.usda +++ b/pxr/usd/lib/usdGeom/schema.usda @@ -683,6 +683,10 @@ class "PointBased" ( class Mesh "Mesh" ( inherits = + customData = { + string extraIncludes = """ +#include "pxr/usd/usd/timeCode.h" """ + } doc="""Encodes a mesh surface whose definition and feature-set will converge with that of OpenSubdiv, http://graphics.pixar.com/opensubdiv/docs/subdivision_surfaces.html. Current exceptions/divergences include: From 97d601d40f66cc5afbf1bc21f8e7d7b175b81c70 Mon Sep 17 00:00:00 2001 From: mrawde Date: Thu, 22 Sep 2016 23:56:27 -0700 Subject: [PATCH 166/380] Reverting shaderAdapter extensibility. (Internal change: 1656527) --- pxr/usdImaging/lib/usdImaging/delegate.cpp | 16 ---------------- pxr/usdImaging/lib/usdImaging/delegate.h | 4 ---- pxr/usdImaging/lib/usdImaging/primAdapter.h | 6 +----- 3 files changed, 1 insertion(+), 25 deletions(-) diff --git a/pxr/usdImaging/lib/usdImaging/delegate.cpp b/pxr/usdImaging/lib/usdImaging/delegate.cpp index 0424b1c9a8..e38fa1b6bb 100644 --- a/pxr/usdImaging/lib/usdImaging/delegate.cpp +++ b/pxr/usdImaging/lib/usdImaging/delegate.cpp @@ -259,11 +259,6 @@ UsdImagingDelegate::_ShaderAdapterSharedPtr UsdImagingDelegate::_ShaderAdapterLookup( SdfPath const& shaderId) const { - auto it = _shaderAdapterMap.find(shaderId); - if (it != _shaderAdapterMap.end()) { - return it->second; - } - return _defaultShaderAdapter; } @@ -491,17 +486,6 @@ UsdImagingIndexProxy::AddDependency(SdfPath const& usdPath, _delegate->_pathAdapterMap[usdPath] = adapterToInsert; } -void -UsdImagingIndexProxy::AddShaderAdapter( - SdfPath const& shaderId, - UsdImagingShaderAdapterSharedPtr const& shaderAdapter) -{ - TF_DEBUG(USDIMAGING_SHADERS).Msg( - "Registering shader adapter for %s\n", shaderId.GetText()); - - _delegate->_shaderAdapterMap[shaderId] = shaderAdapter; -} - void UsdImagingIndexProxy::_AddTask(SdfPath const& usdPath) { diff --git a/pxr/usdImaging/lib/usdImaging/delegate.h b/pxr/usdImaging/lib/usdImaging/delegate.h index b8819710d3..4d2a026d3e 100644 --- a/pxr/usdImaging/lib/usdImaging/delegate.h +++ b/pxr/usdImaging/lib/usdImaging/delegate.h @@ -620,10 +620,6 @@ class UsdImagingIndexProxy { UsdImagingPrimAdapterSharedPtr const& adapter = UsdImagingPrimAdapterSharedPtr()); - /// \brief Register a \p shaderAdapter to handle the shader at \p shaderId. - void AddShaderAdapter(SdfPath const& shaderId, - UsdImagingShaderAdapterSharedPtr const& shaderAdapter); - SdfPath InsertMesh(SdfPath const& usdPath, SdfPath const& shaderBinding, UsdImagingInstancerContext const* instancerContext); diff --git a/pxr/usdImaging/lib/usdImaging/primAdapter.h b/pxr/usdImaging/lib/usdImaging/primAdapter.h index 381b158dde..dd5921de0a 100644 --- a/pxr/usdImaging/lib/usdImaging/primAdapter.h +++ b/pxr/usdImaging/lib/usdImaging/primAdapter.h @@ -189,11 +189,7 @@ class UsdImagingPrimAdapter /// Gets the shader binding for the given prim, walking up namespace if /// necessary. - /// - /// This returns a usdPath to a shaderPrim. If you want to override the - /// default shaderAdapter, use UsdImagingIndexProxy::AddShaderAdapter to - /// register a new adapter for the path returned here. - virtual SdfPath GetShaderBinding(UsdPrim const& prim); + SdfPath GetShaderBinding(UsdPrim const& prim); /// Gets the instancer ID for the given prim and instancerContext. SdfPath GetInstancerBinding(UsdPrim const& prim, From 2f055b4d28c4a21a55a52ea1856ca593da2fce59 Mon Sep 17 00:00:00 2001 From: superfunc Date: Thu, 22 Sep 2016 23:56:37 -0700 Subject: [PATCH 167/380] [UsdUtils] Add the ability to specify endTimeCode to stitchClips. This is a staging change for allowing stitchClips to author template metadata. (Internal change: 1656546) --- pxr/usd/bin/usdstitchclips/usdstitchclips.py | 8 +++- pxr/usd/lib/usdUtils/stitchClips.cpp | 32 +++++++++------ pxr/usd/lib/usdUtils/stitchClips.h | 12 +++++- pxr/usd/lib/usdUtils/wrapStitchClips.cpp | 42 ++++++++------------ 4 files changed, 52 insertions(+), 42 deletions(-) diff --git a/pxr/usd/bin/usdstitchclips/usdstitchclips.py b/pxr/usd/bin/usdstitchclips/usdstitchclips.py index c532201344..29fa45156d 100644 --- a/pxr/usd/bin/usdstitchclips/usdstitchclips.py +++ b/pxr/usd/bin/usdstitchclips/usdstitchclips.py @@ -43,6 +43,8 @@ help='''specify a prim path to stitch clip data at. ''') parser.add_argument('-s', '--startTimeCode', action='store', help='specify a start time') +parser.add_argument('-e', '--endTimeCode', action='store', + help='specify an end time') parser.add_argument('-r', '--reuseExistingTopology', action='store_true', help='Pre-existing topology layer named ' @@ -72,8 +74,12 @@ if results.startTimeCode: results.startTimeCode = float(results.startTimeCode) + if results.endTimeCode: + results.endTimeCode = float(results.endTimeCode) + UsdUtils.StitchClips(outLayer, results.usdFiles, results.clipPath, - results.reuseExistingTopology, results.startTimeCode) + results.reuseExistingTopology, results.startTimeCode, + results.endTimeCode) if not results.noComment: outLayer.comment = 'Generated with ' + ' '.join(sys.argv) diff --git a/pxr/usd/lib/usdUtils/stitchClips.cpp b/pxr/usd/lib/usdUtils/stitchClips.cpp index 8b636728be..c9a55c52d8 100644 --- a/pxr/usd/lib/usdUtils/stitchClips.cpp +++ b/pxr/usd/lib/usdUtils/stitchClips.cpp @@ -508,7 +508,7 @@ namespace { } // This allows one to set the start and end frame data in - // a \p modelClipLayer, based on model clip data contained at + // a \p resultLayer, based on model clip data contained at // \p stitchPath. This function will take the minimum available // startTimeCode(unless one is supplied) from inside of the clipTimes at the // \p stitchPath and the maximum available endTimeCode. @@ -516,21 +516,22 @@ namespace { // Note: if the prim at \p stitchPath has no clip data, neither the start // nor end frame will be set by this operations void - _SetTimeCodeRange(const SdfLayerHandle& modelClipLayer, + _SetTimeCodeRange(const SdfLayerHandle& resultLayer, const SdfPath& clipDataPath, - double startTimeCode) + double startTimeCode, + double endTimeCode) { // it is a coding error to look up clip data in a non-existent path - if (not modelClipLayer->GetPrimAtPath(clipDataPath)) { + if (not resultLayer->GetPrimAtPath(clipDataPath)) { TF_CODING_ERROR("Invalid prim in path: @%s@<%s>", - modelClipLayer->GetIdentifier().c_str(), + resultLayer->GetIdentifier().c_str(), clipDataPath.GetString().c_str()); return; } // obtain the current set of clip times VtVec2dArray currentClipTimes - = _GetUnboxedValue(modelClipLayer, + = _GetUnboxedValue(resultLayer, clipDataPath, clipTimeKey); @@ -546,12 +547,15 @@ namespace { } // grab the min at the front and max at the back - double endTimeCode = (*currentClipTimes.rbegin())[0]; - modelClipLayer->SetEndTimeCode(endTimeCode); + if (endTimeCode == TIME_MAX) { + endTimeCode = (*currentClipTimes.rbegin())[0]; + } + resultLayer->SetEndTimeCode(endTimeCode); + if (startTimeCode == TIME_MAX) { startTimeCode = (*currentClipTimes.begin())[0]; } - modelClipLayer->SetStartTimeCode(startTimeCode); + resultLayer->SetStartTimeCode(startTimeCode); } // Generates a toplogy file name based on an input file name @@ -726,10 +730,11 @@ namespace { const SdfLayerRefPtr& topologyLayer, const SdfLayerRefPtrVector& clipLayers, const SdfPath& clipPath, - const double startTimeCode) + const double startTimeCode, + const double endTimeCode) { _StitchLayers(resultLayer, topologyLayer, clipLayers, clipPath); - _SetTimeCodeRange(resultLayer, clipPath, startTimeCode); + _SetTimeCodeRange(resultLayer, clipPath, startTimeCode, endTimeCode); topologyLayer->Save(); resultLayer->Save(); @@ -819,7 +824,8 @@ UsdUtilsStitchClips(const SdfLayerHandle& resultLayer, const _ClipFileVector& clipLayerFiles, const SdfPath& clipPath, const bool reuseExistingTopology, - const double startTimeCode) + const double startTimeCode, + const double endTimeCode) { // XXX: See comment in UsdUtilsStitchClipsTopology above. TF_PY_ALLOW_THREADS_IN_SCOPE(); @@ -847,5 +853,5 @@ UsdUtilsStitchClips(const SdfLayerHandle& resultLayer, } return _UsdUtilsStitchClipsImpl(resultLayer, topologyLayer, clipLayers, - clipPath, startTimeCode); + clipPath, startTimeCode, endTimeCode); } diff --git a/pxr/usd/lib/usdUtils/stitchClips.h b/pxr/usd/lib/usdUtils/stitchClips.h index 4b009a2a21..76edc29414 100644 --- a/pxr/usd/lib/usdUtils/stitchClips.h +++ b/pxr/usd/lib/usdUtils/stitchClips.h @@ -54,7 +54,13 @@ SDF_DECLARE_HANDLES(SdfLayer); /// \p startTimeCode The first time coordinate for the rootLayer /// to point to. If none is provided, it will be /// the lowest startTimeCode available from -/// the \p clipLayers +/// the \p clipLayers. +/// +/// \p endTimeCode The last time coordinate for the rootLayer to +/// point to. If none is provided, it will be the +/// highest endTimeCode authored from the +/// \p clipLayers. +/// /// /// Details on how this is accomplished can be found below: /// @@ -86,7 +92,7 @@ SDF_DECLARE_HANDLES(SdfLayer); /// clipManifestAssetPath, clipActive etc. at the specified \p clipPath. /// The resultLayer will also have timeCode range data, such as start and end /// timeCodes written to it, with the starting position being provided by -/// \p startTimeCode. +/// \p startTimeCode and the ending provided by \p endTimeCode. /// /// Note: an invalid clip path(because the prim doesn't exist in /// the aggregate topologyLayer) will result in a TF_CODING_ERROR. @@ -100,6 +106,8 @@ UsdUtilsStitchClips(const SdfLayerHandle& resultLayer, const bool reuseExistingTopology = true, const double startTimeCode + = std::numeric_limits::max(), + const double endTimeCode = std::numeric_limits::max()); /// A function which aggregates the topology of a set of \p clipLayerFiles diff --git a/pxr/usd/lib/usdUtils/wrapStitchClips.cpp b/pxr/usd/lib/usdUtils/wrapStitchClips.cpp index 90c394ce29..47b6e2b77f 100644 --- a/pxr/usd/lib/usdUtils/wrapStitchClips.cpp +++ b/pxr/usd/lib/usdUtils/wrapStitchClips.cpp @@ -33,29 +33,15 @@ using namespace boost::python; -// A wrapper to clean up the python API, allowing users to pass in None -// and have it default to the no-stage-frame-supplied case -double -_ConvertStartFrame(const boost::python::object pyStartFrame) +template +T +_ConvertWithDefault(const boost::python::object obj, const T& def) { - double startFrame; - if (not TfPyIsNone(pyStartFrame)) { - startFrame = extract(pyStartFrame); - } else { - startFrame = std::numeric_limits::max(); - } - - return startFrame; -} - -bool -_ConvertReuseTopology(const boost::python::object pyReuseTopology) -{ - if (not TfPyIsNone(pyReuseTopology)) { - return extract(pyReuseTopology); - } else { - return true; - } + if (not TfPyIsNone(obj)) { + return extract(obj); + } + + return def; } void @@ -63,11 +49,14 @@ _ConvertStitchClips(const SdfLayerHandle& resultLayer, const std::vector& clipLayerFiles, const SdfPath& clipPath, const boost::python::object reuseExistingTopology, - const boost::python::object pyStartFrame) + const boost::python::object pyStartFrame, + const boost::python::object pyEndFrame) { + constexpr double dmax = std::numeric_limits::max(); UsdUtilsStitchClips(resultLayer, clipLayerFiles, clipPath, - _ConvertReuseTopology(reuseExistingTopology), - _ConvertStartFrame(pyStartFrame)); + _ConvertWithDefault(reuseExistingTopology, true), + _ConvertWithDefault(pyStartFrame, dmax), + _ConvertWithDefault(pyEndFrame, dmax)); } void _ConvertStitchClipsToplogy(const SdfLayerHandle& topologyLayer, @@ -85,7 +74,8 @@ wrapStitchClips() arg("clipLayerFiles"), arg("clipPath"), arg("reuseExistingTopology")=boost::python::object(), - arg("startFrame")=boost::python::object())); + arg("startFrame")=boost::python::object(), + arg("endFrame")=boost::python::object())); def("StitchClipsTopology", _ConvertStitchClipsToplogy, From bdee72bfca90f606c643aa609c9be2949d427a05 Mon Sep 17 00:00:00 2001 From: mattyjams Date: Thu, 22 Sep 2016 23:56:50 -0700 Subject: [PATCH 168/380] add support for importing indexed Float2Array primvars as sparsely authored UV sets (Internal change: 1656786) --- .../maya/lib/usdMaya/translatorMesh.cpp | 16 +- third_party/maya/lib/usdMaya/translatorMesh.h | 32 ++- .../lib/usdMaya/translatorMesh_PrimVars.cpp | 237 ++++++++++-------- third_party/maya/lib/usdMaya/usdImport.cpp | 17 +- 4 files changed, 178 insertions(+), 124 deletions(-) diff --git a/third_party/maya/lib/usdMaya/translatorMesh.cpp b/third_party/maya/lib/usdMaya/translatorMesh.cpp index 58148d89bf..68945cfa37 100644 --- a/third_party/maya/lib/usdMaya/translatorMesh.cpp +++ b/third_party/maya/lib/usdMaya/translatorMesh.cpp @@ -249,17 +249,13 @@ PxrUsdMayaTranslatorMesh::Create( } } - // If Vec2f, we assume are UVs if (typeName == SdfValueTypeNames->Float2Array) { - if (interpolation == UsdGeomTokens->vertex || - interpolation == UsdGeomTokens->faceVarying) { - if (_AssignUVSetPrimvarToMesh(primvar, meshFn)==false) { - MGlobal::displayWarning(TfStringPrintf("Unable to retrieve and assign data for UVSet <%s> on mesh <%s>", - name.GetText(), mesh.GetPrim().GetPath().GetText()).c_str()); - } - } else { - MGlobal::displayWarning(TfStringPrintf("UVSet <%s> on mesh <%s> has to be vertex of facevarying", - name.GetText(), mesh.GetPrim().GetPath().GetText()).c_str()); + // We assume that Float2Array primvars are UV sets. + if (not _AssignUVSetPrimvarToMesh(primvar, meshFn)) { + MGlobal::displayWarning( + TfStringPrintf("Unable to retrieve and assign data for UV set <%s> on mesh <%s>", + name.GetText(), + mesh.GetPrim().GetPath().GetText()).c_str()); } } else if (interpolation == UsdGeomTokens->vertex || interpolation == UsdGeomTokens->faceVarying || diff --git a/third_party/maya/lib/usdMaya/translatorMesh.h b/third_party/maya/lib/usdMaya/translatorMesh.h index b8001944c1..d47d19cd41 100644 --- a/third_party/maya/lib/usdMaya/translatorMesh.h +++ b/third_party/maya/lib/usdMaya/translatorMesh.h @@ -21,23 +21,27 @@ // KIND, either express or implied. See the Apache License for the specific // language governing permissions and limitations under the Apache License. // + +/// \file translatorMesh.h + #ifndef PXRUSDMAYA_TRANSLATOR_MESH_H #define PXRUSDMAYA_TRANSLATOR_MESH_H -#include "usdMaya/primReaderContext.h" #include "usdMaya/primReaderArgs.h" +#include "usdMaya/primReaderContext.h" #include "pxr/usd/usdGeom/mesh.h" #include "pxr/usd/usdGeom/primvar.h" -#include -#include #include +#include +#include + /// \brief Provides helper functions for creating UsdGeomMesh struct PxrUsdMayaTranslatorMesh { - // Creates a MFnMesh under \p parentNode from \p mesh. + /// Creates an MFnMesh under \p parentNode from \p mesh. static bool Create( const UsdGeomMesh& mesh, MObject parentNode, @@ -45,10 +49,24 @@ struct PxrUsdMayaTranslatorMesh PxrUsdMayaPrimReaderContext* context); private: - static bool _AssignSubDivTagsToMesh( const UsdGeomMesh &primSchema, MObject &meshObj, MFnMesh &meshFn); - static bool _AssignUVSetPrimvarToMesh( const UsdGeomPrimvar &primvar, MFnMesh &meshFn); - static bool _AssignColorSetPrimvarToMesh( const UsdGeomMesh &primSchema, const UsdGeomPrimvar &primvar, MFnMesh &meshFn, MIntArray &polygonCounts, MIntArray &polygonConnects, MFnMesh::MColorRepresentation colorRep); + static bool _AssignSubDivTagsToMesh( + const UsdGeomMesh& primSchema, + MObject& meshObj, + MFnMesh& meshFn); + + static bool _AssignUVSetPrimvarToMesh( + const UsdGeomPrimvar& primvar, + MFnMesh& meshFn); + + static bool _AssignColorSetPrimvarToMesh( + const UsdGeomMesh& primSchema, + const UsdGeomPrimvar& primvar, + MFnMesh& meshFn, + MIntArray& polygonCounts, + MIntArray& polygonConnects, + MFnMesh::MColorRepresentation colorRep); }; + #endif // PXRUSDMAYA_TRANSLATOR_MESH_H diff --git a/third_party/maya/lib/usdMaya/translatorMesh_PrimVars.cpp b/third_party/maya/lib/usdMaya/translatorMesh_PrimVars.cpp index 26cd2304c1..6a5b9bd8af 100644 --- a/third_party/maya/lib/usdMaya/translatorMesh_PrimVars.cpp +++ b/third_party/maya/lib/usdMaya/translatorMesh_PrimVars.cpp @@ -22,130 +22,171 @@ // language governing permissions and limitations under the Apache License. // #include "usdMaya/translatorMesh.h" + #include "usdMaya/util.h" #include "pxr/base/gf/gamma.h" #include "pxr/base/gf/math.h" -#include "pxr/base/gf/transform.h" -#include "pxr/usd/usd/stage.h" -#include "pxr/usd/usd/inherits.h" -#include "pxr/usd/usdGeom/primvar.h" +#include "pxr/base/gf/vec2f.h" +#include "pxr/base/gf/vec3f.h" +#include "pxr/base/gf/vec4f.h" +#include "pxr/base/vt/array.h" #include "pxr/usd/usdGeom/mesh.h" -#include "pxr/usd/usdGeom/scope.h" +#include "pxr/usd/usdGeom/primvar.h" #include "pxr/usd/usdUtils/pipeline.h" -#include #include #include #include +#include + -static bool computeVertexIndices(MFnMesh &meshFn, MIntArray &valuesPerPolygon, MIntArray &valueIndexes, MIntArray &remapIndexes, TfToken interpolation) +/* static */ +bool +PxrUsdMayaTranslatorMesh::_AssignUVSetPrimvarToMesh( + const UsdGeomPrimvar& primvar, + MFnMesh& meshFn) { - MIntArray meshIdxRemap; - meshFn.getVertices(valuesPerPolygon, meshIdxRemap); - int numFaceVertices = meshFn.numFaceVertices(); - valueIndexes.setLength(numFaceVertices); - int vertexIndex; - for (int i=0; i < numFaceVertices; i++) { - if (interpolation == UsdGeomTokens->vertex) { - vertexIndex=meshIdxRemap[i]; - } else { - vertexIndex=i; - } - if (remapIndexes.length()>0) { - valueIndexes.set(remapIndexes[vertexIndex],i); - } else { - valueIndexes.set(vertexIndex,i); - } + const TfToken& primvarName = primvar.GetBaseName(); + + // Get the raw data before applying any indexing. + VtVec2fArray uvValues; + if (not primvar.Get(&uvValues) or uvValues.empty()) { + MGlobal::displayWarning( + TfStringPrintf("Could not read UV values from primvar '%s' on mesh: %s", + primvarName.GetText(), + meshFn.fullPathName().asChar()).c_str()); + return false; } - return true; -} -static bool findCoincidentUVCoord(MFloatArray &uCoords, MFloatArray &vCoords, size_t uvCoordsArraySize, float newU, float newV, size_t *foundIdx) -{ - for (size_t i=0;i uvValues, MFloatArray &uCoords, MFloatArray &vCoords, MIntArray &remapIndexes) -{ - uCoords.setLength(uvValues.size()); - vCoords.setLength(uvValues.size()); - remapIndexes.setLength(uvValues.size()); - size_t i=0, uvCoordsArraySize=0, foundIdx=0; - TF_FOR_ALL(vec, uvValues) { - if (findCoincidentUVCoord(uCoords, vCoords, uvCoordsArraySize, (*vec)[0], (*vec)[1], &foundIdx)) { - remapIndexes[i]=foundIdx; - } else { - uCoords[uvCoordsArraySize] = (*vec)[0]; - vCoords[uvCoordsArraySize] = (*vec)[1]; - remapIndexes[i]=uvCoordsArraySize; - uvCoordsArraySize++; + // uCoords and vCoords now store all of the values and any unassigned + // components have had their indices set to -1, so update the unauthored + // values index. + unauthoredValuesIndex = -1; + + MStatus status; + MString uvSetName(primvarName.GetText()); + if (primvarName == UsdUtilsGetPrimaryUVSetName()) { + // We assume that the primary USD UV set maps to Maya's default 'map1' + // set which always exists, so we shouldn't try to create it. + uvSetName = "map1"; + } else { + status = meshFn.createUVSet(uvSetName); + if (status != MS::kSuccess) { + MGlobal::displayWarning( + TfStringPrintf("Unable to create UV set '%s' for mesh: %s", + uvSetName.asChar(), + meshFn.fullPathName().asChar()).c_str()); + return false; } - i++; } - TF_VERIFY(i == uvValues.size()); - uCoords.setLength(uvCoordsArraySize); - vCoords.setLength(uvCoordsArraySize); -} -/* static */ -bool -PxrUsdMayaTranslatorMesh::_AssignUVSetPrimvarToMesh( const UsdGeomPrimvar &primvar, MFnMesh &meshFn) -{ - TfToken name, interpolation; - SdfValueTypeName typeName; - int elementSize; - primvar.GetDeclarationInfo(&name, &typeName, &interpolation, &elementSize); + // Create UVs on the mesh from the values we collected out of the primvar. + // We'll assign mesh components to these values below. + status = meshFn.setUVs(uCoords, vCoords, &uvSetName); + if (status != MS::kSuccess) { + MGlobal::displayWarning( + TfStringPrintf("Unable to set UV data on UV set '%s' for mesh: %s", + uvSetName.asChar(), + meshFn.fullPathName().asChar()).c_str()); + return false; + } - VtVec2fArray rawVal; - if (primvar.ComputeFlattened(&rawVal, UsdTimeCode::Default())) { - MFloatArray uCoords; - MFloatArray vCoords; - MIntArray remapIndexes; - // Compress coincident UV points to preserve editability in maya - compressUVValues(rawVal, uCoords, vCoords, remapIndexes); - MString uvSetName(name.GetText()); - MStatus status; - // We assume that the st UV set is the first UV set in maya called map1 - if (uvSetName=="st") { - uvSetName="map1"; - status = MS::kSuccess; - } else { - status = meshFn.createUVSet(uvSetName); + const TfToken& interpolation = primvar.GetInterpolation(); + + // Iterate through the mesh's face vertices assigning UV values to them. + MItMeshFaceVertex itFV(meshFn.object()); + unsigned int fvi = 0; + for (itFV.reset(); not itFV.isDone(); itFV.next(), ++fvi) { + int faceId = itFV.faceId(); + int vertexId = itFV.vertId(); + int faceVertexId = itFV.faceVertId(); + + // Primvars with constant or uniform interpolation are not really + // meaningful as UV sets, but we support them anyway. + int uvId = 0; + if (interpolation == UsdGeomTokens->constant) { + uvId = 0; + } else if (interpolation == UsdGeomTokens->uniform) { + uvId = faceId; + } else if (interpolation == UsdGeomTokens->vertex) { + uvId = vertexId; + } else if (interpolation == UsdGeomTokens->faceVarying) { + uvId = fvi; } - if (status == MS::kSuccess) { - status = meshFn.setUVs(uCoords, vCoords, &uvSetName ); - if (status == MS::kSuccess) { - MIntArray valuesPerPolygon; - MIntArray valueIndexes; - if (computeVertexIndices(meshFn, valuesPerPolygon, valueIndexes, remapIndexes, interpolation)) { - status = meshFn.assignUVs(valuesPerPolygon, valueIndexes, &uvSetName); - if (status != MS::kSuccess) { - MGlobal::displayWarning(TfStringPrintf("Unable to assign UV set <%s> to mesh", name.GetText()).c_str()); - } else { - return true; - } - } else { - MGlobal::displayWarning(TfStringPrintf("Unable to computeVertexIndices on UV set <%s>", name.GetText()).c_str()); - } - } else { - MGlobal::displayWarning(TfStringPrintf("Unable to set UV data on <%s>", name.GetText()).c_str()); + + if (uvId < assignmentIndices.size()) { + // The data is indexed, so consult the indices array for the + // correct index into the data. + uvId = assignmentIndices[uvId]; + + if (uvId == unauthoredValuesIndex) { + // This component had no authored value, so skip it. + continue; } - } else { - MGlobal::displayWarning(TfStringPrintf("Unable to create UV <%s>", name.GetText()).c_str()); } - } else { - MGlobal::displayWarning(TfStringPrintf("Primvar <%s> doesn't hold an array of Vec2f", name.GetText()).c_str()); + + status = meshFn.assignUV(faceId, faceVertexId, uvId, &uvSetName); + if (status != MS::kSuccess) { + MGlobal::displayWarning( + TfStringPrintf("Could not assign UV value to UV set '%s' on mesh: %s", + uvSetName.asChar(), + meshFn.fullPathName().asChar()).c_str()); + return false; + } } - return false; + return true; } /* static */ diff --git a/third_party/maya/lib/usdMaya/usdImport.cpp b/third_party/maya/lib/usdMaya/usdImport.cpp index 771a36f660..e38c026c24 100644 --- a/third_party/maya/lib/usdMaya/usdImport.cpp +++ b/third_party/maya/lib/usdMaya/usdImport.cpp @@ -132,16 +132,15 @@ MStatus usdImport::doIt(const MArgList & args) if (shadingMode.IsEmpty()) { jobArgs.shadingMode = PxrUsdMayaShadingModeTokens->displayColor; - } - else { - if (PxrUsdMayaShadingModeRegistry::GetInstance().GetExporter(shadingMode)) { - jobArgs.shadingMode = shadingMode; - } - else { - MGlobal::displayError(TfStringPrintf("No shadingMode '%s' found. Setting shadingMode='none'", - shadingMode.GetText()).c_str()); - jobArgs.shadingMode = PxrUsdMayaShadingModeTokens->none; + } else if (PxrUsdMayaShadingModeRegistry::GetInstance().GetImporter(shadingMode)) { + jobArgs.shadingMode = shadingMode; + } else { + if (shadingMode != PxrUsdMayaShadingModeTokens->none) { + MGlobal::displayError( + TfStringPrintf("No shadingMode '%s' found. Setting shadingMode='none'", + shadingMode.GetText()).c_str()); } + jobArgs.shadingMode = PxrUsdMayaShadingModeTokens->none; } } From e7518516f61577250aedf27d5944530246a89e40 Mon Sep 17 00:00:00 2001 From: comand Date: Thu, 22 Sep 2016 23:59:38 -0700 Subject: [PATCH 169/380] Add pxr/base/tf/pyAnnotatedBoolResult. (Internal change: 1656801) --- pxr/base/lib/tf/module.cpp | 1 + pxr/base/lib/tf/pyAnnotatedBoolResult.cpp | 1 + pxr/base/lib/tf/pyAnnotatedBoolResult.h | 101 ++++++++++++++++++ .../lib/tf/wrapTestPyAnnotatedBoolResult.cpp | 50 +++++++++ 4 files changed, 153 insertions(+) create mode 100644 pxr/base/lib/tf/pyAnnotatedBoolResult.cpp create mode 100644 pxr/base/lib/tf/pyAnnotatedBoolResult.h create mode 100644 pxr/base/lib/tf/wrapTestPyAnnotatedBoolResult.cpp diff --git a/pxr/base/lib/tf/module.cpp b/pxr/base/lib/tf/module.cpp index 2313431184..4aaf3c167b 100644 --- a/pxr/base/lib/tf/module.cpp +++ b/pxr/base/lib/tf/module.cpp @@ -56,6 +56,7 @@ TF_WRAP_MODULE { TF_WRAP( TimeStamp ); TF_WRAP( Token ); TF_WRAP( Type ); + TF_WRAP( Tf_TestPyAnnotatedBoolResult ); TF_WRAP( Tf_TestPyContainerConversions ); TF_WRAP( Tf_TestPyDateTime ); TF_WRAP( Tf_TestPyStaticTokens ); diff --git a/pxr/base/lib/tf/pyAnnotatedBoolResult.cpp b/pxr/base/lib/tf/pyAnnotatedBoolResult.cpp new file mode 100644 index 0000000000..1eb8344274 --- /dev/null +++ b/pxr/base/lib/tf/pyAnnotatedBoolResult.cpp @@ -0,0 +1 @@ +#include "pxr/base/tf/pyAnnotatedBoolResult.h" diff --git a/pxr/base/lib/tf/pyAnnotatedBoolResult.h b/pxr/base/lib/tf/pyAnnotatedBoolResult.h new file mode 100644 index 0000000000..186ee684cd --- /dev/null +++ b/pxr/base/lib/tf/pyAnnotatedBoolResult.h @@ -0,0 +1,101 @@ +#ifndef TF_PYANNOTATEDBOOLRESULT_H +#define TF_PYANNOTATEDBOOLRESULT_H + +#include "pxr/base/tf/pyLock.h" +#include "pxr/base/tf/pyUtils.h" + +#include +#include +#include +#include + +#include + +template +struct TfPyAnnotatedBoolResult : + boost::equality_comparable, bool> +{ + TfPyAnnotatedBoolResult() {} + + TfPyAnnotatedBoolResult(bool val, Annotation const &annotation) : + _val(val), _annotation(annotation) {} + + bool GetValue() const { + return _val; + } + + Annotation const &GetAnnotation() const { + return _annotation; + } + + std::string GetRepr() const { + return GetValue() ? "True" : + "(False, " + TfPyRepr(GetAnnotation()) + ")"; + } + + /// Returns \c true if the result is the same as \p rhs. + bool operator==(bool rhs) const { + return _val == rhs; + } + + template + static boost::python::class_ + Wrap(char const *name, char const *annotationName) { + typedef TfPyAnnotatedBoolResult This; + using namespace boost::python; + TfPyLock lock; + return class_(name, no_init) + .def("__nonzero__", &Derived::GetValue) + .def("__repr__", &Derived::GetRepr) + .def(self == bool()) + .def(self != bool()) + .def(bool() == self) + .def(bool() != self) + // Use a helper function. We'd like to def_readonly the + // _annotation member but there are two problems with that. + // First, we can't control the return_value_policy and if the + // Annotation type has a custom to-Python converter then the + // def_readonly return_value_policy of return_internal_reference + // won't work since the object needs conversion. Second, if we + // try to use GetAnnotation() with add_property then we'll get + // a failure at runtime because Python has a Derived but + // GetAnnotation takes a TfPyAnnotatedBoolResult + // and boost python doesn't know the former is-a latter because + // TfPyAnnotatedBoolResult is not wrapped. + // + // So we provide a templated static method that takes a Derived + // and returns Annotation by value. We can add_property that + // with no problem. + .add_property(annotationName, &This::_GetAnnotation) + ; + } + +private: + // Helper function for wrapper. + template + static Annotation _GetAnnotation(const Derived& x) + { + return x.GetAnnotation(); + } + +private: + bool _val; + Annotation _annotation; + +}; + +/// Returns \c true if the result of \p lhs is the same as \p rhs. +template +bool operator==(bool lhs, TfPyAnnotatedBoolResult& rhs) +{ + return rhs == lhs; +} + +/// Returns \c false if the result of \p lhs is the same as \p rhs. +template +bool operator!=(bool lhs, TfPyAnnotatedBoolResult& rhs) +{ + return rhs != lhs; +} + +#endif // TF_PYANNOTATEDBOOLRESULT_H diff --git a/pxr/base/lib/tf/wrapTestPyAnnotatedBoolResult.cpp b/pxr/base/lib/tf/wrapTestPyAnnotatedBoolResult.cpp new file mode 100644 index 0000000000..a2d3134443 --- /dev/null +++ b/pxr/base/lib/tf/wrapTestPyAnnotatedBoolResult.cpp @@ -0,0 +1,50 @@ +// +// 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. +// + +#include "pxr/base/tf/pyAnnotatedBoolResult.h" +#include +#include + +using namespace boost::python; + +struct Tf_TestAnnotatedBoolResult : TfPyAnnotatedBoolResult { + Tf_TestAnnotatedBoolResult(bool value, const std::string& annotation) + : TfPyAnnotatedBoolResult(value, annotation) { } +}; + +static Tf_TestAnnotatedBoolResult +_TestAnnotatedBoolResult( + bool value, + const std::string& annotation) +{ + return Tf_TestAnnotatedBoolResult(value, annotation); +} + +void wrapTf_TestPyAnnotatedBoolResult() +{ + def("_TestAnnotatedBoolResult", &_TestAnnotatedBoolResult); + + Tf_TestAnnotatedBoolResult::Wrap( + "Tf_TestAnnotatedBoolResult", "annotation"); +} From b118b176c9ce6ef2555e87c2e840ebf4750dec24 Mon Sep 17 00:00:00 2001 From: comand Date: Fri, 23 Sep 2016 00:00:01 -0700 Subject: [PATCH 170/380] IsValidPathString returns a TfPyAnnotatedBoolResult once more, now that TfPyAnnotatedBoolResult is available in tf. (Internal change: 1656803) --- pxr/usd/lib/sdf/wrapPath.cpp | 29 +++++++++++------------------ 1 file changed, 11 insertions(+), 18 deletions(-) diff --git a/pxr/usd/lib/sdf/wrapPath.cpp b/pxr/usd/lib/sdf/wrapPath.cpp index 2a45922e6b..082f43997c 100644 --- a/pxr/usd/lib/sdf/wrapPath.cpp +++ b/pxr/usd/lib/sdf/wrapPath.cpp @@ -22,6 +22,7 @@ // language governing permissions and limitations under the Apache License. // #include "pxr/usd/sdf/path.h" +#include "pxr/base/tf/pyAnnotatedBoolResult.h" #include "pxr/base/tf/pyResultConversions.h" #include "pxr/base/tf/pyContainerConversions.h" #include "pxr/base/tf/hash.h" @@ -87,27 +88,19 @@ _FindLongestPrefix(SdfPathVector const &paths, SdfPath const &path) return object(*result); } -// XXX TODO: -// In order to accommodate this code moving to amber, CtfPyAnnotatedBoolResult -// would need to be moved to pxr/base/tf. This is a a medium sized move; -// I'm deferring that to later to get this into the build now so that -// refactoring can move forward. We should revisit this. - -// struct Sdf_PathIsValidPathStringResult : public CtfPyAnnotatedBoolResult -// { -// Sdf_PathIsValidPathStringResult(bool val, string const &msg) : -// TfPyAnnotatedBoolResult(val, msg) {} -// }; +struct Sdf_PathIsValidPathStringResult : public TfPyAnnotatedBoolResult +{ + Sdf_PathIsValidPathStringResult(bool val, string const &msg) : + TfPyAnnotatedBoolResult(val, msg) {} +}; static -//Sdf_PathIsValidPathStringResult -bool +Sdf_PathIsValidPathStringResult _IsValidPathString(string const &pathString) { string errMsg; bool valid = SdfPath::IsValidPathString(pathString, &errMsg); - // return Sdf_PathIsValidPathStringResult(valid, errMsg); - return valid; + return Sdf_PathIsValidPathStringResult(valid, errMsg); } static @@ -318,8 +311,8 @@ void wrapPath() { VtValueFromPython(); - // Sdf_PathIsValidPathStringResult:: - // Wrap("_IsValidPathStringResult", - // "errorMessage"); + Sdf_PathIsValidPathStringResult:: + Wrap("_IsValidPathStringResult", + "errorMessage"); } From f1da1691e4c3d5ee16670218359a6339ca9ffca7 Mon Sep 17 00:00:00 2001 From: spiffmon Date: Fri, 23 Sep 2016 00:00:17 -0700 Subject: [PATCH 171/380] Add defaultPrim to Ball.shadingVariants.usda. The associated script adds it, so this file likely didn't get regenerated properly, and as a result, the Ball.usd file that references it fails to load the reference (Internal change: 1656875) --- .../tutorials/endToEnd/assets/Ball/Ball.shadingVariants.usda | 3 +++ 1 file changed, 3 insertions(+) diff --git a/extras/usd/tutorials/endToEnd/assets/Ball/Ball.shadingVariants.usda b/extras/usd/tutorials/endToEnd/assets/Ball/Ball.shadingVariants.usda index f49255c4c8..d9ba3ed9a1 100644 --- a/extras/usd/tutorials/endToEnd/assets/Ball/Ball.shadingVariants.usda +++ b/extras/usd/tutorials/endToEnd/assets/Ball/Ball.shadingVariants.usda @@ -1,4 +1,7 @@ #usda 1.0 +( + defaultPrim = "Ball" +) over "Ball" ( variants = { From 39a5f9a196ac1c320df4a048900256b743f2ce17 Mon Sep 17 00:00:00 2001 From: comand Date: Fri, 23 Sep 2016 00:00:26 -0700 Subject: [PATCH 172/380] Add test for TfPyAnnotatedBoolResult. (Internal change: 1656920) --- .../testenv/testTf_PyAnnotatedBoolResult.py | 41 +++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 pxr/base/lib/tf/testenv/testTf_PyAnnotatedBoolResult.py diff --git a/pxr/base/lib/tf/testenv/testTf_PyAnnotatedBoolResult.py b/pxr/base/lib/tf/testenv/testTf_PyAnnotatedBoolResult.py new file mode 100644 index 0000000000..e0a91c2d0e --- /dev/null +++ b/pxr/base/lib/tf/testenv/testTf_PyAnnotatedBoolResult.py @@ -0,0 +1,41 @@ +#!/pxrpythonsubst +# +# 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. +# + +from pxr import Tf +import unittest + +class TestTfPyAnnotatedBoolResult(unittest.TestCase): + + def test_boolResult(self): + result = Tf._TestAnnotatedBoolResult(True, 'This is true') + self.assertTrue(result) + self.assertEqual(result.annotation, 'This is true') + result = Tf._TestAnnotatedBoolResult(False, 'This is false') + self.assertFalse(result) + self.assertEqual(result.annotation, 'This is false') + +if __name__ == '__main__': + unittest.main() + From 911bcaa9e0caf86a75a47b5513c4d8b9459f74f7 Mon Sep 17 00:00:00 2001 From: takahito-tejima Date: Fri, 23 Sep 2016 00:00:50 -0700 Subject: [PATCH 173/380] [Hd] prevent shader compilation error when sampling coordinate is not defined Currently hydra's codeGen generates texture accessor as HdGet_diffuseColor(vec2 coord) { return texture(sampler2d_diffuseColor, coord); } HdGet_diffuseColor() { return HdGet_diffuseColor(HdGet_uv()); } but it fails to compile if the prim doesn't have HdGet_uv defined in primvars. For easier integration, this change adds local fixes vec2(0) instead if not. Ideally this should be detected in codegen if the inPrimVar exist or not, instead of GLSL compile time switch. (Internal change: 1656980) --- pxr/imaging/lib/hd/codeGen.cpp | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/pxr/imaging/lib/hd/codeGen.cpp b/pxr/imaging/lib/hd/codeGen.cpp index 6fab3ebf98..493f5aabbd 100644 --- a/pxr/imaging/lib/hd/codeGen.cpp +++ b/pxr/imaging/lib/hd/codeGen.cpp @@ -1797,7 +1797,12 @@ Hd_CodeGen::_GenerateShaderParameters() if (not it->second.inPrimVars.empty()) { accessors - << " HdGet_" << it->second.inPrimVars[0] << "().xy"; + << "\n" + << "#if defined(HD_HAS_" << it->second.inPrimVars[0] << ")\n" + << " HdGet_" << it->second.inPrimVars[0] << "().xy\n" + << "#else\n" + << "vec2(0.0, 0.0)\n" + << "#endif\n"; } else { // allow to fetch uv texture without sampler coordinate for convenience. accessors @@ -1830,8 +1835,13 @@ Hd_CodeGen::_GenerateShaderParameters() << " HdGet_" << it->second.name << "() { return HdGet_" << it->second.name << "("; if (not it->second.inPrimVars.empty()) { - accessors - << "HdGet_" << it->second.inPrimVars[0] << "().xy"; + accessors + << "\n" + << "#if defined(HD_HAS_" << it->second.inPrimVars[0] << ")\n" + << "HdGet_" << it->second.inPrimVars[0] << "().xy\n" + << "#else\n" + << "vec2(0.0, 0.0)\n" + << "#endif\n"; } else { accessors << "vec2(0.0, 0.0)"; @@ -1902,7 +1912,11 @@ Hd_CodeGen::_GenerateShaderParameters() accessors << it->second.dataType << " HdGet_" << it->second.name << "() {\n" - << " return HdGet_" << it->second.inPrimVars[0] << "();" + << "#if defined(HD_HAS_" << it->second.inPrimVars[0] << ")\n" + << " return HdGet_" << it->second.inPrimVars[0] << "();\n" + << "#else\n" + << " return " << it->second.dataType << "(0);\n" + << "#endif\n" << "\n}\n" ; } From 6a8803f489555c4d85b9c8ebeaa7fc669407b058 Mon Sep 17 00:00:00 2001 From: sdao Date: Fri, 23 Sep 2016 00:01:01 -0700 Subject: [PATCH 174/380] Workaround for Maya crash in MFnMesh.setUVs() after creating crease set (Internal change: 1657042) --- third_party/maya/lib/usdMaya/translatorMesh_PrimVars.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/third_party/maya/lib/usdMaya/translatorMesh_PrimVars.cpp b/third_party/maya/lib/usdMaya/translatorMesh_PrimVars.cpp index 6a5b9bd8af..a5dbb4946f 100644 --- a/third_party/maya/lib/usdMaya/translatorMesh_PrimVars.cpp +++ b/third_party/maya/lib/usdMaya/translatorMesh_PrimVars.cpp @@ -131,6 +131,12 @@ PxrUsdMayaTranslatorMesh::_AssignUVSetPrimvarToMesh( } } + // The following two lines should have no effect on user-visible state but + // prevent a Maya crash in MFnMesh.setUVs after creating a crease set. + // XXX this workaround is needed pending a fix by Autodesk. + MString currentSet = meshFn.currentUVSetName(); + meshFn.setCurrentUVSetName(currentSet); + // Create UVs on the mesh from the values we collected out of the primvar. // We'll assign mesh components to these values below. status = meshFn.setUVs(uCoords, vCoords, &uvSetName); From 58b3c0f559dc4d3602db06ad89afae2d9ef5158d Mon Sep 17 00:00:00 2001 From: MWDD Date: Fri, 23 Sep 2016 00:01:09 -0700 Subject: [PATCH 175/380] Fix for not resetting varying bit after initial frame draw. The bug report was complaining about poor performance playing back a shot, even though most of the shot was unloaded or invis'ed. Profiles revealed that the time was being spent in Hydra during Syncing even though only a small number of items were changing in the frame. The problem was caused by invalidating the prims during the initial renders causing the prims to become marked as varying. We have a heuristic that resets the varying flag on prims when more than a certain percentage of prims in the dirty list are actually clean. This percentage was set very high (90%) when the shot it question has 100000's of items, but was only reaching 88%. Changes: - Changed the heuristic to be 25% - Added a debug flag that reports the current heuristics (Internal change: 1657082) --- pxr/imaging/lib/hd/debugCodes.cpp | 1 + pxr/imaging/lib/hd/debugCodes.h | 4 ++-- pxr/imaging/lib/hd/renderIndex.cpp | 11 +++++++++-- 3 files changed, 12 insertions(+), 4 deletions(-) diff --git a/pxr/imaging/lib/hd/debugCodes.cpp b/pxr/imaging/lib/hd/debugCodes.cpp index 517dad053d..5b0d7b89ab 100644 --- a/pxr/imaging/lib/hd/debugCodes.cpp +++ b/pxr/imaging/lib/hd/debugCodes.cpp @@ -86,4 +86,5 @@ TF_REGISTRY_FUNCTION(TfDebug) TF_DEBUG_ENVIRONMENT_SYMBOL(HD_TEXTURE_ADDED, "Report when textures are added"); TF_DEBUG_ENVIRONMENT_SYMBOL(HD_TEXTURE_REMOVED, "Report when textures are removed"); + TF_DEBUG_ENVIRONMENT_SYMBOL(HD_VARYING_STATE, "Reports state tracking of varying state"); } diff --git a/pxr/imaging/lib/hd/debugCodes.h b/pxr/imaging/lib/hd/debugCodes.h index dca9a61f26..9e8a23ca19 100644 --- a/pxr/imaging/lib/hd/debugCodes.h +++ b/pxr/imaging/lib/hd/debugCodes.h @@ -65,8 +65,8 @@ TF_DEBUG_CODES( HD_TASK_ADDED, HD_TASK_REMOVED, HD_TEXTURE_ADDED, - HD_TEXTURE_REMOVED - + HD_TEXTURE_REMOVED, + HD_VARYING_STATE ); #endif // HD_DEBUGCODES_H diff --git a/pxr/imaging/lib/hd/renderIndex.cpp b/pxr/imaging/lib/hd/renderIndex.cpp index abe4fe2f2e..9cb58ed9bf 100644 --- a/pxr/imaging/lib/hd/renderIndex.cpp +++ b/pxr/imaging/lib/hd/renderIndex.cpp @@ -888,14 +888,21 @@ HdRenderIndex::SyncAll() } // Use a heuristic to determine whether or not to destroy the entire - // dirty state. We say that if we've skipped more than 90% of the + // dirty state. We say that if we've skipped more than 25% of the // rprims that were claimed dirty, then it's time to clean up this // list. This leads to performance improvements after many rprims // get dirty and then cleaned one, and the steady state becomes a // small number of dirty items. if (not dirtyIds.empty()) { resetVaryingState = - ((float )numSkipped / (float)dirtyIds.size()) > 0.9f; + ((float )numSkipped / (float)dirtyIds.size()) > 0.25f; + + if (TfDebug::IsEnabled(HD_VARYING_STATE)) { + std::cout << "Dirty List Redundancy = " + << ((float )numSkipped * 100.0f / (float)dirtyIds.size()) + << "% (" << numSkipped << " / " + << dirtyIds.size() << ")" << std::endl; + } } } From 3e826ceec7c1aac500c8bbf6cf48a18544fd0417 Mon Sep 17 00:00:00 2001 From: gitamohr Date: Fri, 23 Sep 2016 00:01:59 -0700 Subject: [PATCH 176/380] arch: Add ArchMemAdvise() and ArchFileAdvise() wrappers for posix_{m,f}advise(). Only expose the WILLNEED and DONTNEED advice values for now. On Windows this is currently a noop. (Internal change: 1657232) --- pxr/base/lib/arch/fileSystem.cpp | 25 +++++++++++++++++++++++++ pxr/base/lib/arch/fileSystem.h | 25 +++++++++++++++++++++++++ 2 files changed, 50 insertions(+) diff --git a/pxr/base/lib/arch/fileSystem.cpp b/pxr/base/lib/arch/fileSystem.cpp index 89de1a7ab8..96882d1c2e 100644 --- a/pxr/base/lib/arch/fileSystem.cpp +++ b/pxr/base/lib/arch/fileSystem.cpp @@ -366,6 +366,19 @@ ArchMapFileReadWrite(FILE *file) return Arch_MapFileImpl(file); } +ARCH_API +void ArchMemAdvise(void const *addr, size_t len, ArchMemAdvice adv) +{ +#if defined(ARCH_OS_WINDOWS) + // No windows implementation yet. Look at + // PrefetchVirtualMemory()/OfferVirtualMemory() in future. +#else // assume POSIX + posix_madvise(const_cast(addr), len, + adv == ArchMemAdviceWillNeed ? + POSIX_MADV_WILLNEED : POSIX_MADV_DONTNEED); +#endif +} + int64_t ArchPRead(FILE *file, void *buffer, size_t count, int64_t offset) { @@ -478,3 +491,15 @@ ArchPWrite(FILE *file, void const *bytes, size_t count, int64_t offset) #endif } +ARCH_API +void ArchFileAdvise( + FILE *file, int64_t offset, size_t count, ArchFileAdvice adv) +{ +#if defined(ARCH_OS_WINDOWS) + // No windows implementation yet. Not clear what's equivalent. +#else // assume POSIX + posix_fadvise(fileno(file), offset, static_cast(count), + adv == ArchFileAdviceWillNeed ? + POSIX_FADV_WILLNEED : POSIX_FADV_DONTNEED); +#endif +} diff --git a/pxr/base/lib/arch/fileSystem.h b/pxr/base/lib/arch/fileSystem.h index 4ad781edfd..a57393eca6 100644 --- a/pxr/base/lib/arch/fileSystem.h +++ b/pxr/base/lib/arch/fileSystem.h @@ -187,6 +187,18 @@ ArchConstFileMapping ArchMapFileReadOnly(FILE *file); ARCH_API ArchMutableFileMapping ArchMapFileReadWrite(FILE *file); +enum ArchMemAdvice { + ArchMemAdviceWillNeed, // OS may prefetch this range. + ArchMemAdviceDontNeed // OS may free resources related to this range. +}; + +/// Advise the OS regarding how the application intends to access a range of +/// memory. See ArchMemAdvice. This is primarily useful for mapped file +/// regions. This call does not change program semantics. It is only an +/// optimization hint to the OS, and may be a no-op on some systems. +ARCH_API +void ArchMemAdvise(void const *addr, size_t len, ArchMemAdvice adv); + /// Read up to \p count bytes from \p offset in \p file into \p buffer. The /// file position indicator for \p file is not changed. Return the number of /// bytes read, or zero if at end of file. Return -1 in case of an error, with @@ -201,6 +213,19 @@ int64_t ArchPRead(FILE *file, void *buffer, size_t count, int64_t offset); ARCH_API int64_t ArchPWrite(FILE *file, void const *bytes, size_t count, int64_t offset); +enum ArchFileAdvice { + ArchFileAdviceWillNeed, // OS may prefetch this range. + ArchFileAdviceDontNeed // OS may free resources related to this range. +}; + +/// Advise the OS regarding how the application intends to access a range of +/// bytes in a file. See ArchFileAdvice. This call does not change program +/// semantics. It is only an optimization hint to the OS, and may be a no-op on +/// some systems. +ARCH_API +void ArchFileAdvise(FILE *file, int64_t offset, size_t count, + ArchFileAdvice adv); + ///@} #endif // ARCH_FILESYSTEM_H From b9c8f1ea4c235d2c165d47b7bae35cf4d46b2ec1 Mon Sep 17 00:00:00 2001 From: gitamohr Date: Fri, 23 Sep 2016 15:03:53 -0700 Subject: [PATCH 177/380] usd: Check for 'usdc' as underlying file format first, since we expect that to be the most common case. (Internal change: 1657417) --- pxr/usd/lib/usd/usdFileFormat.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/pxr/usd/lib/usd/usdFileFormat.cpp b/pxr/usd/lib/usd/usdFileFormat.cpp index dd575f5285..33b190118a 100644 --- a/pxr/usd/lib/usd/usdFileFormat.cpp +++ b/pxr/usd/lib/usd/usdFileFormat.cpp @@ -73,16 +73,16 @@ static SdfFileFormatConstPtr _GetUnderlyingFileFormat(const string& filePath) { - auto usdaFormat = _GetFileFormat(UsdUsdaFileFormatTokens->Id); - if (usdaFormat->CanRead(filePath)) { - return usdaFormat; - } - auto usdcFormat = _GetFileFormat(UsdUsdcFileFormatTokens->Id); if (usdcFormat->CanRead(filePath)) { return usdcFormat; } + auto usdaFormat = _GetFileFormat(UsdUsdaFileFormatTokens->Id); + if (usdaFormat->CanRead(filePath)) { + return usdaFormat; + } + // XXX: Usdb has to come last because it unconditionally returns 'true' for // all CanRead() calls! // XXX: Explicitly check if the Usdb format exists because it may not From f7dff48549a6b0d69832fd7e9ae2666c58cce64e Mon Sep 17 00:00:00 2001 From: sunyab Date: Fri, 23 Sep 2016 15:04:03 -0700 Subject: [PATCH 178/380] Add Pixar copyright notice to open source code. (Internal change: 1657502) --- pxr/base/lib/tf/pyAnnotatedBoolResult.cpp | 23 +++++++++++++++++++++++ pxr/base/lib/tf/pyAnnotatedBoolResult.h | 23 +++++++++++++++++++++++ 2 files changed, 46 insertions(+) diff --git a/pxr/base/lib/tf/pyAnnotatedBoolResult.cpp b/pxr/base/lib/tf/pyAnnotatedBoolResult.cpp index 1eb8344274..5f839de2e0 100644 --- a/pxr/base/lib/tf/pyAnnotatedBoolResult.cpp +++ b/pxr/base/lib/tf/pyAnnotatedBoolResult.cpp @@ -1 +1,24 @@ +// +// 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. +// #include "pxr/base/tf/pyAnnotatedBoolResult.h" diff --git a/pxr/base/lib/tf/pyAnnotatedBoolResult.h b/pxr/base/lib/tf/pyAnnotatedBoolResult.h index 186ee684cd..9dfbc190bd 100644 --- a/pxr/base/lib/tf/pyAnnotatedBoolResult.h +++ b/pxr/base/lib/tf/pyAnnotatedBoolResult.h @@ -1,3 +1,26 @@ +// +// 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 TF_PYANNOTATEDBOOLRESULT_H #define TF_PYANNOTATEDBOOLRESULT_H From f983733671f1e5d8fd4be4b17dfc689814168bef Mon Sep 17 00:00:00 2001 From: gitamohr Date: Fri, 23 Sep 2016 15:04:14 -0700 Subject: [PATCH 179/380] usd: Use Arch{Mem,File}Advise() to ideally prefetch the structural part of a .usdc file. This is the index data at the end of the file which we always read. (Internal change: 1657531) --- pxr/usd/lib/usd/crateFile.cpp | 29 +++++++++++++++++++++++++++++ pxr/usd/lib/usd/crateFile.h | 1 + 2 files changed, 30 insertions(+) diff --git a/pxr/usd/lib/usd/crateFile.cpp b/pxr/usd/lib/usd/crateFile.cpp index a33d0e8802..e865544c01 100644 --- a/pxr/usd/lib/usd/crateFile.cpp +++ b/pxr/usd/lib/usd/crateFile.cpp @@ -365,6 +365,10 @@ struct _MmapStream { } inline int64_t Tell() const { return _cur - _mapStart; } inline void Seek(int64_t offset) { _cur = _mapStart + offset; } + inline void Prefetch(int64_t offset, int64_t size) { + ArchMemAdvise(_mapStart + offset, size, ArchMemAdviceWillNeed); + } + private: char const *_cur; char const *_mapStart; @@ -377,6 +381,10 @@ struct _PreadStream { } inline int64_t Tell() const { return _cur; } inline void Seek(int64_t offset) { _cur = offset; } + inline void Prefetch(int64_t offset, int64_t size) { + ArchFileAdvise(_file, offset, size, ArchFileAdviceWillNeed); + } + private: int64_t _cur; FILE *_file; @@ -562,6 +570,8 @@ class CrateFile::_Reader : public _ReaderBase return bits; } + void Prefetch(int64_t offset, int64_t size) { src.Prefetch(offset, size); } + void Seek(uint64_t offset) { src.Seek(offset); } // Map helper. @@ -1587,6 +1597,7 @@ CrateFile::_ReadStructuralSections(Reader reader, int64_t fileSize) TfErrorMark m; _boot = _ReadBootStrap(reader.src, fileSize); if (m.IsClean()) _toc = _ReadTOC(reader, _boot); + if (m.IsClean()) _PrefetchStructuralSections(reader); if (m.IsClean()) _ReadTokens(reader); if (m.IsClean()) _ReadStrings(reader); if (m.IsClean()) _ReadFields(reader); @@ -1621,6 +1632,24 @@ CrateFile::_ReadBootStrap(ByteStream src, int64_t fileSize) return b; } +template +void +CrateFile::_PrefetchStructuralSections(Reader reader) const +{ + // Go through the _toc and find its maximal range, then ask the reader to + // prefetch that range. + int64_t min = -1, max = -1; + for (_Section const &sec: _toc.sections) { + if (min == -1 || (sec.start < min)) + min = sec.start; + int64_t end = sec.start + sec.size; + if (max == -1 || (end > max)) + max = end; + } + if (min != -1 && max != -1) + reader.Prefetch(min, max-min); +} + template CrateFile::_TableOfContents CrateFile::_ReadTOC(Reader reader, _BootStrap const &b) const diff --git a/pxr/usd/lib/usd/crateFile.h b/pxr/usd/lib/usd/crateFile.h index 799a4ef046..60f7bb8acd 100644 --- a/pxr/usd/lib/usd/crateFile.h +++ b/pxr/usd/lib/usd/crateFile.h @@ -560,6 +560,7 @@ class CrateFile template _TableOfContents _ReadTOC(Reader src, _BootStrap const &b) const; + template void _PrefetchStructuralSections(Reader src) const; template void _ReadFieldSets(Reader src); template void _ReadFields(Reader src); template void _ReadSpecs(Reader src); From c5195c7d8e70f33345bc84d7fbd9c12385dfe603 Mon Sep 17 00:00:00 2001 From: blevin Date: Fri, 23 Sep 2016 15:04:22 -0700 Subject: [PATCH 180/380] Muting & unmuting a layer no longer loses unsaved changes. (Internal change: 1657575) --- pxr/usd/lib/sdf/layer.cpp | 86 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 83 insertions(+), 3 deletions(-) diff --git a/pxr/usd/lib/sdf/layer.cpp b/pxr/usd/lib/sdf/layer.cpp index 0d203618ea..c71d251b86 100644 --- a/pxr/usd/lib/sdf/layer.cpp +++ b/pxr/usd/lib/sdf/layer.cpp @@ -85,8 +85,10 @@ TF_REGISTRY_FUNCTION(TfType) // paths should be asset paths, when applicable, or identifiers if no asset // path exists for the desired layers. typedef set _MutedLayers; +typedef std::map _MutedLayerDataMap; static TfStaticData<_MutedLayers> _mutedLayers; -// Global mutex protecting _mutedLayers. +static TfStaticData<_MutedLayerDataMap> _mutedLayerData; +// Global mutex protecting _mutedLayers and _mutedLayerData static TfStaticData _mutedLayersMutex; // This is a global revision number that tracks changes to _mutedLayers. Since // we seldom mute and unmute layers, this lets layers cache their muteness and @@ -94,6 +96,7 @@ static TfStaticData _mutedLayersMutex; // _mutedLayers. static std::atomic_size_t _mutedLayersRevision { 1 }; + // A registry for loaded layers. static TfStaticData _layerRegistry; // Global mutex protecting _layerRegistry. @@ -146,6 +149,23 @@ SdfLayer::~SdfLayer() TF_DEBUG(SDF_LAYER).Msg( "SdfLayer::~SdfLayer('%s')\n", GetIdentifier().c_str()); + if (IsMuted()) { + std::string mutedPath = _GetMutedPath(); + SdfAbstractDataRefPtr mutedData; + { + std::lock_guard lock(*_mutedLayersMutex); + // Drop any in-memory edits we may have been holding for this layer. + // To minimize time holding the lock, swap the data out and + // erase the entry, then release the lock before proceeding + // to drop the refcount. + _MutedLayerDataMap::iterator i = _mutedLayerData->find(mutedPath); + if (i != _mutedLayerData->end()) { + std::swap(mutedData, i->second); + _mutedLayerData->erase(i); + } + } + } + std::lock_guard lock(*_layerRegistryMutex); // Note that FindOrOpen may have already removed this layer from @@ -2291,7 +2311,46 @@ SdfLayer::AddToMutedLayers(const string &path) } if (didChange) { if (SdfLayerHandle layer = Find(path)) { - layer->_Reload(/* force */ true); + if (layer->IsDirty()) { + SdfFileFormatConstPtr format = layer->GetFileFormat(); + SdfAbstractDataRefPtr initializedData = + format->InitData(layer->GetFileFormatArguments()); + if (format->IsStreamingLayer(*layer.operator->())) { + // See the discussion in TransferContent() + // about streaming layers; the same concerns + // apply here. We must swap out the actual data + // ownership and tell clients the entire data + // store has changed. + { + std::lock_guard lock(*_mutedLayersMutex); + TF_VERIFY((*_mutedLayerData).find(path) == + (*_mutedLayerData).end()); + (*_mutedLayerData)[path] = layer->_data; + } + // _SetData() takes ownership of initializedData and sends + // change notification. + layer->_SetData(initializedData); + } else { + // Copy the dirty layer data to an in-memory store + // that will be owned by _mutedLayerData. + SdfAbstractDataRefPtr mutedData = + format->InitData(layer->GetFileFormatArguments()); + mutedData->CopyFrom(layer->_data); + { + std::lock_guard lock(*_mutedLayersMutex); + TF_VERIFY((*_mutedLayerData).find(path) == + (*_mutedLayerData).end()); + std::swap( (*_mutedLayerData)[path], mutedData ); + } + // Mutate the layer's data to the initialized state. + // This enables efficient change processing downstream. + layer->_SetData(initializedData); + } + TF_VERIFY(layer->IsDirty()); + } else { + // Reload as muted. + layer->_Reload(/* force */ true); + } } SdfNotice::LayerMutenessChanged(path, /* wasMuted = */ true).Send(); } @@ -2310,7 +2369,28 @@ SdfLayer::RemoveFromMutedLayers(const string &path) } if (didChange) { if (SdfLayerHandle layer = Find(path)) { - layer->_Reload(/* force */ true); + if (layer->IsDirty()) { + SdfAbstractDataRefPtr mutedData; + { + std::lock_guard lock(*_mutedLayersMutex); + _MutedLayerDataMap::iterator i = + _mutedLayerData->find(path); + if (TF_VERIFY(i != _mutedLayerData->end())) { + std::swap(mutedData, i->second); + _mutedLayerData->erase(i); + } + } + if (TF_VERIFY(mutedData)) { + // If IsStreamingLayer() is true, this re-takes ownership + // of the mutedData object. Otherwise, this mutates + // the existing data container to match its contents. + layer->_SetData(mutedData); + } + TF_VERIFY(layer->IsDirty()); + } else { + // Reload as unmuted. + layer->_Reload(/* force */ true); + } } SdfNotice::LayerMutenessChanged(path, /* wasMuted = */ false).Send(); } From d4966d6a800c8e9f6870a05b86d85a8f17986f6f Mon Sep 17 00:00:00 2001 From: sunyab Date: Fri, 23 Sep 2016 15:04:32 -0700 Subject: [PATCH 181/380] Remove call to nonexistent posix_fadvise on OSX (Internal change: 1657576) --- pxr/base/lib/arch/fileSystem.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pxr/base/lib/arch/fileSystem.cpp b/pxr/base/lib/arch/fileSystem.cpp index 96882d1c2e..3d88b2e03d 100644 --- a/pxr/base/lib/arch/fileSystem.cpp +++ b/pxr/base/lib/arch/fileSystem.cpp @@ -497,6 +497,8 @@ void ArchFileAdvise( { #if defined(ARCH_OS_WINDOWS) // No windows implementation yet. Not clear what's equivalent. +#elif defined(ARCH_OS_DARWIN) + // No OSX implementation; posix_fadvise does not exist on that platform. #else // assume POSIX posix_fadvise(fileno(file), offset, static_cast(count), adv == ArchFileAdviceWillNeed ? From f5a5ff12486c43528afa1502b305f0dc65da9821 Mon Sep 17 00:00:00 2001 From: sunyab Date: Fri, 23 Sep 2016 15:04:41 -0700 Subject: [PATCH 182/380] Fix extension for Python modules on all platforms Python modules must be suffixed with .pyd on Windows, and .so on Linux and OSX. Fixes #19 (Internal change: 1657601) --- cmake/macros/Public.cmake | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/cmake/macros/Public.cmake b/cmake/macros/Public.cmake index 6478505614..569c7b2bdf 100644 --- a/cmake/macros/Public.cmake +++ b/cmake/macros/Public.cmake @@ -170,12 +170,26 @@ function(pxr_shared_library LIBRARY_NAME) set(rpath "$ORIGIN/../../../../${PXR_INSTALL_SUBDIR}/lib:${rpath}") endif() - set_target_properties(${LIBRARY_NAME} - PROPERTIES - PREFIX "" - FOLDER "${PXR_PREFIX}/_python" - INSTALL_RPATH ${rpath} - ) + # Python modules must be suffixed with .pyd on Windows and .so on + # other platforms. + if(WIN32) + set_target_properties(${LIBRARY_NAME} + PROPERTIES + PREFIX "" + SUFFIX ".pyd" + FOLDER "${PXR_PREFIX}/_python" + INSTALL_RPATH ${rpath} + LINK_FLAGS_RELEASE "/SUBSYSTEM:WINDOWS" + ) + else() + set_target_properties(${LIBRARY_NAME} + PROPERTIES + PREFIX "" + SUFFIX ".so" + FOLDER "${PXR_PREFIX}/_python" + INSTALL_RPATH ${rpath} + ) + endif() else() _get_install_dir(lib LIB_INSTALL_PREFIX) _get_share_install_dir(SHARE_INSTALL_PREFIX) From 5fffa909ae036f7a6f081054b376afc53b792f8e Mon Sep 17 00:00:00 2001 From: sunyab Date: Fri, 23 Sep 2016 15:04:52 -0700 Subject: [PATCH 183/380] Add missing dependency on OpenMayaUI to px_vp20 (Internal change: 1657608) --- third_party/maya/lib/px_vp20/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/third_party/maya/lib/px_vp20/CMakeLists.txt b/third_party/maya/lib/px_vp20/CMakeLists.txt index 40a6179c68..092778f7b3 100644 --- a/third_party/maya/lib/px_vp20/CMakeLists.txt +++ b/third_party/maya/lib/px_vp20/CMakeLists.txt @@ -4,6 +4,7 @@ pxr_shared_library(${PXR_PACKAGE} LIBRARIES gf ${MAYA_OpenMaya_LIBRARY} + ${MAYA_OpenMayaUI_LIBRARY} ${MAYA_OpenMayaRender_LIBRARY} ${OPENGL_gl_LIBRARY} From 4280d7c0f94acc07c75818346d6c2dce7c646791 Mon Sep 17 00:00:00 2001 From: George ElKoura Date: Fri, 23 Sep 2016 23:00:10 -0700 Subject: [PATCH 184/380] Fixed typo in export macro. --- pxr/imaging/lib/hdx/camera.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pxr/imaging/lib/hdx/camera.h b/pxr/imaging/lib/hdx/camera.h index ee107e5c21..f6f43937fe 100644 --- a/pxr/imaging/lib/hdx/camera.h +++ b/pxr/imaging/lib/hdx/camera.h @@ -60,7 +60,7 @@ class HdxCamera : public HdSprim { HDXLIB_API HdxCamera(HdSceneDelegate* delegate, SdfPath const & id); - HDLIB_API + HDXLIB_API ~HdxCamera(); // note: not virtual (for now) // change tracking for HdxLight From 92d00b8bccc9966937b848ab0e3bd7cfcc843ed7 Mon Sep 17 00:00:00 2001 From: George ElKoura Date: Sun, 25 Sep 2016 20:59:46 -0700 Subject: [PATCH 185/380] Add some missing export macros to usdGeom and usdUtils. --- pxr/usd/lib/usdGeom/imageable.h | 5 +++++ pxr/usd/lib/usdUtils/stitchClips.h | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/pxr/usd/lib/usdGeom/imageable.h b/pxr/usd/lib/usdGeom/imageable.h index e1e89579e4..bb8d1ff794 100644 --- a/pxr/usd/lib/usdGeom/imageable.h +++ b/pxr/usd/lib/usdGeom/imageable.h @@ -237,10 +237,12 @@ class UsdGeomImageable : public UsdTyped /// \note It is only valid to author the proxyPrim relationship on /// prims whose purpose is "render". /// + USDGEOM_API UsdRelationship GetProxyPrimRel() const; /// See GetProxyPrimRel(), and also /// \ref Usd_Create_Or_Get_Property for when to use Get vs Create + USDGEOM_API UsdRelationship CreateProxyPrimRel() const; public: @@ -491,6 +493,7 @@ class UsdGeomImageable : public UsdTyped /// change this method to return a context-aware result. /// /// \sa SetProxyPrim(), GetProxyPrimRel() + USDGEOM_API UsdPrim ComputeProxyPrim(UsdPrim *renderPrim=NULL) const; /// Convenience function for authoring the \em renderProxy rel on this @@ -501,9 +504,11 @@ class UsdGeomImageable : public UsdTyped /// purpoes of the specified prim. /// /// \sa ComputeProxyPrim(), GetProxyPrimRel() + USDGEOM_API bool SetProxyPrim(const UsdPrim &proxy) const; /// \overload that takes any UsdSchemaBase-derived object + USDGEOM_API bool SetProxyPrim(const UsdSchemaBase &proxy) const; /// Compute the bound of this prim in world space, at the specified diff --git a/pxr/usd/lib/usdUtils/stitchClips.h b/pxr/usd/lib/usdUtils/stitchClips.h index 705cc91a8b..0d41592503 100644 --- a/pxr/usd/lib/usdUtils/stitchClips.h +++ b/pxr/usd/lib/usdUtils/stitchClips.h @@ -113,7 +113,7 @@ UsdUtilsStitchClips(const SdfLayerHandle& resultLayer, /// /// \p clipLayerFiles The files containing the time varying data. /// -bool +USDUTILS_API bool UsdUtilsStitchClipsTopology(const SdfLayerHandle& topologyLayer, const std::vector& clipLayerFiles); From 7fb997955636c5ab2a22fe2a857b830c14a09dca Mon Sep 17 00:00:00 2001 From: George ElKoura Date: Sun, 25 Sep 2016 21:00:55 -0700 Subject: [PATCH 186/380] Turn off examples on Windows temporarily because of broken includes. --- extras/usd/CMakeLists.txt | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/extras/usd/CMakeLists.txt b/extras/usd/CMakeLists.txt index e4503686dd..4df49dbe81 100644 --- a/extras/usd/CMakeLists.txt +++ b/extras/usd/CMakeLists.txt @@ -1,3 +1,6 @@ -add_subdirectory(examples) +# XXX: comment out examples for now. It seems like we're not passing in the +# correct include directories... we're passing in $BUILD/include (which doesn't +# exist) and not $INST/include which we ought to be passing in. +#add_subdirectory(examples) add_subdirectory(tutorials) From 436a691aae96cee83d4b86bdd5bb5d9114900d9e Mon Sep 17 00:00:00 2001 From: George ElKoura Date: Sun, 25 Sep 2016 21:03:50 -0700 Subject: [PATCH 187/380] Use secure version of posix API in testWorkLoops.cpp and crateFile.cpp. --- pxr/base/lib/work/testenv/testWorkLoops.cpp | 3 ++- pxr/usd/lib/usd/crateFile.cpp | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/pxr/base/lib/work/testenv/testWorkLoops.cpp b/pxr/base/lib/work/testenv/testWorkLoops.cpp index 58c787e099..6091fbc468 100644 --- a/pxr/base/lib/work/testenv/testWorkLoops.cpp +++ b/pxr/base/lib/work/testenv/testWorkLoops.cpp @@ -193,7 +193,8 @@ main(int argc, char **argv) if (perfMode) { // XXX:perfgen only accepts metric names ending in _time. See bug 97317 - FILE *outputFile = fopen("perfstats.raw", "w"); + FILE *outputFile; + fopen_s(&outputFile, "perfstats.raw", "w"); fprintf(outputFile, "{'profile':'TBB Loops_time','metric':'time','value':%f,'samples':1}\n", tbbSeconds); diff --git a/pxr/usd/lib/usd/crateFile.cpp b/pxr/usd/lib/usd/crateFile.cpp index baea6689ec..838fa2bcd3 100644 --- a/pxr/usd/lib/usd/crateFile.cpp +++ b/pxr/usd/lib/usd/crateFile.cpp @@ -219,7 +219,7 @@ struct CrateFile::Version static Version FromString(char const *str) { uint32_t maj, min, pat; - if (sscanf(str, "%u.%u.%u", &maj, &min, &pat) != 3 || + if (sscanf_s(str, "%u.%u.%u", &maj, &min, &pat) != 3 || maj > 255 || min > 255 || pat > 255) { return Version(); } From 93ccd3517ac910df321b44ffc3693936664e5d14 Mon Sep 17 00:00:00 2001 From: George ElKoura Date: Sun, 25 Sep 2016 21:28:59 -0700 Subject: [PATCH 188/380] Fix merge error. --- pxr/base/lib/tf/CMakeLists.txt | 19 ------------------- 1 file changed, 19 deletions(-) diff --git a/pxr/base/lib/tf/CMakeLists.txt b/pxr/base/lib/tf/CMakeLists.txt index 4690122721..2a86e0f382 100644 --- a/pxr/base/lib/tf/CMakeLists.txt +++ b/pxr/base/lib/tf/CMakeLists.txt @@ -202,25 +202,6 @@ pxr_shared_library(tf testenv/testTfScriptModuleLoader_Unknown.py ) -<<<<<<< HEAD -if(UNIX) - pxr_build_test(testTfPyFunction - LIBRARIES - tf - ${Boost_PYTHON_LIBRARY} - CPPFILES - testenv/testTfPyFunction.cpp - ) - - pxr_build_test(testTfPyInterpreter - LIBRARIES - tf - CPPFILES - testenv/testTfPyInterpreter.cpp - ) -======= ->>>>>>> f1a2e20b249ac1e8aa8ec5cd6b2f558ecdd06f74 - pxr_build_test(testTfPyInterpreter LIBRARIES tf From 8f97d5b908d00ce1fe85adbf72236df52498b296 Mon Sep 17 00:00:00 2001 From: George ElKoura Date: Sun, 25 Sep 2016 21:33:06 -0700 Subject: [PATCH 189/380] Fix up small hd and hdx errors for Windows. --- pxr/imaging/lib/hd/changeTracker.h | 3 +++ pxr/imaging/lib/hdx/drawTarget.h | 3 ++- pxr/imaging/lib/hdx/drawTargetRenderPass.h | 4 ++-- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/pxr/imaging/lib/hd/changeTracker.h b/pxr/imaging/lib/hd/changeTracker.h index 935d8dbec0..fcba6a9513 100644 --- a/pxr/imaging/lib/hd/changeTracker.h +++ b/pxr/imaging/lib/hd/changeTracker.h @@ -491,13 +491,16 @@ class HdChangeTracker : public boost::noncopyable { // ---------------------------------------------------------------------- // /// Adds a named state for tracking. + HDLIB_API void AddState(TfToken const& name); /// Marks a named state as being dirty., this bumps the version of the /// state. + HDLIB_API void MarkStateDirty(TfToken const& name); /// Returns the current version of the named state. + HDLIB_API unsigned GetStateVersion(TfToken const &name) const; // ---------------------------------------------------------------------- // diff --git a/pxr/imaging/lib/hdx/drawTarget.h b/pxr/imaging/lib/hdx/drawTarget.h index 17ab65511d..b720f770a6 100644 --- a/pxr/imaging/lib/hdx/drawTarget.h +++ b/pxr/imaging/lib/hdx/drawTarget.h @@ -27,6 +27,7 @@ #include "pxr/imaging/hd/enums.h" #include "pxr/imaging/hd/rprimCollection.h" #include "pxr/imaging/hd/sprim.h" +#include "pxr/imaging/hdx/api.h" #include "pxr/imaging/hdx/drawTargetRenderPassState.h" #include "pxr/imaging/glf/drawTarget.h" @@ -46,7 +47,7 @@ (enable) \ (resolution) -TF_DECLARE_PUBLIC_TOKENS(HdxDrawTargetTokens, HDX_DRAW_TARGET_TOKENS); +TF_DECLARE_PUBLIC_TOKENS(HdxDrawTargetTokens, HDXLIB_API, HDX_DRAW_TARGET_TOKENS); class HdSceneDelegate; class HdxDrawTargetAttachmentDescArray; diff --git a/pxr/imaging/lib/hdx/drawTargetRenderPass.h b/pxr/imaging/lib/hdx/drawTargetRenderPass.h index 224dc0bf3c..b83d180bec 100644 --- a/pxr/imaging/lib/hdx/drawTargetRenderPass.h +++ b/pxr/imaging/lib/hdx/drawTargetRenderPass.h @@ -24,7 +24,7 @@ #ifndef HDX_DRAW_TARGET_RENDER_PASS_H #define HDX_DRAW_TARGET_RENDER_PASS_H -#include "pxr/imaging/hd/api.h" +#include "pxr/imaging/hdx/api.h" #include "pxr/imaging/hd/renderPass.h" #include "pxr/imaging/hd/rprimCollection.h" @@ -61,7 +61,7 @@ class HdxDrawTargetRenderPass : boost::noncopyable { /// Sets the non-context dependent state. The object is expected to /// live longer than this class. HDXLIB_API - void SetRenderPassState(HdDrawTargetRenderPassState *renderPassState); + void SetRenderPassState(HdxDrawTargetRenderPassState *renderPassState); HDXLIB_API void SetRprimCollection(HdRprimCollection const& col); From bd8c8e002659002b63fc72b749988942cb79cd27 Mon Sep 17 00:00:00 2001 From: sunyab Date: Mon, 26 Sep 2016 15:27:08 -0700 Subject: [PATCH 190/380] Move unused functions out of arch/fileSystem.h (Internal change: 1657620) --- pxr/base/lib/arch/fileSystem.cpp | 68 -------------------------------- pxr/base/lib/arch/fileSystem.h | 18 --------- 2 files changed, 86 deletions(-) diff --git a/pxr/base/lib/arch/fileSystem.cpp b/pxr/base/lib/arch/fileSystem.cpp index 3d88b2e03d..53bbaa633f 100644 --- a/pxr/base/lib/arch/fileSystem.cpp +++ b/pxr/base/lib/arch/fileSystem.cpp @@ -87,30 +87,6 @@ ArchGetModificationTime(const struct stat& st) #endif } -double -ArchGetAccessTime(const struct stat& st) -{ -#if defined(ARCH_OS_LINUX) - return st.st_atim.tv_sec + 1e-9*st.st_atim.tv_nsec; -#elif defined(ARCH_OS_DARWIN) - return st.st_atimespec.tv_sec + 1e-9*st.st_atimespec.tv_nsec; -#else -#error Unknown system architecture -#endif -} - -double -ArchGetStatusChangeTime(const struct stat& st) -{ -#if defined(ARCH_OS_LINUX) - return st.st_ctim.tv_sec + 1e-9*st.st_ctim.tv_nsec; -#elif defined(ARCH_OS_DARWIN) - return st.st_ctimespec.tv_sec + 1e-9*st.st_ctimespec.tv_nsec; -#else -#error Unknown system architecture -#endif -} - namespace { struct _Fcloser { inline void operator()(FILE *f) const { if (f) { fclose(f); } } @@ -255,50 +231,6 @@ ArchGetTmpDir() return _TmpDir; } -set -ArchGetAutomountDirectories() -{ - set result; - -#if !defined(ARCH_OS_LINUX) - ARCH_ERROR("unimplemented function"); -#else - if (FILE *in = fopen("/proc/mounts","r")) { - char linebuffer[1024]; - - while (fgets(linebuffer, 1024, in)) { - char name[1024], dir[1024], type[1024], opts[1024]; - if (sscanf(linebuffer, "%s %s %s %s", name, dir, type, opts) == 4 && - strcmp(type, "autofs") == 0) { - - // Omit mounts with the 'direct' option set. - bool direct = false; - - char* saveptr; - char* token = strtok_r(opts, ",", &saveptr); - while (token) { - if (strcmp(token, "direct") == 0) { - direct = true; - break; - } - token = strtok_r(NULL, ",", &saveptr); - } - - if (not direct) - result.insert(dir); - } - } - - fclose(in); - } - else { - ARCH_ERROR("Cannot open /proc/mounts"); - } -#endif - - return result; -} - void Arch_Unmapper::operator()(char const *mapStart) const { diff --git a/pxr/base/lib/arch/fileSystem.h b/pxr/base/lib/arch/fileSystem.h index a57393eca6..754e15f87e 100644 --- a/pxr/base/lib/arch/fileSystem.h +++ b/pxr/base/lib/arch/fileSystem.h @@ -69,18 +69,6 @@ ARCH_API bool ArchStatIsWritable(const struct stat *st); /// available in the stat structure for the current platform. ARCH_API double ArchGetModificationTime(const struct stat& st); -/// Returns the access time (atime) in seconds from the stat struct. -/// -/// This function returns the access time with as much precision as is -/// available in the stat structure for the current platform. -ARCH_API double ArchGetAccessTime(const struct stat& st); - -/// Returns the status change time (ctime) in seconds from the stat struct. -/// -/// This function returns the status change time with as much precision as is -/// available in the stat structure for the current platform. -ARCH_API double ArchGetStatusChangeTime(const struct stat& st); - /// Return the path to a temporary directory for this platform. /// /// The returned temporary directory will be a location that will normally @@ -145,12 +133,6 @@ ARCH_API std::string ArchMakeTmpSubdir(const std::string& tmpdir, const std::string& prefix); -/// Return all automounted directories. -/// -/// Returns a set of all directories that are automount points for the host. -ARCH_API -std::set ArchGetAutomountDirectories(); - // Helper 'deleter' for use with std::unique_ptr for file mappings. #if defined(ARCH_OS_WINDOWS) struct Arch_Unmapper { From 42095889061eaf640617fc3df2b4ade31715b917 Mon Sep 17 00:00:00 2001 From: unhyperbolic Date: Mon, 26 Sep 2016 15:27:16 -0700 Subject: [PATCH 191/380] Adding shutter:open and close to UsdGeomCamera. (Internal change: 1657653) --- pxr/usd/lib/usdGeom/camera.cpp | 36 ++++++++++++++++++++ pxr/usd/lib/usdGeom/camera.h | 43 ++++++++++++++++++++++++ pxr/usd/lib/usdGeom/generatedSchema.usda | 11 ++++++ pxr/usd/lib/usdGeom/schema.usda | 13 +++++++ pxr/usd/lib/usdGeom/tokens.h | 4 +++ pxr/usd/lib/usdGeom/wrapCamera.cpp | 28 +++++++++++++++ 6 files changed, 135 insertions(+) diff --git a/pxr/usd/lib/usdGeom/camera.cpp b/pxr/usd/lib/usdGeom/camera.cpp index 8e4d8e32d9..9c968765a1 100644 --- a/pxr/usd/lib/usdGeom/camera.cpp +++ b/pxr/usd/lib/usdGeom/camera.cpp @@ -280,6 +280,40 @@ UsdGeomCamera::CreateStereoRoleAttr(VtValue const &defaultValue, bool writeSpars writeSparsely); } +UsdAttribute +UsdGeomCamera::GetShutterOpenAttr() const +{ + return GetPrim().GetAttribute(UsdGeomTokens->shutterOpen); +} + +UsdAttribute +UsdGeomCamera::CreateShutterOpenAttr(VtValue const &defaultValue, bool writeSparsely) const +{ + return UsdSchemaBase::_CreateAttr(UsdGeomTokens->shutterOpen, + SdfValueTypeNames->Double, + /* custom = */ false, + SdfVariabilityVarying, + defaultValue, + writeSparsely); +} + +UsdAttribute +UsdGeomCamera::GetShutterCloseAttr() const +{ + return GetPrim().GetAttribute(UsdGeomTokens->shutterClose); +} + +UsdAttribute +UsdGeomCamera::CreateShutterCloseAttr(VtValue const &defaultValue, bool writeSparsely) const +{ + return UsdSchemaBase::_CreateAttr(UsdGeomTokens->shutterClose, + SdfValueTypeNames->Double, + /* custom = */ false, + SdfVariabilityVarying, + defaultValue, + writeSparsely); +} + namespace { static inline TfTokenVector _ConcatenateAttributeNames(const TfTokenVector& left,const TfTokenVector& right) @@ -308,6 +342,8 @@ UsdGeomCamera::GetSchemaAttributeNames(bool includeInherited) UsdGeomTokens->fStop, UsdGeomTokens->focusDistance, UsdGeomTokens->stereoRole, + UsdGeomTokens->shutterOpen, + UsdGeomTokens->shutterClose, }; static TfTokenVector allNames = _ConcatenateAttributeNames( diff --git a/pxr/usd/lib/usdGeom/camera.h b/pxr/usd/lib/usdGeom/camera.h index 4a341f939c..a7ffc963b3 100644 --- a/pxr/usd/lib/usdGeom/camera.h +++ b/pxr/usd/lib/usdGeom/camera.h @@ -388,6 +388,49 @@ class UsdGeomCamera : public UsdGeomXformable /// the default for \p writeSparsely is \c false. UsdAttribute CreateStereoRoleAttr(VtValue const &defaultValue = VtValue(), bool writeSparsely=false) const; +public: + // --------------------------------------------------------------------- // + // SHUTTEROPEN + // --------------------------------------------------------------------- // + /// Frame relative shutter open time in UsdTimeCode units (negative + /// value indicates that the shutter opens before the current's + /// frame time). Used for motion blur. + /// + /// \n C++ Type: double + /// \n Usd Type: SdfValueTypeNames->Double + /// \n Variability: SdfVariabilityVarying + /// \n Fallback Value: 0.0 + UsdAttribute GetShutterOpenAttr() const; + + /// See GetShutterOpenAttr(), and also + /// \ref Usd_Create_Or_Get_Property for when to use Get vs Create. + /// If specified, author \p defaultValue as the attribute's default, + /// sparsely (when it makes sense to do so) if \p writeSparsely is \c true - + /// the default for \p writeSparsely is \c false. + UsdAttribute CreateShutterOpenAttr(VtValue const &defaultValue = VtValue(), bool writeSparsely=false) const; + +public: + // --------------------------------------------------------------------- // + // SHUTTERCLOSE + // --------------------------------------------------------------------- // + /// Frame relative shutter close time, analogous comments from + /// shutter:open apply. A value greater or equal to shutter:open + /// should be authored, otherwise there is no exposure and a + /// renderer should produce a black image. + /// + /// \n C++ Type: double + /// \n Usd Type: SdfValueTypeNames->Double + /// \n Variability: SdfVariabilityVarying + /// \n Fallback Value: 0.0 + UsdAttribute GetShutterCloseAttr() const; + + /// See GetShutterCloseAttr(), and also + /// \ref Usd_Create_Or_Get_Property for when to use Get vs Create. + /// If specified, author \p defaultValue as the attribute's default, + /// sparsely (when it makes sense to do so) if \p writeSparsely is \c true - + /// the default for \p writeSparsely is \c false. + UsdAttribute CreateShutterCloseAttr(VtValue const &defaultValue = VtValue(), bool writeSparsely=false) const; + public: // ===================================================================== // // Feel free to add custom code below this line, it will be preserved by diff --git a/pxr/usd/lib/usdGeom/generatedSchema.usda b/pxr/usd/lib/usdGeom/generatedSchema.usda index aa68317689..97f1e5e8bf 100644 --- a/pxr/usd/lib/usdGeom/generatedSchema.usda +++ b/pxr/usd/lib/usdGeom/generatedSchema.usda @@ -3137,6 +3137,17 @@ class Camera "Camera" ( well with the needs of multithreaded rendering. Purpose provides us with a better tool for dynamic, interactive complexity management.''' ) + double shutter:close = 0 ( + doc = """Frame relative shutter close time, analogous comments from + shutter:open apply. A value greater or equal to shutter:open + should be authored, otherwise there is no exposure and a + renderer should produce a black image.""" + ) + double shutter:open = 0 ( + doc = """Frame relative shutter open time in UsdTimeCode units (negative + value indicates that the shutter opens before the current's + frame time). Used for motion blur.""" + ) uniform token stereoRole = "mono" ( allowedTokens = ["mono", "left", "right"] doc = """If different from mono, the camera is intended to be the left diff --git a/pxr/usd/lib/usdGeom/schema.usda b/pxr/usd/lib/usdGeom/schema.usda index 20cee71da0..f06f5aab73 100644 --- a/pxr/usd/lib/usdGeom/schema.usda +++ b/pxr/usd/lib/usdGeom/schema.usda @@ -1229,4 +1229,17 @@ class Camera "Camera" ( allowedTokens = ["mono", "left", "right"] doc = """If different from mono, the camera is intended to be the left or right camera of a stereo setup.""") + + # Parameters for motion blur + double shutter:open = 0.0 ( + doc = """Frame relative shutter open time in UsdTimeCode units (negative + value indicates that the shutter opens before the current + frame time). Used for motion blur.""" + ) + double shutter:close = 0.0 ( + doc = """Frame relative shutter close time, analogous comments from + shutter:open apply. A value greater or equal to shutter:open + should be authored, otherwise there is no exposure and a + renderer should produce a black image.""" + ) } diff --git a/pxr/usd/lib/usdGeom/tokens.h b/pxr/usd/lib/usdGeom/tokens.h index b739e09246..6169b20dd8 100644 --- a/pxr/usd/lib/usdGeom/tokens.h +++ b/pxr/usd/lib/usdGeom/tokens.h @@ -118,6 +118,8 @@ (render) \ (right) \ (rightHanded) \ + ((shutterClose, "shutter:close")) \ + ((shutterOpen, "shutter:open")) \ (size) \ (stereoRole) \ (subdivisionScheme) \ @@ -255,6 +257,8 @@ /// \li render - Possible value for UsdGeomImageable::GetPurposeAttr() /// \li right - Possible value for UsdGeomCamera::GetStereoRoleAttr() /// \li rightHanded - Possible value for UsdGeomGprim::GetOrientationAttr(), Default value for UsdGeomGprim::GetOrientationAttr() +/// \li shutterClose - UsdGeomCamera +/// \li shutterOpen - UsdGeomCamera /// \li size - UsdGeomCube /// \li stereoRole - UsdGeomCamera /// \li subdivisionScheme - UsdGeomMesh diff --git a/pxr/usd/lib/usdGeom/wrapCamera.cpp b/pxr/usd/lib/usdGeom/wrapCamera.cpp index 7537543ec1..1cf6c22119 100644 --- a/pxr/usd/lib/usdGeom/wrapCamera.cpp +++ b/pxr/usd/lib/usdGeom/wrapCamera.cpp @@ -122,6 +122,20 @@ _CreateStereoRoleAttr(UsdGeomCamera &self, return self.CreateStereoRoleAttr( UsdPythonToSdfType(defaultVal, SdfValueTypeNames->Token), writeSparsely); } + +static UsdAttribute +_CreateShutterOpenAttr(UsdGeomCamera &self, + object defaultVal, bool writeSparsely) { + return self.CreateShutterOpenAttr( + UsdPythonToSdfType(defaultVal, SdfValueTypeNames->Double), writeSparsely); +} + +static UsdAttribute +_CreateShutterCloseAttr(UsdGeomCamera &self, + object defaultVal, bool writeSparsely) { + return self.CreateShutterCloseAttr( + UsdPythonToSdfType(defaultVal, SdfValueTypeNames->Double), writeSparsely); +} void wrapUsdGeomCamera() { @@ -230,6 +244,20 @@ void wrapUsdGeomCamera() &_CreateStereoRoleAttr, (arg("defaultValue")=object(), arg("writeSparsely")=false)) + + .def("GetShutterOpenAttr", + &This::GetShutterOpenAttr) + .def("CreateShutterOpenAttr", + &_CreateShutterOpenAttr, + (arg("defaultValue")=object(), + arg("writeSparsely")=false)) + + .def("GetShutterCloseAttr", + &This::GetShutterCloseAttr) + .def("CreateShutterCloseAttr", + &_CreateShutterCloseAttr, + (arg("defaultValue")=object(), + arg("writeSparsely")=false)) ; From 18a1d38feee3661f3204d8d23f01d4db3baf9ffc Mon Sep 17 00:00:00 2001 From: superfunc Date: Mon, 26 Sep 2016 18:24:35 -0700 Subject: [PATCH 192/380] [Usd] Ensure relationship targets get updated when flattening masters. (Internal change: 1657971) --- pxr/usd/lib/usd/stage.cpp | 33 ++++++++++++++++++++++++++++++--- pxr/usd/lib/usd/stage.h | 10 ++++++---- 2 files changed, 36 insertions(+), 7 deletions(-) diff --git a/pxr/usd/lib/usd/stage.cpp b/pxr/usd/lib/usd/stage.cpp index 0faacad449..af53fe2f9d 100644 --- a/pxr/usd/lib/usd/stage.cpp +++ b/pxr/usd/lib/usd/stage.cpp @@ -3460,6 +3460,30 @@ namespace { using _MasterToFlattenedPathMap = std::unordered_map; +SdfPath +_GenerateTranslatedTargetPath(const SdfPath& inputPath, + const _MasterToFlattenedPathMap& masterToFlattened) +{ + if (inputPath == SdfPath::AbsoluteRootPath()) { + return inputPath; + } + + // Master prims will always be the root + auto prefix = inputPath; + for ( ; prefix.GetParentPath() != SdfPath::AbsoluteRootPath(); + prefix = prefix.GetParentPath()) { + + // Nothing to do here, just climbing to the parent path + } + + auto replacement = masterToFlattened.find(prefix); + if (replacement == end(masterToFlattened)) { + return inputPath; + } + + return inputPath.ReplacePrefix(prefix, replacement->second); +} + // We want to give generated masters in the flattened stage // reserved(using '__' as a prefix), unclashing paths, however, // we don't want to use the '__Master' paths which have special @@ -3599,7 +3623,7 @@ UsdStage::_FlattenPrim(const UsdPrim &usdPrim, _CopyMetadata(usdPrim, newPrim); for (auto const &prop : usdPrim.GetAuthoredProperties()) { - _CopyProperty(prop, newPrim); + _CopyProperty(prop, newPrim, masterToFlattened); } } @@ -3626,7 +3650,9 @@ UsdStage::_CopyMasterPrim(const UsdPrim &masterPrim, void UsdStage::_CopyProperty(const UsdProperty &prop, - const SdfPrimSpecHandle &dest) const + const SdfPrimSpecHandle &dest, + const _MasterToFlattenedPathMap + &masterToFlattened) const { if (prop.Is()) { UsdAttribute attr = prop.As(); @@ -3682,7 +3708,8 @@ UsdStage::_CopyProperty(const UsdProperty &prop, SdfTargetsProxy sdfTargets = sdfRel->GetTargetPathList(); sdfTargets.ClearEditsAndMakeExplicit(); for (auto const& path : targets) { - sdfTargets.Add(path); + sdfTargets.Add(_GenerateTranslatedTargetPath(path, + masterToFlattened)); } } } diff --git a/pxr/usd/lib/usd/stage.h b/pxr/usd/lib/usd/stage.h index a6aad2ee57..bde7a3cfa9 100644 --- a/pxr/usd/lib/usd/stage.h +++ b/pxr/usd/lib/usd/stage.h @@ -1128,14 +1128,16 @@ class UsdStage : public TfRefBase, public TfWeakBase { // --------------------------------------------------------------------- // // Spec Existence & Definition Helpers // --------------------------------------------------------------------- // + using _MasterToFlattenedPathMap + = std::unordered_map; + void _CopyMetadata(const UsdObject &source, const SdfSpecHandle& dest) const; void _CopyProperty(const UsdProperty &prop, - const SdfPrimSpecHandle& dest) const; - - using _MasterToFlattenedPathMap - = std::unordered_map; + const SdfPrimSpecHandle& dest, + const _MasterToFlattenedPathMap + &masterToFlattened) const; void _CopyMasterPrim(const UsdPrim &masterPrim, const SdfLayerHandle &destinationLyer, From 0fe5e6502919cbf4c85949b9c4229f30db3b5457 Mon Sep 17 00:00:00 2001 From: mattyjams Date: Mon, 26 Sep 2016 18:24:45 -0700 Subject: [PATCH 193/380] add support for exporting user-tagged Maya attributes as primvars and usdRi attributes This change fleshes out the metadata schema for the JSON blob stored in the 'USD_UserExportedAttributesJson' attribute on Maya nodes to allow specifying which type of attribute a particular Maya node should be exported as. Primvars can also have their interpolation specified. It includes changes to the Maya widget to allow authoring these opinions when tagging attributes for export. (Internal change: 1658018) --- .../lib/usdMaya/userExportedAttributesUI.py | 196 ++++++++++++-- third_party/maya/lib/usdMaya/writeUtil.cpp | 255 +++++++++++++++--- third_party/maya/lib/usdMaya/writeUtil.h | 49 +++- 3 files changed, 437 insertions(+), 63 deletions(-) diff --git a/third_party/maya/lib/usdMaya/userExportedAttributesUI.py b/third_party/maya/lib/usdMaya/userExportedAttributesUI.py index 5cfbed65bf..8c635dd987 100644 --- a/third_party/maya/lib/usdMaya/userExportedAttributesUI.py +++ b/third_party/maya/lib/usdMaya/userExportedAttributesUI.py @@ -23,6 +23,8 @@ # import json +from pxr import UsdGeom + from maya import cmds from maya.app.general import mayaMixin @@ -31,6 +33,25 @@ EXPORTED_ATTRS_MAYA_ATTR_NAME = 'USD_UserExportedAttributesJson' +USD_ATTR_TYPE_USD = 'USD' +USD_ATTR_TYPE_PRIMVAR = 'primvar' +USD_ATTR_TYPE_USDRI = 'usdRi' + +USD_ATTR_TYPE_OPTIONS = [ + USD_ATTR_TYPE_USD, + USD_ATTR_TYPE_PRIMVAR, + USD_ATTR_TYPE_USDRI +] + +# The first empty string option here allows the interpolation to be un-specified. +PRIMVAR_INTERPOLATION_OPTIONS = [ + '', + UsdGeom.Tokens.constant, + UsdGeom.Tokens.uniform, + UsdGeom.Tokens.vertex, + UsdGeom.Tokens.faceVarying +] + RESERVED_ATTRIBUTES = set([EXPORTED_ATTRS_MAYA_ATTR_NAME]) ITEM_MIME_TYPE = 'application/x-maya-usdmaya-user-exported-attributes' @@ -45,16 +66,42 @@ class ExportedAttribute(object): def __init__(self, mayaAttrName): self._mayaAttrName = mayaAttrName + self._usdAttrType = None self._usdAttrName = None + self._primvarInterpolation = None def __eq__(self, other): + # Note that _primvarInterpolation does not factor in here. return (self._mayaAttrName == other._mayaAttrName and + self._usdAttrType == other._usdAttrType and self._usdAttrName == other._usdAttrName) @property def mayaAttrName(self): return self._mayaAttrName + @property + def usdAttrType(self): + if self._usdAttrType is None: + return USD_ATTR_TYPE_USD + + return self._usdAttrType + + @usdAttrType.setter + def usdAttrType(self, value): + exportableAttrTypes = [ + USD_ATTR_TYPE_PRIMVAR, + USD_ATTR_TYPE_USDRI + ] + if value not in exportableAttrTypes: + self._usdAttrType = None + else: + self._usdAttrType = value + + # Clear out interpolation as well if this is not a primvar. + if value != USD_ATTR_TYPE_PRIMVAR: + self._primvarInterpolation = None + @property def usdAttrName(self): return self._usdAttrName @@ -66,14 +113,36 @@ def usdAttrName(self, value): else: self._usdAttrName = value + @property + def primvarInterpolation(self): + return self._primvarInterpolation + + @primvarInterpolation.setter + def primvarInterpolation(self, value): + exportableInterpolations = [ + UsdGeom.Tokens.constant, + UsdGeom.Tokens.uniform, + UsdGeom.Tokens.vertex, + UsdGeom.Tokens.faceVarying + ] + if (self._usdAttrType != USD_ATTR_TYPE_PRIMVAR or + value not in exportableInterpolations): + self._primvarInterpolation = None + else: + self._primvarInterpolation = value + def GetJsonDict(self): """ This method returns a dictionary representation of this object that can be dumped to JSON. """ result = { self._mayaAttrName : {} } + if self._usdAttrType: + result[self._mayaAttrName]['usdAttrType'] = self._usdAttrType if self._usdAttrName: result[self._mayaAttrName]['usdAttrName'] = self._usdAttrName + if self._primvarInterpolation: + result[self._mayaAttrName]['interpolation'] = self._primvarInterpolation return result @staticmethod @@ -96,7 +165,9 @@ def GetExportedAttributesFromNode(nodeName): for mayaAttrName in sorted(jsonDict.keys()): exportedAttr = ExportedAttribute(mayaAttrName) attrMetadata = jsonDict[mayaAttrName] + exportedAttr.usdAttrType = attrMetadata.get('usdAttrType') exportedAttr.usdAttrName = attrMetadata.get('usdAttrName') + exportedAttr.primvarInterpolation = attrMetadata.get('interpolation') result.append(exportedAttr) return result @@ -176,11 +247,15 @@ class ExportedAttributesModel(QtCore.QAbstractTableModel): model changes. """ MAYA_ATTR_NAME_COLUMN = 0 - USD_ATTR_NAME_COLUMN = 1 - NUM_COLUMNS = 2 + USD_ATTR_TYPE_COLUMN = 1 + USD_ATTR_NAME_COLUMN = 2 + PRIMVAR_INTERPOLATION_COLUMN = 3 + NUM_COLUMNS = 4 - def __init__(self, exportedAttrs=[], parent=None): + def __init__(self, exportedAttrs=None, parent=None): super(ExportedAttributesModel, self).__init__(parent=parent) + if exportedAttrs is None: + exportedAttrs = [] self._exportedAttrs = exportedAttrs @property @@ -192,27 +267,42 @@ def exportedAttributes(self, exportedAttrs): self._exportedAttrs = exportedAttrs self.reset() - def rowCount(self, parent): + def rowCount(self, parent=QtCore.QModelIndex()): if not self._exportedAttrs: return 0 return len(self._exportedAttrs) - def columnCount(self, parent): + def columnCount(self, parent=QtCore.QModelIndex()): if not self.rowCount(parent): return 0 return ExportedAttributesModel.NUM_COLUMNS def headerData(self, section, orientation, role): - COLUMN_HEADERS = ["Maya Attribute Name", "USD Attribute Name"] - - if orientation == QtCore.Qt.Horizontal and role == QtCore.Qt.DisplayRole: + COLUMN_HEADERS = [ + 'Maya Attribute Name', + 'USD Attribute Type', + 'USD Attribute Name', + 'Interpolation'] + + COLUMN_TOOLTIPS = [ + 'The name of the Maya node attribute to be exported to USD', + 'The type of attribute to create in USD', + 'Which name to use for the attribute in USD (defaults to Maya Attribute Name if empty)', + 'Which interpolation to use for primvar-type attributes' + ] + + if role == QtCore.Qt.DisplayRole: return COLUMN_HEADERS[section] + elif role == QtCore.Qt.ToolTipRole: + return COLUMN_TOOLTIPS[section] return None - def data(self, index, role): + def data(self, index, role=QtCore.Qt.DisplayRole): + value = None + if not self._exportedAttrs or not index.isValid() or role != QtCore.Qt.DisplayRole: - return None + return value row = index.row() column = index.column() @@ -220,26 +310,32 @@ def data(self, index, role): exportedAttr = self._exportedAttrs[row] if column == ExportedAttributesModel.MAYA_ATTR_NAME_COLUMN: value = exportedAttr.mayaAttrName + elif column == ExportedAttributesModel.USD_ATTR_TYPE_COLUMN: + value = exportedAttr.usdAttrType elif column == ExportedAttributesModel.USD_ATTR_NAME_COLUMN: value = exportedAttr.usdAttrName - else: - return None + elif column == ExportedAttributesModel.PRIMVAR_INTERPOLATION_COLUMN: + value = exportedAttr.primvarInterpolation return value - def setData(self, index, value, role): + def setData(self, index, value, role=QtCore.Qt.EditRole): if not self._exportedAttrs: return False row = index.row() column = index.column() - # Currently, only the usdAttrName is editable. - if column != ExportedAttributesModel.USD_ATTR_NAME_COLUMN: - return False - exportedAttr = self._exportedAttrs[row] - exportedAttr.usdAttrName = value + + if column == ExportedAttributesModel.USD_ATTR_TYPE_COLUMN: + exportedAttr.usdAttrType = value + elif column == ExportedAttributesModel.USD_ATTR_NAME_COLUMN: + exportedAttr.usdAttrName = value + elif column == ExportedAttributesModel.PRIMVAR_INTERPOLATION_COLUMN: + exportedAttr.primvarInterpolation = value + else: + return False # Update the selected nodes with the new data. selectedNodeNames = cmds.ls(selection=True, long=True) @@ -259,10 +355,17 @@ def flags(self, index): itemFlags = (QtCore.Qt.ItemIsEnabled | QtCore.Qt.ItemIsSelectable) - if index.column() == ExportedAttributesModel.MAYA_ATTR_NAME_COLUMN: + column = index.column() + if column == ExportedAttributesModel.MAYA_ATTR_NAME_COLUMN: itemFlags |= QtCore.Qt.ItemIsDragEnabled - elif index.column() == ExportedAttributesModel.USD_ATTR_NAME_COLUMN: + elif (column == ExportedAttributesModel.USD_ATTR_TYPE_COLUMN or + column == ExportedAttributesModel.USD_ATTR_NAME_COLUMN): itemFlags |= QtCore.Qt.ItemIsEditable + elif column == ExportedAttributesModel.PRIMVAR_INTERPOLATION_COLUMN: + # The primvar column is only editable if this is a primvar. + exportedAttr = self._exportedAttrs[index.row()] + if exportedAttr.usdAttrType == USD_ATTR_TYPE_PRIMVAR: + itemFlags |= QtCore.Qt.ItemIsEditable return itemFlags @@ -299,6 +402,37 @@ def dropMimeData(self, mimeData, action, row, column, parent): return True +class ExportedAttributesViewItemDelegate(QtGui.QStyledItemDelegate): + + def __init__(self, choices, parent=None): + super(ExportedAttributesViewItemDelegate, self).__init__(parent=parent) + self._choices = choices + + def createEditor(self, parent, option, index): + editor = QtGui.QComboBox(parent) + editor.addItems(self._choices) + + # Use the model data to pre-select a choice in the combo box. + currentValue = index.model().data(index) + if currentValue in self._choices: + currentIndex = self._choices.index(currentValue) + editor.setCurrentIndex(currentIndex) + + editor.currentIndexChanged.connect(self.currentIndexChanged) + return editor + + def setEditorData(self, editor, index): + editor.blockSignals(True) + editor.setCurrentIndex(editor.currentIndex()) + editor.blockSignals(False) + + def setModelData(self, editor, model, index): + model.setData(index, editor.currentText()) + + def currentIndexChanged(self): + self.commitData.emit(self.sender()) + + class ExportedAttributesView(QtGui.QTableView): def __init__(self, parent=None): @@ -306,6 +440,12 @@ def __init__(self, parent=None): self.setDragEnabled(True) self.setAcceptDrops(True) + self.setItemDelegateForColumn(ExportedAttributesModel.USD_ATTR_TYPE_COLUMN, + ExportedAttributesViewItemDelegate(USD_ATTR_TYPE_OPTIONS, self)) + + self.setItemDelegateForColumn(ExportedAttributesModel.PRIMVAR_INTERPOLATION_COLUMN, + ExportedAttributesViewItemDelegate(PRIMVAR_INTERPOLATION_OPTIONS, self)) + def dragEnterEvent(self, event): if event.source() == self: event.ignore() @@ -540,6 +680,22 @@ def _syncUI(self): commonExportedAttrs = [commonExportedAttrs[x] for x in commonExportedAttributeNames] commonExportedAttrs.sort(key=lambda x: x.mayaAttrName) self.exportedAttrsModel.exportedAttributes = commonExportedAttrs + + # Normally, the combo boxes for selecting usdAttrType and + # primvarInterpolation would only appear when the table cell is put into + # edit mode. Instead, we want the combo boxes to always be visible, so + # we tell the view to open them as persistent editors. + for row in xrange(self.exportedAttrsModel.rowCount()): + usdAttrTypeIndex = self.exportedAttrsModel.index(row, + ExportedAttributesModel.USD_ATTR_TYPE_COLUMN) + self.exportedAttrsView.openPersistentEditor(usdAttrTypeIndex) + + # Only open the interpolation editor if this is a primvar. + if self.exportedAttrsModel.data(usdAttrTypeIndex) == USD_ATTR_TYPE_PRIMVAR: + primvarInterpolationIndex = self.exportedAttrsModel.index(row, + ExportedAttributesModel.PRIMVAR_INTERPOLATION_COLUMN) + self.exportedAttrsView.openPersistentEditor(primvarInterpolationIndex) + self.exportedAttrsView.resizeColumnsToContents() # Collect the attributes common to all selected nodes. diff --git a/third_party/maya/lib/usdMaya/writeUtil.cpp b/third_party/maya/lib/usdMaya/writeUtil.cpp index 762a80892a..9806ad3d2c 100644 --- a/third_party/maya/lib/usdMaya/writeUtil.cpp +++ b/third_party/maya/lib/usdMaya/writeUtil.cpp @@ -28,8 +28,17 @@ #include "pxr/base/js/value.h" #include "pxr/base/tf/staticTokens.h" #include "pxr/base/tf/stringUtils.h" +#include "pxr/base/tf/token.h" +#include "pxr/base/vt/types.h" +#include "pxr/usd/sdf/valueTypeName.h" #include "pxr/usd/usd/attribute.h" #include "pxr/usd/usd/prim.h" +#include "pxr/usd/usd/property.h" +#include "pxr/usd/usd/timeCode.h" +#include "pxr/usd/usdGeom/imageable.h" +#include "pxr/usd/usdGeom/primvar.h" +#include "pxr/usd/usdGeom/tokens.h" +#include "pxr/usd/usdRi/statements.h" #include #include @@ -56,12 +65,17 @@ #include #include +#include +#include TF_DEFINE_PRIVATE_TOKENS( _tokens, (USD_UserExportedAttributesJson) (usdAttrName) + (usdAttrType) + ((USDAttrTypePrimvar, "primvar")) + ((USDAttrTypeUsdRi, "usdRi")) ); @@ -180,40 +194,137 @@ PxrUsdMayaWriteUtil::GetUsdTypeName( const MPlug& plg) return attrType; } - +/* static */ UsdAttribute PxrUsdMayaWriteUtil::GetOrCreateUsdAttr( - const MPlug& plg, + const MPlug& attrPlug, const UsdPrim& usdPrim, - const std::string &attrName, - bool custom) + const std::string& attrName, + const bool custom) { - MObject attrObj(plg.attribute()); + UsdAttribute usdAttr; - TfToken usdAttrName(attrName); - if (usdAttrName.IsEmpty()) { - printf("Invalid attrName '%s' for %s\n", - attrName.c_str(), - plg.name().asChar()); - return UsdAttribute(); + if (not usdPrim) { + return usdAttr; } - - // See if usdAttr already exists. If so, return. - UsdAttribute usdAttr = usdPrim.GetAttribute(usdAttrName); + + MObject attrObj(attrPlug.attribute()); + + TfToken usdAttrNameToken(attrName); + if (usdAttrNameToken.IsEmpty()) { + MGlobal::displayError( + TfStringPrintf("Invalid USD attribute name '%s' for Maya plug '%s'", + attrName.c_str(), + attrPlug.name().asChar()).c_str()); + return usdAttr; + } + + // See if the USD attribute already exists. If so, return it. + usdAttr = usdPrim.GetAttribute(usdAttrNameToken); if (usdAttr) { return usdAttr; } - SdfValueTypeName attrType = PxrUsdMayaWriteUtil::GetUsdTypeName(plg); + const SdfValueTypeName& typeName = PxrUsdMayaWriteUtil::GetUsdTypeName(attrPlug); + if (typeName) { + usdAttr = usdPrim.CreateAttribute(usdAttrNameToken, typeName, custom); + } + + return usdAttr; +} + +/* static */ +UsdGeomPrimvar PxrUsdMayaWriteUtil::GetOrCreatePrimvar( + const MPlug& attrPlug, + UsdGeomImageable& imageable, + const std::string& primvarName, + const TfToken& interpolation, + const int elementSize, + const bool custom) +{ + UsdGeomPrimvar primvar; - // --------------------- - // CreateAttribute on USD Prim if specified above - if (attrType) { - usdAttr = usdPrim.CreateAttribute(usdAttrName, attrType, custom); + if (not imageable) { + return primvar; } - else { - // Skipping. Unsupported type. + + MObject attrObj(attrPlug.attribute()); + + TfToken primvarNameToken(primvarName); + if (primvarNameToken.IsEmpty()) { + MGlobal::displayError( + TfStringPrintf("Invalid primvar name '%s' for Maya plug '%s'", + primvarName.c_str(), + attrPlug.name().asChar()).c_str()); + return primvar; + } + + // See if the primvar already exists. If so, return it. + primvar = imageable.GetPrimvar(primvarNameToken); + if (primvar) { + return primvar; + } + + const SdfValueTypeName& typeName = PxrUsdMayaWriteUtil::GetUsdTypeName(attrPlug); + if (typeName) { + primvar = imageable.CreatePrimvar(primvarNameToken, + typeName, + interpolation, + elementSize, + custom); + } + + return primvar; +} + +/* static */ +UsdAttribute PxrUsdMayaWriteUtil::GetOrCreateUsdRiAttribute( + const MPlug& attrPlug, + const UsdPrim& usdPrim, + const std::string& attrName, + const std::string& nameSpace) +{ + UsdAttribute usdAttr; + + if (not usdPrim) { + return usdAttr; } + + MObject attrObj(attrPlug.attribute()); + + TfToken riAttrNameToken(attrName); + if (riAttrNameToken.IsEmpty()) { + MGlobal::displayError( + TfStringPrintf("Invalid UsdRi attribute name '%s' for Maya plug '%s'", + attrName.c_str(), + attrPlug.name().asChar()).c_str()); + return usdAttr; + } + + UsdRiStatements riStatements(usdPrim); + if (not riStatements) { + return usdAttr; + } + + // See if a UsdRi attribute with this name already exists. If so, return it. + // XXX: There isn't currently API for looking for a specific UsdRi attribute + // by name, so we have to get them all and then see if one matches. + const std::vector& riAttrs = riStatements.GetRiAttributes(nameSpace); + TF_FOR_ALL(iter, riAttrs) { + if (iter->GetBaseName() == riAttrNameToken) { + // Re-get the attribute from the prim so we can return it as a + // UsdAttribute rather than a UsdProperty. + return usdPrim.GetAttribute(iter->GetName()); + } + } + + const SdfValueTypeName& typeName = PxrUsdMayaWriteUtil::GetUsdTypeName(attrPlug); + if (typeName) { + usdAttr = riStatements.CreateRiAttribute(riAttrNameToken, + typeName.GetType(), + nameSpace); + } + return usdAttr; } @@ -448,6 +559,21 @@ PxrUsdMayaWriteUtil::SetUsdAttr( return true; } +static +std::string +_GetExportAttributeMetadata( + const JsObject& attrMetadata, + const TfToken& keyToken) +{ + std::string value; + JsObject::const_iterator attrMetadataIter = attrMetadata.find(keyToken); + if (attrMetadataIter != attrMetadata.end()) { + value = attrMetadataIter->second.GetString(); + } + + return value; +} + // This method inspects the JSON blob stored in the 'USD_UserExportedAttributesJson' // attribute on the Maya node at dagPath and exports any attributes specified // there onto usdPrim at time usdTime. The JSON should contain an object that @@ -459,7 +585,17 @@ PxrUsdMayaWriteUtil::SetUsdAttr( // }, // "myMayaAttributeTwo": { // "usdAttrName": "my:namespace:attributeTwo" -// } +// }, +// "attributeAsPrimvar": { +// "usdAttrType": "primvar" +// }, +// "attributeAsVertexInterpPrimvar": { +// "usdAttrType": "primvar", +// "interpolation": "vertex" +// }, +// "attributeAsRibAttribute": { +// "usdAttrType": "usdRi" +// }, // } // // If the attribute metadata contains a value for "usdAttrName", the attribute @@ -524,15 +660,12 @@ PxrUsdMayaWriteUtil::WriteUserExportedAttributes( const JsObject& attrMetadata = iter->second.GetJsObject(); - // Check the metadata to see if the USD attribute name should be - // different than the Maya attribute name. - std::string usdAttrName = mayaAttrName; - JsObject::const_iterator usdAttrValueIter = attrMetadata.find(_tokens->usdAttrName); - if (usdAttrValueIter != attrMetadata.end()) { - std::string nameValue = usdAttrValueIter->second.GetString(); - if (not nameValue.empty()) { - usdAttrName = nameValue; - } + // Check whether the USD attribute name should be different than the + // Maya attribute name. + std::string usdAttrName = + _GetExportAttributeMetadata(attrMetadata, _tokens->usdAttrName); + if (usdAttrName.empty()) { + usdAttrName = mayaAttrName; } const auto& insertIter = exportedUsdAttrNames.insert(usdAttrName); @@ -545,10 +678,64 @@ PxrUsdMayaWriteUtil::WriteUserExportedAttributes( continue; } - UsdAttribute usdAttr = PxrUsdMayaWriteUtil::GetOrCreateUsdAttr( - attrPlug, usdPrim, usdAttrName, true); + // Check if this is a particular type of attribute (e.g. primvar or + // usdRi attribute). If we don't recognize the type specified, we'll + // fall back to a regular USD attribute. + TfToken usdAttrType( + _GetExportAttributeMetadata(attrMetadata, _tokens->usdAttrType)); + + // Check whether an interpolation type was specified. This is only + // relevant for primvars. + TfToken interpolation( + _GetExportAttributeMetadata(attrMetadata, + UsdGeomTokens->interpolation)); + + UsdAttribute usdAttr; + + if (usdAttrType == _tokens->USDAttrTypePrimvar) { + UsdGeomImageable imageable(usdPrim); + if (not imageable) { + MGlobal::displayError( + TfStringPrintf( + "Cannot create primvar for non-UsdGeomImageable USD prim: '%s'", + usdPrim.GetPath().GetText()).c_str()); + continue; + } + UsdGeomPrimvar primvar = + PxrUsdMayaWriteUtil::GetOrCreatePrimvar(attrPlug, + imageable, + usdAttrName, + interpolation, + -1, + true); + if (primvar) { + usdAttr = primvar.GetAttr(); + } + } else if (usdAttrType == _tokens->USDAttrTypeUsdRi) { + usdAttr = + PxrUsdMayaWriteUtil::GetOrCreateUsdRiAttribute(attrPlug, + usdPrim, + usdAttrName); + } else { + usdAttr = PxrUsdMayaWriteUtil::GetOrCreateUsdAttr(attrPlug, + usdPrim, + usdAttrName, + true); + } + if (usdAttr) { - PxrUsdMayaWriteUtil::SetUsdAttr(attrPlug, usdAttr, usdTime); + if (not PxrUsdMayaWriteUtil::SetUsdAttr(attrPlug, usdAttr, usdTime)) { + MGlobal::displayError( + TfStringPrintf("Could not set value for attribute: '%s'", + usdAttr.GetPath().GetText()).c_str()); + continue; + } + } else { + MGlobal::displayError( + TfStringPrintf("Could not create attribute '%s' for USD prim: '%s'", + usdAttrName.c_str(), + usdPrim.GetPath().GetText()).c_str()); + continue; } } diff --git a/third_party/maya/lib/usdMaya/writeUtil.h b/third_party/maya/lib/usdMaya/writeUtil.h index 9c91acb2ad..adedb0e46d 100644 --- a/third_party/maya/lib/usdMaya/writeUtil.h +++ b/third_party/maya/lib/usdMaya/writeUtil.h @@ -21,37 +21,68 @@ // KIND, either express or implied. See the Apache License for the specific // language governing permissions and limitations under the Apache License. // + +/// \file writeUtil.h + #ifndef PXRUSDMAYA_WRITEUTIL_H #define PXRUSDMAYA_WRITEUTIL_H +#include "pxr/base/tf/token.h" +#include "pxr/base/vt/types.h" +#include "pxr/usd/sdf/valueTypeName.h" #include "pxr/usd/usd/attribute.h" #include "pxr/usd/usd/prim.h" +#include "pxr/usd/usd/timeCode.h" +#include "pxr/usd/usdGeom/imageable.h" +#include "pxr/usd/usdGeom/primvar.h" + #include #include #include +#include + +#include + struct PxrUsdMayaWriteUtil { /// \name Helpers for writing USD /// \{ - /// Given an \p attrPlug, try to create and attribute on \p usdPrim with - /// the name \p attrName. Note, it's value will not be set. + /// Get the SdfValueTypeName that corresponds to the given plug \p attrPlug. + static SdfValueTypeName GetUsdTypeName(const MPlug& attrPlug); + + /// Given an \p attrPlug, try to create a USD attribute on \p usdPrim with + /// the name \p attrName. Note, it's value will not be set. /// /// Attributes that are not part of the primSchema should have \p custom /// set to true. - static SdfValueTypeName GetUsdTypeName( const MPlug& attrPlug ); + static UsdAttribute GetOrCreateUsdAttr( + const MPlug& attrPlug, + const UsdPrim& usdPrim, + const std::string& attrName, + const bool custom = false); - /// Given an \p attrPlug, try to create and attribute on \p usdPrim with - /// the name \p attrName. Note, it's value will not be set. + /// Given an \p attrPlug, try to create a primvar on \p imageable with + /// the name \p primvarName. Note, it's value will not be set. /// /// Attributes that are not part of the primSchema should have \p custom /// set to true. - static UsdAttribute GetOrCreateUsdAttr( - const MPlug& attrPlug, + static UsdGeomPrimvar GetOrCreatePrimvar( + const MPlug& attrPlug, + UsdGeomImageable& imageable, + const std::string& primvarName, + const TfToken& interpolation = TfToken(), + const int elementSize = -1, + const bool custom = false); + + /// Given an \p attrPlug, try to create a UsdRi attribute on \p usdPrim with + /// the name \p attrName. Note, it's value will not be set. + static UsdAttribute GetOrCreateUsdRiAttribute( + const MPlug& attrPlug, const UsdPrim& usdPrim, - const std::string &attrName, - bool custom); + const std::string& attrName, + const std::string& nameSpace = "user"); /// Given an \p attrPlug, determine it's value and set it on \p usdAttr at /// \p usdTime. From 62aa02a2122e8b5b1495ca4c03330e230cd801f7 Mon Sep 17 00:00:00 2001 From: mattyjams Date: Mon, 26 Sep 2016 18:25:15 -0700 Subject: [PATCH 194/380] follow-up to change 1656801: Add pyAnnotatedBoolResult to CMakeLists.txt (Internal change: 1658040) --- pxr/base/lib/tf/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/pxr/base/lib/tf/CMakeLists.txt b/pxr/base/lib/tf/CMakeLists.txt index 7852d715de..c82287b118 100644 --- a/pxr/base/lib/tf/CMakeLists.txt +++ b/pxr/base/lib/tf/CMakeLists.txt @@ -57,6 +57,7 @@ pxr_shared_library(tf patternMatcher pointerAndBits poolAllocator + pyAnnotatedBoolResult pyArg pyCall pyClassMethod From 74b120084df8eac105e852ea883d3028b9ca61e9 Mon Sep 17 00:00:00 2001 From: mattyjams Date: Tue, 27 Sep 2016 14:24:21 -0700 Subject: [PATCH 195/380] fix signed vs. unsigned comparisons (Internal change: 1658170) --- third_party/maya/lib/usdMaya/MayaNurbsSurfaceWriter.cpp | 6 +++--- third_party/maya/lib/usdMaya/translatorMesh_PrimVars.cpp | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/third_party/maya/lib/usdMaya/MayaNurbsSurfaceWriter.cpp b/third_party/maya/lib/usdMaya/MayaNurbsSurfaceWriter.cpp index 4fb6712048..9df90f8e65 100644 --- a/third_party/maya/lib/usdMaya/MayaNurbsSurfaceWriter.cpp +++ b/third_party/maya/lib/usdMaya/MayaNurbsSurfaceWriter.cpp @@ -60,15 +60,15 @@ _FixNormalizedKnotRange( if (startVal < knots[degree]) { changeVal = knots[degree]; - for (int i=0; i<=degree; ++i) { + for (unsigned int i = 0; i <= degree; ++i) { if (knots[i] == changeVal) { knots[i] = startVal; } } } if (endVal > knots[numKnots - (degree + 1)]) { - changeVal = knots[numKnots - (degree+1)]; - for (int i=numKnots - (degree+1); i(uvId) < assignmentIndices.size()) { // The data is indexed, so consult the indices array for the // correct index into the data. uvId = assignmentIndices[uvId]; From 3bcf320ea18d36f9135f8cb154e103690c6fe969 Mon Sep 17 00:00:00 2001 From: pixar-oss Date: Tue, 27 Sep 2016 14:24:28 -0700 Subject: [PATCH 196/380] Avoid destroying MallogTag thread local data. MallocTag keeps some thread local data around to track the stack of tags among other things. We allocated this using "static thread_local _ThreadData data". This meant the object was destroyed when the thread exited. But controlling the order of object destruction is hard and some objects destroyed later were doing memory allocation and deallocation. That would re-enter MallocTag and try to access the destroyed _ThreadData. This change allocates and constructs the _ThreadData in such a way that we neither use the heap nor destroy the object. We unfortunately leak the blocks allocated on the heap by the members in _ThreadData. (Internal change: 1658244) --- pxr/base/lib/tf/mallocTag.cpp | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/pxr/base/lib/tf/mallocTag.cpp b/pxr/base/lib/tf/mallocTag.cpp index 820e1f57d4..0cbf1333a9 100644 --- a/pxr/base/lib/tf/mallocTag.cpp +++ b/pxr/base/lib/tf/mallocTag.cpp @@ -45,6 +45,7 @@ #include #include #include +#include #include #include @@ -841,8 +842,18 @@ class TfMallocTag::Tls { Find() { #if defined(ARCH_HAS_THREAD_LOCAL) - static thread_local _ThreadData data; - return &data; + // This weirdness is so we don't use the heap and we don't call + // the destructor of _ThreadData when the thread is exiting. + // We can't do the latter because we don't know in what order + // objects will be destroyed and objects destroyed after the + // _ThreadData may do heap (de)allocation, which requires the + // _ThreadData object. We leak the heap allocated blocks in + // the _ThreadData. + static thread_local + std::aligned_storage::type dataBuffer; + static thread_local _ThreadData* data = new (&dataBuffer) _ThreadData; + return data; #else TF_FATAL_ERROR("TfMallocTag not supported on platforms " "without thread_local"); From 7a9bd49bb0ddd18bff37f2e9af7c80fe0aac69af Mon Sep 17 00:00:00 2001 From: Aaron Luk Date: Wed, 28 Sep 2016 16:28:10 +0200 Subject: [PATCH 197/380] [Tf] Add wrapTestPyAnnotatedBoolResult to build, fixing linking errors. --- pxr/base/lib/tf/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/pxr/base/lib/tf/CMakeLists.txt b/pxr/base/lib/tf/CMakeLists.txt index c82287b118..c28e7c8f62 100644 --- a/pxr/base/lib/tf/CMakeLists.txt +++ b/pxr/base/lib/tf/CMakeLists.txt @@ -174,6 +174,7 @@ pxr_shared_library(tf wrapStopwatch.cpp wrapStringUtils.cpp wrapTemplateString.cpp + wrapTestPyAnnotatedBoolResult.cpp wrapTestPyContainerConversions.cpp wrapTestPyDateTime.cpp wrapTestPyStaticTokens.cpp From 48d61fff01d5c79b1a133bb4043ce9b04b4e92fb Mon Sep 17 00:00:00 2001 From: spiffmon Date: Mon, 17 Oct 2016 13:33:05 -0700 Subject: [PATCH 198/380] Open stage fully populated before creating overs in session layer, so that we get favorable reloading behavior when new payloads appear in response to editing. This has the happy knock-on effect of cutting the stage-loading time just about in half. (Internal change: 1658315) --- pxr/usdImaging/lib/usdviewq/mainWindow.py | 23 +++++++++-------------- 1 file changed, 9 insertions(+), 14 deletions(-) diff --git a/pxr/usdImaging/lib/usdviewq/mainWindow.py b/pxr/usdImaging/lib/usdviewq/mainWindow.py index 49dbe907b4..e65873ad36 100644 --- a/pxr/usdImaging/lib/usdviewq/mainWindow.py +++ b/pxr/usdImaging/lib/usdviewq/mainWindow.py @@ -1088,13 +1088,13 @@ def _openStage(self, usdFilePath): Tf.MallocTag.Initialize() with Timer() as t: - if self._noRender: - # no point in optimizing for editing if we're not redrawing - loadSet = Usd.Stage.LoadNone if self._unloaded else Usd.Stage.LoadAll - stage = Usd.Stage.Open(usdFilePath, - self._pathResolverContext, - loadSet) - else: + loadSet = Usd.Stage.LoadNone if self._unloaded else Usd.Stage.LoadAll + stage = Usd.Stage.Open(usdFilePath, + self._pathResolverContext, + loadSet) + + # no point in optimizing for editing if we're not redrawing + if stage and not self._noRender: # as described in bug #99309, UsdStage change processing # can't yet tell the difference between an effectively # "inert" change caused by adding an empty Over primSpec, and @@ -1106,11 +1106,8 @@ def _openStage(self, usdFilePath): # away and start over. Here, we limit the propagation of # invalidation due to creation of new overs to the enclosing # model by pre-populating the session layer with overs for - # the interior of the model hierarchy, very cheaply, by - # creating the overs before we've loaded any models. - stage = Usd.Stage.Open(usdFilePath, - self._pathResolverContext, - Usd.Stage.LoadNone) + # the interior of the model hierarchy, before the renderer + # starts listening for changes. sl = stage.GetSessionLayer() # We can only safely do Sdf-level ops inside an Sdf.ChangeBlock, # so gather all the paths from the UsdStage first @@ -1121,8 +1118,6 @@ def _openStage(self, usdFilePath): for mpp in modelPaths: parent = sl.GetPrimAtPath(mpp.GetParentPath()) Sdf.PrimSpec(parent, mpp.name, Sdf.SpecifierOver) - if not self._unloaded: - stage.GetPseudoRoot().Load() if not stage: print >> sys.stderr, "Error opening stage '" + usdFilePath + "'" else: From 4621d5fabe96d38e8e3a0d7c5a4c45aa77318632 Mon Sep 17 00:00:00 2001 From: gitamohr Date: Mon, 17 Oct 2016 13:33:41 -0700 Subject: [PATCH 199/380] usd: Quick fix for 'IsStreamingLayer' for usdc-backed usd files. This fixes a crash in cases where a .usd file is replaced with new content, and then the file is Reload()ed in an app. (Internal change: 1658433) --- pxr/usd/lib/usd/usdFileFormat.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/pxr/usd/lib/usd/usdFileFormat.cpp b/pxr/usd/lib/usd/usdFileFormat.cpp index 33b190118a..0b5065b70e 100644 --- a/pxr/usd/lib/usd/usdFileFormat.cpp +++ b/pxr/usd/lib/usd/usdFileFormat.cpp @@ -356,6 +356,7 @@ bool UsdUsdFileFormat::_IsStreamingLayer( const SdfLayerBase& layer) const { - return (_GetUnderlyingFileFormatForLayer(&layer)->GetFormatId() == - UsdUsdbFileFormatTokens->Id); + auto formatId = _GetUnderlyingFileFormatForLayer(&layer)->GetFormatId(); + return formatId == UsdUsdbFileFormatTokens->Id || + formatId == UsdUsdcFileFormatTokens->Id; } From c4b06c3f1c024f4ba84508ddc2c9f2ba9b0f1604 Mon Sep 17 00:00:00 2001 From: gitamohr Date: Mon, 17 Oct 2016 13:33:56 -0700 Subject: [PATCH 200/380] sdf: Make sure we mark streaming layers dirty when we call _SetData() on them for mutating operations. (Internal change: 1658690) --- pxr/usd/lib/sdf/layer.cpp | 36 +++++++++++++++++++++++------------- 1 file changed, 23 insertions(+), 13 deletions(-) diff --git a/pxr/usd/lib/sdf/layer.cpp b/pxr/usd/lib/sdf/layer.cpp index c71d251b86..f5e844e240 100644 --- a/pxr/usd/lib/sdf/layer.cpp +++ b/pxr/usd/lib/sdf/layer.cpp @@ -2413,6 +2413,9 @@ SdfLayer::Clear() } _SetData(GetFileFormat()->InitData(GetFileFormatArguments())); + + if (GetFileFormat()->IsStreamingLayer(*this)) + _stateDelegate->_MarkCurrentStateAsDirty(); } bool @@ -2506,22 +2509,29 @@ SdfLayer::TransferContent(const SdfLayerHandle& layer) // multiple layers to be sharing the same data object, so we // have to make a copy of the data here. // - if (_ShouldNotify()) { - if (GetFileFormat()->IsStreamingLayer(*this)) { - SdfAbstractDataRefPtr newData = - GetFileFormat()->InitData(GetFileFormatArguments()); - newData->CopyFrom(layer->_data); - _SetData(newData); - } - else { - _SetData(layer->_data); - } - } else { - SdfAbstractDataRefPtr newData = - GetFileFormat()->InitData(GetFileFormatArguments()); + + bool notify = _ShouldNotify(); + bool isStreamingLayer = GetFileFormat()->IsStreamingLayer(*this); + SdfAbstractDataRefPtr newData; + + if (!notify || isStreamingLayer) { + newData = GetFileFormat()->InitData(GetFileFormatArguments()); newData->CopyFrom(layer->_data); + } + else { + newData = layer->_data; + } + + if (notify) { + _SetData(newData); + } else { _data = newData; } + + // If this is a "streaming" layer, we must mark it dirty. + if (isStreamingLayer) { + _stateDelegate->_MarkCurrentStateAsDirty(); + } } static void From 975d5e4ac8cb060a27a1e9a6b56d4baddc2a2b10 Mon Sep 17 00:00:00 2001 From: mrawde Date: Mon, 17 Oct 2016 13:34:06 -0700 Subject: [PATCH 201/380] more thoroughly remove extendable shaderAdapter logic. (Internal change: 1658814) --- pxr/usdImaging/lib/usdImaging/CMakeLists.txt | 3 +- .../lib/usdImaging/defaultShaderAdapter.h | 58 ------------------- pxr/usdImaging/lib/usdImaging/delegate.cpp | 8 +-- pxr/usdImaging/lib/usdImaging/delegate.h | 15 +++-- ...ultShaderAdapter.cpp => shaderAdapter.cpp} | 16 ++--- pxr/usdImaging/lib/usdImaging/shaderAdapter.h | 37 ++++++------ 6 files changed, 38 insertions(+), 99 deletions(-) delete mode 100644 pxr/usdImaging/lib/usdImaging/defaultShaderAdapter.h rename pxr/usdImaging/lib/usdImaging/{defaultShaderAdapter.cpp => shaderAdapter.cpp} (95%) diff --git a/pxr/usdImaging/lib/usdImaging/CMakeLists.txt b/pxr/usdImaging/lib/usdImaging/CMakeLists.txt index 8384809d05..2bc092d9b4 100644 --- a/pxr/usdImaging/lib/usdImaging/CMakeLists.txt +++ b/pxr/usdImaging/lib/usdImaging/CMakeLists.txt @@ -44,7 +44,6 @@ pxr_shared_library(usdImaging PUBLIC_CLASSES adapterRegistry debugCodes - defaultShaderAdapter delegate engine gl @@ -52,6 +51,7 @@ pxr_shared_library(usdImaging inheritedCache instancerContext refEngine + shaderAdapter tokens valueCache taskDelegate @@ -71,7 +71,6 @@ pxr_shared_library(usdImaging PUBLIC_HEADERS version.h - shaderAdapter.h PRIVATE_CLASSES defaultTaskDelegate diff --git a/pxr/usdImaging/lib/usdImaging/defaultShaderAdapter.h b/pxr/usdImaging/lib/usdImaging/defaultShaderAdapter.h deleted file mode 100644 index ed77329916..0000000000 --- a/pxr/usdImaging/lib/usdImaging/defaultShaderAdapter.h +++ /dev/null @@ -1,58 +0,0 @@ -// -// 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 USDIMAGING_DEFAULTSHADERADAPTER_H -#define USDIMAGING_DEFAULTSHADERADAPTER_H - -#include "pxr/usdImaging/usdImaging/shaderAdapter.h" -#include "pxr/usdImaging/usdImaging/delegate.h" - -/// \class UsdImagingDefaultShaderAdapter -/// \brief An implementation of the shader adapter that uses Usd objects to -/// build up a shading network. -/// -/// Currently, in the absence of any other shaderAdapter registered the delegate -/// will default to using this implementation. -class UsdImagingDefaultShaderAdapter : public UsdImagingShaderAdapter -{ -public: - UsdImagingDefaultShaderAdapter(UsdImagingDelegate* delegate); - - /// \brief Traverses the shading prims and if any of the attributes are time - /// varying, returns true. - bool GetSurfaceShaderIsTimeVarying(SdfPath const& usdPath) const override; - - /// \brief Gets the shading source via the \c UsdHydrShader schema. - std::string GetSurfaceShaderSource(SdfPath const& usdPath) const override; - - TfTokenVector GetSurfaceShaderParamNames(SdfPath const& usdPath) const override; - - VtValue GetSurfaceShaderParamValue(SdfPath const& usdPath, TfToken const& paramName) const override; - HdShaderParamVector GetSurfaceShaderParams(SdfPath const& usdPath) const override; - SdfPathVector GetSurfaceShaderTextures(SdfPath const& usdPath) const override; - -private: - UsdImagingDelegate* _delegate; -}; - -#endif // USDIMAGING_DEFAULTSHADERADAPTER_H diff --git a/pxr/usdImaging/lib/usdImaging/delegate.cpp b/pxr/usdImaging/lib/usdImaging/delegate.cpp index e38fa1b6bb..39eff8544a 100644 --- a/pxr/usdImaging/lib/usdImaging/delegate.cpp +++ b/pxr/usdImaging/lib/usdImaging/delegate.cpp @@ -27,9 +27,9 @@ #include "pxr/usdImaging/usdImaging/adapterRegistry.h" #include "pxr/usdImaging/usdImaging/debugCodes.h" -#include "pxr/usdImaging/usdImaging/defaultShaderAdapter.h" #include "pxr/usdImaging/usdImaging/instanceAdapter.h" #include "pxr/usdImaging/usdImaging/primAdapter.h" +#include "pxr/usdImaging/usdImaging/shaderAdapter.h" #include "pxr/usdImaging/usdImaging/tokens.h" #include "pxr/imaging/glf/ptexTexture.h" @@ -93,7 +93,7 @@ UsdImagingDelegate::UsdImagingDelegate() , _xformCache(GetTime(), GetRootCompensation()) , _materialBindingCache(GetTime(), GetRootCompensation()) , _visCache(GetTime(), GetRootCompensation()) - , _defaultShaderAdapter(boost::make_shared(this)) + , _shaderAdapter(boost::make_shared(this)) { // this constructor create a new render index. HdChangeTracker &tracker = GetRenderIndex().GetChangeTracker(); @@ -127,7 +127,7 @@ UsdImagingDelegate::UsdImagingDelegate( , _xformCache(GetTime(), GetRootCompensation()) , _materialBindingCache(GetTime(), GetRootCompensation()) , _visCache(GetTime(), GetRootCompensation()) - , _defaultShaderAdapter(boost::make_shared(this)) + , _shaderAdapter(boost::make_shared(this)) { HdChangeTracker &tracker = GetRenderIndex().GetChangeTracker(); tracker.AddCollection(UsdImagingCollectionTokens->geometryAndGuides); @@ -259,7 +259,7 @@ UsdImagingDelegate::_ShaderAdapterSharedPtr UsdImagingDelegate::_ShaderAdapterLookup( SdfPath const& shaderId) const { - return _defaultShaderAdapter; + return _shaderAdapter; } // -------------------------------------------------------------------------- // diff --git a/pxr/usdImaging/lib/usdImaging/delegate.h b/pxr/usdImaging/lib/usdImaging/delegate.h index 4d2a026d3e..1c1bb92c9a 100644 --- a/pxr/usdImaging/lib/usdImaging/delegate.h +++ b/pxr/usdImaging/lib/usdImaging/delegate.h @@ -393,9 +393,9 @@ class UsdImagingDelegate : public HdSceneDelegate, public TfWeakBase { friend class UsdImagingIndexProxy; friend class UsdImagingPrimAdapter; - // UsdImagingDefaultShaderAdapter needs access to _GetPrim. We should + // UsdImagingShaderAdapter needs access to _GetPrim. We should // consider making it public. - friend class UsdImagingDefaultShaderAdapter; + friend class UsdImagingShaderAdapter; bool _ValidateRefineLevel(int level) { if (not (0 <= level and level <= 8)) { @@ -518,12 +518,12 @@ class UsdImagingDelegate : public HdSceneDelegate, public TfWeakBase { _PathAdapterMap _pathAdapterMap; typedef UsdImagingShaderAdapterSharedPtr _ShaderAdapterSharedPtr; - typedef SdfPathTable<_ShaderAdapterSharedPtr> _ShaderAdapterMap; - _ShaderAdapterMap _shaderAdapterMap; // This method looks up a shader adapter based on the \p shaderId. - // This will never return a nullptr. If there is no registered shader - // adapter, it will return the "default". + // Currently, it's hard coded to return _shaderAdapter but could be + // extended. + // + // This will never return a nullptr. _ShaderAdapterSharedPtr _ShaderAdapterLookup(SdfPath const& shaderId) const; // XXX: These maps could be store as individual member paths on the Rprim @@ -601,8 +601,7 @@ class UsdImagingDelegate : public HdSceneDelegate, public TfWeakBase { // Collection CollectionMap _collectionMap; - // default shader adapter - boost::shared_ptr _defaultShaderAdapter; + UsdImagingShaderAdapterSharedPtr _shaderAdapter; }; /// \class UsdImagingIndexProxy diff --git a/pxr/usdImaging/lib/usdImaging/defaultShaderAdapter.cpp b/pxr/usdImaging/lib/usdImaging/shaderAdapter.cpp similarity index 95% rename from pxr/usdImaging/lib/usdImaging/defaultShaderAdapter.cpp rename to pxr/usdImaging/lib/usdImaging/shaderAdapter.cpp index 7bf4489e83..5bb7773421 100644 --- a/pxr/usdImaging/lib/usdImaging/defaultShaderAdapter.cpp +++ b/pxr/usdImaging/lib/usdImaging/shaderAdapter.cpp @@ -21,7 +21,7 @@ // KIND, either express or implied. See the Apache License for the specific // language governing permissions and limitations under the Apache License. // -#include "pxr/usdImaging/usdImaging/defaultShaderAdapter.h" +#include "pxr/usdImaging/usdImaging/shaderAdapter.h" #include "pxr/usdImaging/usdImaging/delegate.h" #include "pxr/usdImaging/usdImaging/tokens.h" @@ -36,13 +36,13 @@ #include "pxr/usd/usdHydra/primvar.h" #include "pxr/usd/usdHydra/tokens.h" -UsdImagingDefaultShaderAdapter::UsdImagingDefaultShaderAdapter(UsdImagingDelegate* delegate) +UsdImagingShaderAdapter::UsdImagingShaderAdapter(UsdImagingDelegate* delegate) : _delegate(delegate) { } bool -UsdImagingDefaultShaderAdapter::GetSurfaceShaderIsTimeVarying(SdfPath const& usdPath) const +UsdImagingShaderAdapter::GetSurfaceShaderIsTimeVarying(SdfPath const& usdPath) const { if (UsdPrim p = _delegate->_GetPrim(usdPath)) { const std::vector &attrs = p.GetAttributes(); @@ -57,7 +57,7 @@ UsdImagingDefaultShaderAdapter::GetSurfaceShaderIsTimeVarying(SdfPath const& usd } std::string -UsdImagingDefaultShaderAdapter::GetSurfaceShaderSource(SdfPath const &usdPath) const +UsdImagingShaderAdapter::GetSurfaceShaderSource(SdfPath const &usdPath) const { std::string const EMPTY; if (not TF_VERIFY(usdPath != SdfPath())) @@ -111,7 +111,7 @@ UsdImagingDefaultShaderAdapter::GetSurfaceShaderSource(SdfPath const &usdPath) c } TfTokenVector -UsdImagingDefaultShaderAdapter::GetSurfaceShaderParamNames(SdfPath const &usdPath) const +UsdImagingShaderAdapter::GetSurfaceShaderParamNames(SdfPath const &usdPath) const { TfTokenVector names; if (not TF_VERIFY(usdPath != SdfPath())) @@ -153,7 +153,7 @@ UsdImagingDefaultShaderAdapter::GetSurfaceShaderParamNames(SdfPath const &usdPat } VtValue -UsdImagingDefaultShaderAdapter::GetSurfaceShaderParamValue(SdfPath const &usdPath, +UsdImagingShaderAdapter::GetSurfaceShaderParamValue(SdfPath const &usdPath, TfToken const ¶mName) const { if (not TF_VERIFY(usdPath != SdfPath())) @@ -182,7 +182,7 @@ UsdImagingDefaultShaderAdapter::GetSurfaceShaderParamValue(SdfPath const &usdPat } HdShaderParamVector -UsdImagingDefaultShaderAdapter::GetSurfaceShaderParams(SdfPath const &usdPath) const +UsdImagingShaderAdapter::GetSurfaceShaderParams(SdfPath const &usdPath) const { HdShaderParamVector params; @@ -319,7 +319,7 @@ UsdImagingDefaultShaderAdapter::GetSurfaceShaderParams(SdfPath const &usdPath) c } SdfPathVector -UsdImagingDefaultShaderAdapter::GetSurfaceShaderTextures(SdfPath const &usdPath) const +UsdImagingShaderAdapter::GetSurfaceShaderTextures(SdfPath const &usdPath) const { SdfPathVector textureIDs; diff --git a/pxr/usdImaging/lib/usdImaging/shaderAdapter.h b/pxr/usdImaging/lib/usdImaging/shaderAdapter.h index 669b5b5a1f..4e298138df 100644 --- a/pxr/usdImaging/lib/usdImaging/shaderAdapter.h +++ b/pxr/usdImaging/lib/usdImaging/shaderAdapter.h @@ -24,48 +24,47 @@ #ifndef USDIMAGING_SHADERADAPTER_H #define USDIMAGING_SHADERADAPTER_H +class UsdImagingDelegate; + #include "pxr/imaging/hd/shaderParam.h" /// \class UsdImagingShaderAdapter -/// \brief Interface that provides information that can be used to generate a -/// surface shader in hydra. -/// -/// Shaders are identified by a \p shaderPath which is a usd stage path.. All -/// the pure virtual methods in this interface will likely need to be -/// coordinated. For example, \c GetSurfaceShaderParams declares all the -/// parameters that the shader uses. Hydra will later query the \c -/// UsdImagingShaderAdapter for the values (\c -/// UsdImagingShaderAdapater::GetSurfaceShaderParamValue). -/// -/// \sa UsdImagingIndexProxy::AddShaderAdapter -/// \sa UsdImagingDefaultShaderAdapter +/// \brief Provides information that can be used to generate a surface shader in +/// hydra. class UsdImagingShaderAdapter { public: - /// \brief Return true if \p usdPath is time varying. - virtual bool GetSurfaceShaderIsTimeVarying(SdfPath const& usdPath) const = 0; + UsdImagingShaderAdapter(UsdImagingDelegate* delegate); + + /// \brief Traverses the shading prims and if any of the attributes are time + /// varying, returns true. + bool GetSurfaceShaderIsTimeVarying(SdfPath const& usdPath) const; /// \brief Returns the glsl source string for the shader at \p usdPath. - virtual std::string GetSurfaceShaderSource(SdfPath const& usdPath) const = 0; + /// + /// This obtains the shading source via the \c UsdHydraShader schema. + std::string GetSurfaceShaderSource(SdfPath const& usdPath) const; /// \brief Returns the parameter names for \p usdPath. /// \deprecated This is now replaced by UsdImagingShaderAdapter::GetSurfaceShaderParams - virtual TfTokenVector GetSurfaceShaderParamNames(SdfPath const& usdPath) const = 0; + TfTokenVector GetSurfaceShaderParamNames(SdfPath const& usdPath) const; /// \brief Returns the value of param \p paramName for \p usdPath. - virtual VtValue GetSurfaceShaderParamValue(SdfPath const& usdPath, TfToken const& paramName) const = 0; + VtValue GetSurfaceShaderParamValue(SdfPath const& usdPath, TfToken const& paramName) const; /// \brief Returns the parameters that \p usdPath users. Hydra will built /// the appropriate internal data structures so that these values are /// available in the shader. /// /// \sa HdShaderParam - virtual HdShaderParamVector GetSurfaceShaderParams(SdfPath const& usdPath) const = 0; + HdShaderParamVector GetSurfaceShaderParams(SdfPath const& usdPath) const; /// \brief Returns the textures (identified by \c SdfPath objects) that \p /// usdPath users. - virtual SdfPathVector GetSurfaceShaderTextures(SdfPath const& usdPath) const = 0; + SdfPathVector GetSurfaceShaderTextures(SdfPath const& usdPath) const; +private: + UsdImagingDelegate* _delegate; }; #endif // USDIMAGING_SHADERADAPTER_H From 15f8356f5826b6eb9a342c1878a454982469f2a3 Mon Sep 17 00:00:00 2001 From: superfunc Date: Mon, 17 Oct 2016 13:34:16 -0700 Subject: [PATCH 202/380] [UsdUtils] Allow users to add topology layer as a sublayer rather than a reference on a prim in the result layer. (Internal change: 1661132) --- pxr/usd/lib/usdUtils/stitchClips.cpp | 47 ++++++++++++---------------- pxr/usd/lib/usdUtils/stitchClips.h | 5 ++- 2 files changed, 24 insertions(+), 28 deletions(-) diff --git a/pxr/usd/lib/usdUtils/stitchClips.cpp b/pxr/usd/lib/usdUtils/stitchClips.cpp index c9a55c52d8..3fccff333f 100644 --- a/pxr/usd/lib/usdUtils/stitchClips.cpp +++ b/pxr/usd/lib/usdUtils/stitchClips.cpp @@ -63,6 +63,9 @@ namespace { // ------------------------------------------------------------------------ constexpr double TIME_MAX = std::numeric_limits::max(); + // We insert the topology layer as the strongest + constexpr size_t TOPOLOGY_SUBLAYER_STRENGTH = 0; + // keys for indexing into the clip info // XXX: This code is shared in usd/clip.h // ------------------------------------------------------------------------ @@ -391,29 +394,18 @@ namespace { } void - _StitchClipTopologyLayerReference(const SdfLayerRefPtr& resultLayer, - const SdfPath& rootPath, - const std::string& topIdentifier) + _StitchClipsTopologySubLayerPath(const SdfLayerRefPtr& resultLayer, + const std::string& topIdentifier) { - if (not resultLayer->GetPrimAtPath(rootPath)) { - TF_CODING_ERROR("Invalid prim path referenced in result layer"); - return; + auto sublayers = resultLayer->GetSubLayerPaths(); + + // We only want to add the topology layer if it hasn't been + // previously sublayered into this result layer. + if (std::find(sublayers.begin(), sublayers.end(), topIdentifier) + == sublayers.end()) { + resultLayer->InsertSubLayerPath(topIdentifier, + TOPOLOGY_SUBLAYER_STRENGTH); } - - // fetch any available references at the prim - SdfReferencesProxy currentReferenceVec - = resultLayer - ->GetPrimAtPath(rootPath) - ->GetReferenceList(); - - // insert the new reference to the topology file - currentReferenceVec - .Add(SdfReference(topIdentifier, rootPath)); - - // make the ref owning prim a def - resultLayer - ->GetPrimAtPath(rootPath) - ->SetSpecifier(SdfSpecifierDef); } // Add the clipAssetPath metadata at the specified \p stitchPath @@ -709,7 +701,8 @@ namespace { = _GetRelativePathIfPossible(topologyLayer->GetIdentifier(), topologyLayer->GetRealPath(), resultLayer->GetRealPath()); - _StitchClipTopologyLayerReference(resultLayer, rootPath, topologyId); + + _StitchClipsTopologySubLayerPath(resultLayer, topologyId); } } @@ -733,7 +726,7 @@ namespace { const double startTimeCode, const double endTimeCode) { - _StitchLayers(resultLayer, topologyLayer, clipLayers, clipPath); + _StitchLayers(resultLayer, topologyLayer, clipLayers, clipPath); _SetTimeCodeRange(resultLayer, clipPath, startTimeCode, endTimeCode); topologyLayer->Save(); @@ -837,12 +830,12 @@ UsdUtilsStitchClips(const SdfLayerHandle& resultLayer, SdfLayerRefPtr topologyLayer; bool topologyWasGenerated; - std::tie(topologyLayer, topologyWasGenerated) = _CreateTopologyLayer( - resultLayer, reuseExistingTopology); + std::tie(topologyLayer, topologyWasGenerated) + = _CreateTopologyLayer(resultLayer, reuseExistingTopology); SdfLayerRefPtrVector clipLayers; - const bool clipLayersAreValid = _OpenClipLayers(&clipLayers, - clipLayerFiles, clipPath); + const bool clipLayersAreValid + = _OpenClipLayers(&clipLayers, clipLayerFiles, clipPath); if (not clipLayersAreValid) { if (topologyWasGenerated) { diff --git a/pxr/usd/lib/usdUtils/stitchClips.h b/pxr/usd/lib/usdUtils/stitchClips.h index 76edc29414..1a8e2276b6 100644 --- a/pxr/usd/lib/usdUtils/stitchClips.h +++ b/pxr/usd/lib/usdUtils/stitchClips.h @@ -42,7 +42,10 @@ SDF_DECLARE_HANDLES(SdfLayer); /// clipPath without copying the samples into a separate layer. /// /// \p resultLayer The layer to which clip meta data and frame data -/// will be written +/// will be written. The layer representing the static +/// scene topology will be authored as a sublayer on +/// this layer as well; it will be authored as the +/// first sublayer in the list(strongest). /// /// \p clipLayerFiles The files containing the time varying data. /// From ec8787301294cdd0aa54d402c0b3a69cb18d3ccc Mon Sep 17 00:00:00 2001 From: jloy Date: Mon, 17 Oct 2016 13:34:26 -0700 Subject: [PATCH 203/380] Vt: remove out-of-date comment. The C++ standard requires the object layout that the comment misattributed to a gcc-specific behavior. At the time the comment was written, the first member of VtArray also derived from boost::equality_comparable, which in turn derived from (untemplated) empty_base. boost::equality_comparable was later improved to derive from empty_base so it wouldn't prevent the empty base class optimization in situations like this (see https://svn.boost.org/trac/boost/ticket/979.) In the meantime, VtArray's implementation was also changed to use boost::intrusive_ptr, which does not derive from equality_comparable. (Internal change: 1661138) --- pxr/base/lib/vt/array.h | 6 ------ 1 file changed, 6 deletions(-) diff --git a/pxr/base/lib/vt/array.h b/pxr/base/lib/vt/array.h index b913fefa77..a42dc9a33e 100644 --- a/pxr/base/lib/vt/array.h +++ b/pxr/base/lib/vt/array.h @@ -109,12 +109,6 @@ class VtArray { typedef boost::container::vector _VecType; - // VtArray should derive from boost::equality_comparable, but because of - // gcc's awesomeness, that increases the size of VtArray by a pointer. - // Which is stupid, because equality_comparable is empty, and in fact, ONLY - // creates friend free functions. So instead, we manually provide != in - // terms of ==. - public: /// Type this array holds. From 1d2a59b37fc2f0fb0e5500bc5ac50d92fca52927 Mon Sep 17 00:00:00 2001 From: poljere Date: Mon, 17 Oct 2016 13:34:37 -0700 Subject: [PATCH 204/380] If a shader did not compile we would replace it with a fallback shader however that would not be taken into account when binding buffers and other parts of the pipeline. To solve this issue now we keeping the shaders used in the program so we can access them anywhere in the batch, this also consolidates the different ways to access the shaders that we had previously. [Hd] In renderPassState : Function GetShaders() Now it only returns the lighting and renderpass shader, it does not know about surface shader and it does not take into account the override shader, now it is up to the consumer of that function. In drawBatch : Currently if a shader did not compile you would replace the shader with a fallback shader however that would not be taken into account when binding buffers and other parts of the pipeline. Now we store the current shader we are using and we use that one to bind buffers correctly. In inmediateDrawBatch and indirectDrawBatch : Both are using the shaders stored in the program associated to a batch. (Internal change: 1661165) --- pxr/imaging/lib/hd/drawBatch.cpp | 52 +++++++++++++--------- pxr/imaging/lib/hd/drawBatch.h | 53 +++++++++++++++++++++-- pxr/imaging/lib/hd/immediateDrawBatch.cpp | 15 +++---- pxr/imaging/lib/hd/indirectDrawBatch.cpp | 32 ++++++-------- pxr/imaging/lib/hd/renderPassState.cpp | 13 +----- pxr/imaging/lib/hd/renderPassState.h | 5 +-- 6 files changed, 107 insertions(+), 63 deletions(-) diff --git a/pxr/imaging/lib/hd/drawBatch.cpp b/pxr/imaging/lib/hd/drawBatch.cpp index 859bd4ff03..187af524ad 100644 --- a/pxr/imaging/lib/hd/drawBatch.cpp +++ b/pxr/imaging/lib/hd/drawBatch.cpp @@ -183,26 +183,34 @@ Hd_DrawBatch::_GetDrawingProgram(HdRenderPassStateSharedPtr const &state, HdDrawItem const *firstDrawItem = _drawItemInstances[0]->GetDrawItem(); - size_t shaderHash = state->GetShaderHash(); // overrideShader is taken into account + // Calculate unique hash to detect if the shader (composed) has changed + // recently and we need to recompile it. + size_t shaderHash = state->GetShaderHash(); boost::hash_combine(shaderHash, firstDrawItem->GetGeometricShader()->ComputeHash()); + HdShaderSharedPtr overrideShader = state->GetOverrideShader(); + HdShaderSharedPtr surfaceShader = overrideShader ? overrideShader + : firstDrawItem->GetSurfaceShader(); + boost::hash_combine(shaderHash, surfaceShader->ComputeHash()); bool shaderChanged = (_shaderHash != shaderHash); + + // Set shaders (lighting and renderpass) to the program. + // We need to do this before checking if the shaderChanged because + // it is possible that the shader does not need to + // be recompiled but some of the parameters have changed. + HdShaderSharedPtrVector shaders = state->GetShaders(); + _program.SetShaders(shaders); + _program.SetGeometricShader(firstDrawItem->GetGeometricShader()); // XXX: if this function appears to be expensive, we might consider caching // programs by shaderHash. if (not _program.GetGLSLProgram() or shaderChanged) { + + _program.SetSurfaceShader(surfaceShader); - // compose shaders - HdShaderSharedPtrVector shaders(3); - shaders[0] = state->GetLightingShader(); - shaders[1] = state->GetRenderPassShader(); - HdShaderSharedPtr overrideShader = state->GetOverrideShader(); - shaders[2] = overrideShader ? overrideShader - : firstDrawItem->GetSurfaceShader(); - - if (not _program.CompileShader(firstDrawItem, - firstDrawItem->GetGeometricShader(), - shaders, indirect)) { + // Try to compile the shader and if it fails to compile we go back + // to use the specified fallback surface shader. + if (not _program.CompileShader(firstDrawItem, indirect)) { // If we failed to compile the surface shader, replace it with the // fallback surface shader and try again. @@ -224,11 +232,9 @@ Hd_DrawBatch::_GetDrawingProgram(HdRenderPassStateSharedPtr const &state, HdSurfaceShaderSharedPtr( new HdGLSLFXShader(glslSurfaceFallback)); - shaders[2] = fallbackSurface; + _program.SetSurfaceShader(fallbackSurface); - bool res = _program.CompileShader(firstDrawItem, - firstDrawItem->GetGeometricShader(), - shaders, indirect); + bool res = _program.CompileShader(firstDrawItem, indirect); // We expect the fallback shader to always compile. TF_VERIFY(res); } @@ -242,16 +248,20 @@ Hd_DrawBatch::_GetDrawingProgram(HdRenderPassStateSharedPtr const &state, bool Hd_DrawBatch::_DrawingProgram::CompileShader( HdDrawItem const *drawItem, - Hd_GeometricShaderPtr const &geometricShader, - HdShaderSharedPtrVector const &shaders, bool indirect) { HD_TRACE_FUNCTION(); HD_MALLOC_TAG_FUNCTION(); // glew has to be intialized - if (not glLinkProgram) + if (not glLinkProgram) { + return false; + } + + if (not _geometricShader) { + TF_CODING_ERROR("Can not compile a shader without a geometric shader"); return false; + } // determine binding points and populate metaData HdBindingRequestVector customBindings; @@ -259,11 +269,13 @@ Hd_DrawBatch::_DrawingProgram::CompileShader( _GetCustomBindings(&customBindings, &instanceDraw); // also (surface, renderPass) shaders use their bindings + HdShaderSharedPtrVector shaders = GetComposedShaders(); + TF_FOR_ALL(it, shaders) { (*it)->AddBindings(&customBindings); } - Hd_CodeGen codeGen(geometricShader, shaders); + Hd_CodeGen codeGen(_geometricShader, shaders); // let resourcebinder resolve bindings and populate metadata // which is owned by codegen. diff --git a/pxr/imaging/lib/hd/drawBatch.h b/pxr/imaging/lib/hd/drawBatch.h index 5f31e39f3b..c60ef0abba 100644 --- a/pxr/imaging/lib/hd/drawBatch.h +++ b/pxr/imaging/lib/hd/drawBatch.h @@ -99,8 +99,6 @@ class Hd_DrawBatch { bool CompileShader( HdDrawItem const *drawItem, - Hd_GeometricShaderSharedPtr const &geometricShader, - HdShaderSharedPtrVector const &shaders, bool indirect); HdGLSLProgramSharedPtr GetGLSLProgram() const { @@ -109,11 +107,57 @@ class Hd_DrawBatch { /// Returns the resouce binder, which is used for buffer resource /// bindings at draw time. - const Hd_ResourceBinder &GetBinder() const { return _resourceBinder; } + const Hd_ResourceBinder &GetBinder() const { + return _resourceBinder; + } void Reset() { _glslProgram.reset(); + _surfaceShader.reset(); + _geometricShader.reset(); _resourceBinder = Hd_ResourceBinder(); + _shaders.clear(); + } + + void SetSurfaceShader(HdShaderSharedPtr shader) { + _surfaceShader = shader; + } + + const HdShaderSharedPtr &GetSurfaceShader() { + return _surfaceShader; + } + + void SetGeometricShader(Hd_GeometricShaderSharedPtr shader) { + _geometricShader = shader; + } + + const Hd_GeometricShaderSharedPtr &GetGeometricShader() { + return _geometricShader; + } + + /// Set shaders (lighting/renderpass). In the case of Geometric Shaders + /// or Surface shaders you can use the specific setters. + void SetShaders(HdShaderSharedPtrVector shaders) { + _shaders = shaders; + } + + /// Returns array of shaders, this will not include the surface shader + /// passed via SetSurfaceShader (or the geometric shader). + const HdShaderSharedPtrVector &GetShaders() const { + return _shaders; + } + + /// Returns array of composed shaders, this include the shaders passed + /// via SetShaders and the shader passed to SetSurfaceShader. + HdShaderSharedPtrVector GetComposedShaders() const { + HdShaderSharedPtrVector shaders; + for (int i=0; i<_shaders.size(); i++) { + shaders.push_back(_shaders[i]); + } + if (_surfaceShader) { + shaders.push_back(_surfaceShader); + } + return shaders; } protected: @@ -129,6 +173,9 @@ class Hd_DrawBatch { private: HdGLSLProgramSharedPtr _glslProgram; Hd_ResourceBinder _resourceBinder; + HdShaderSharedPtrVector _shaders; + Hd_GeometricShaderSharedPtr _geometricShader; + HdShaderSharedPtr _surfaceShader; }; _DrawingProgram & _GetDrawingProgram( diff --git a/pxr/imaging/lib/hd/immediateDrawBatch.cpp b/pxr/imaging/lib/hd/immediateDrawBatch.cpp index f5b6773c15..f27d1e6d68 100644 --- a/pxr/imaging/lib/hd/immediateDrawBatch.cpp +++ b/pxr/imaging/lib/hd/immediateDrawBatch.cpp @@ -120,14 +120,13 @@ Hd_ImmediateDrawBatch::ExecuteDraw( if (not TF_VERIFY(glslProgram->Validate())) return; const Hd_ResourceBinder &binder = program.GetBinder(); + const HdShaderSharedPtrVector &shaders = program.GetComposedShaders(); GLuint programId = glslProgram->GetProgram().GetId(); TF_VERIFY(programId); glUseProgram(programId); - HdShaderSharedPtrVector shaders - = renderPassState->GetShaders(/*surfaceShader=*/HdShaderSharedPtr()); bool hasOverrideShader = bool(renderPassState->GetOverrideShader()); TF_FOR_ALL(it, shaders) { @@ -136,9 +135,8 @@ Hd_ImmediateDrawBatch::ExecuteDraw( // Set up geometric shader states // all batch item should have the same geometric shader. - HdDrawItem const* batchItem = _drawItemInstances.front()->GetDrawItem(); Hd_GeometricShaderSharedPtr const &geometricShader - = batchItem->GetGeometricShader(); + = program.GetGeometricShader(); geometricShader->BindResources(binder, programId); size_t numItemsDrawn = 0; @@ -239,7 +237,8 @@ Hd_ImmediateDrawBatch::ExecuteDraw( // HdBufferArrayRangeSharedPtr const & instanceIndexBar = drawItem->GetInstanceIndexRange(); - if (instanceIndexBar and (not instanceIndexBar->IsAggregatedWith(instanceIndexBarCurrent))) { + if (instanceIndexBar and + (not instanceIndexBar->IsAggregatedWith(instanceIndexBarCurrent))) { binder.UnbindBufferArray(instanceIndexBarCurrent); binder.BindBufferArray(instanceIndexBar); instanceIndexBarCurrent = instanceIndexBar; @@ -251,7 +250,7 @@ Hd_ImmediateDrawBatch::ExecuteDraw( HdBufferArrayRangeSharedPtr const & shaderBar = renderPassState->GetOverrideShader() ? HdBufferArrayRangeSharedPtr() - : drawItem->GetSurfaceShader()->GetShaderData(); + : program.GetSurfaceShader()->GetShaderData(); // shaderBar isn't needed when the surfaceShader is overriden if (shaderBar and (not shaderBar->IsAggregatedWith(shaderBarCurrent))) { if (shaderBarCurrent) { @@ -267,7 +266,7 @@ Hd_ImmediateDrawBatch::ExecuteDraw( // shader textures // if (not hasOverrideShader) { - drawItem->GetSurfaceShader()->BindResources(binder, programId); + program.GetSurfaceShader()->BindResources(binder, programId); } /* @@ -371,7 +370,7 @@ Hd_ImmediateDrawBatch::ExecuteDraw( } if (not hasOverrideShader) { - drawItem->GetSurfaceShader()->UnbindResources(binder, programId); + program.GetSurfaceShader()->UnbindResources(binder, programId); } HD_PERF_COUNTER_INCR(HdPerfTokens->drawCalls); diff --git a/pxr/imaging/lib/hd/indirectDrawBatch.cpp b/pxr/imaging/lib/hd/indirectDrawBatch.cpp index 45806def6d..30c89f1a3d 100644 --- a/pxr/imaging/lib/hd/indirectDrawBatch.cpp +++ b/pxr/imaging/lib/hd/indirectDrawBatch.cpp @@ -114,10 +114,9 @@ Hd_IndirectDrawBatch::_GetCullingProgram() // sharing the culling geometric shader for the same configuration. Hd_GeometricShaderSharedPtr cullShader = Hd_GeometricShader::Create(shaderKey); + _cullingProgram.SetGeometricShader(cullShader); _cullingProgram.CompileShader(_drawItemInstances.front()->GetDrawItem(), - cullShader, - HdShaderSharedPtrVector(), /*indirect=*/true); } return _cullingProgram; @@ -993,10 +992,7 @@ Hd_IndirectDrawBatch::ExecuteDraw( glUseProgram(programId); const Hd_ResourceBinder &binder = program.GetBinder(); - - // resolve shaders (surface shader may be overriden) - HdShaderSharedPtrVector shaders - = renderPassState->GetShaders(batchItem->GetSurfaceShader()); + const HdShaderSharedPtrVector &shaders = program.GetComposedShaders(); // XXX: for surfaces shader, we need to iterate all drawItems to // make textures resident, instead of just the first batchItem @@ -1054,12 +1050,11 @@ Hd_IndirectDrawBatch::ExecuteDraw( // shader buffer bind HdBufferArrayRangeSharedPtr shaderBar; - - // shaderBar isn't needed when the surfaceShader is overriden - if (not renderPassState->GetOverrideShader()) { - shaderBar = batchItem->GetSurfaceShader()->GetShaderData(); + TF_FOR_ALL(shader, shaders) { + shaderBar = (*shader)->GetShaderData(); if (shaderBar) { - binder.BindBuffer(HdTokens->surfaceShaderParams, shaderBar->GetResource()); + binder.BindBuffer(HdTokens->surfaceShaderParams, + shaderBar->GetResource()); } } @@ -1069,7 +1064,7 @@ Hd_IndirectDrawBatch::ExecuteDraw( binder.BindBufferArray(dispatchBar); // update geometric shader states - batchItem->GetGeometricShader()->BindResources(binder, programId); + program.GetGeometricShader()->BindResources(binder, programId); GLuint batchCount = _dispatchBuffer->GetCount(); @@ -1081,12 +1076,12 @@ Hd_IndirectDrawBatch::ExecuteDraw( " - indirect: %d\n" " - drawCount: %d\n" " - stride: %zu\n", - batchItem->GetGeometricShader()->GetPrimitiveMode(), + program.GetGeometricShader()->GetPrimitiveMode(), 0, batchCount, _dispatchBuffer->GetCommandNumUints()*sizeof(GLuint)); glMultiDrawArraysIndirect( - batchItem->GetGeometricShader()->GetPrimitiveMode(), + program.GetGeometricShader()->GetPrimitiveMode(), 0, // draw command always starts with 0 batchCount, _dispatchBuffer->GetCommandNumUints()*sizeof(GLuint)); @@ -1097,12 +1092,12 @@ Hd_IndirectDrawBatch::ExecuteDraw( " - indirect: %d\n" " - drawCount: %d\n" " - stride: %zu\n", - batchItem->GetGeometricShader()->GetPrimitiveMode(), + program.GetGeometricShader()->GetPrimitiveMode(), 0, batchCount, _dispatchBuffer->GetCommandNumUints()*sizeof(GLuint)); glMultiDrawElementsIndirect( - batchItem->GetGeometricShader()->GetPrimitiveMode(), + program.GetGeometricShader()->GetPrimitiveMode(), GL_UNSIGNED_INT, 0, // draw command always starts with 0 batchCount, @@ -1122,7 +1117,8 @@ Hd_IndirectDrawBatch::ExecuteDraw( binder.UnbindBufferArray(vertexBar); binder.UnbindBufferArray(dispatchBar); if(shaderBar) { - binder.UnbindBuffer(HdTokens->surfaceShaderParams, shaderBar->GetResource()); + binder.UnbindBuffer(HdTokens->surfaceShaderParams, + shaderBar->GetResource()); } if (instanceIndexBar) { @@ -1135,7 +1131,7 @@ Hd_IndirectDrawBatch::ExecuteDraw( TF_FOR_ALL(it, shaders) { (*it)->UnbindResources(binder, programId); } - batchItem->GetGeometricShader()->UnbindResources(binder, programId); + program.GetGeometricShader()->UnbindResources(binder, programId); glUseProgram(0); } diff --git a/pxr/imaging/lib/hd/renderPassState.cpp b/pxr/imaging/lib/hd/renderPassState.cpp index 80e2111c5f..c02a850eb8 100644 --- a/pxr/imaging/lib/hd/renderPassState.cpp +++ b/pxr/imaging/lib/hd/renderPassState.cpp @@ -307,18 +307,12 @@ HdRenderPassState::SetOverrideShader(HdShaderSharedPtr const &overrideShader) } HdShaderSharedPtrVector -HdRenderPassState::GetShaders(HdShaderSharedPtr const &surfaceShader) const +HdRenderPassState::GetShaders() const { HdShaderSharedPtrVector shaders; - shaders.reserve(3); + shaders.reserve(2); shaders.push_back(_lightingShader); shaders.push_back(_renderPassShader); - if (_overrideShader) { - shaders.push_back(_overrideShader); - } else if (surfaceShader) { - shaders.push_back(surfaceShader); - } - return shaders; } @@ -407,9 +401,6 @@ HdRenderPassState::GetShaderHash() const size_t hash = _lightingShader->ComputeHash(); boost::hash_combine(hash, _renderPassShader->ComputeHash()); boost::hash_combine(hash, _clipPlanes.size()); - if (_overrideShader) { - boost::hash_combine(hash, _overrideShader->ComputeHash()); - } return hash; } diff --git a/pxr/imaging/lib/hd/renderPassState.h b/pxr/imaging/lib/hd/renderPassState.h index 307fd6cd5b..85c9d32d80 100644 --- a/pxr/imaging/lib/hd/renderPassState.h +++ b/pxr/imaging/lib/hd/renderPassState.h @@ -119,9 +119,8 @@ class HdRenderPassState { return _overrideShader; } - /// returns composed shader vectors. surfaceShader may be overriden. - HdShaderSharedPtrVector GetShaders( - HdShaderSharedPtr const &surfaceShader) const; + /// returns shaders (lighting/renderpass) + HdShaderSharedPtrVector GetShaders() const; GfMatrix4d const &GetCullMatrix() const { return _cullMatrix; From 3482797b8bd62d42918ddf98ca3cc46992ea3e96 Mon Sep 17 00:00:00 2001 From: mattyjams Date: Mon, 17 Oct 2016 13:34:49 -0700 Subject: [PATCH 205/380] add a Reset() method to UsdMayaGLBatchRenderer and make sure it's invoked on Maya scene updates The batch renderer is used as a static singleton object, and it keeps caches that contain ShapeRenderer objects, each of which may hold a pointer to a UsdImagingDelegate object. Those delegates maintain a strong pointer to the UsdStage. As a result, we need to make sure that the batch renderer's state is cleared so that the stage and any loaded layers can be released. This resolves an issue where making edits directly in USD with a stage loaded with an assembly or proxy node resulted in those edits persisting into a new scene, since the strong pointers in the delegate(s) were preventing the stage and layers from being released. (Internal change: 1661166) --- .../maya/lib/pxrUsdMayaGL/batchRenderer.cpp | 43 +++++++++++++++++-- .../maya/lib/pxrUsdMayaGL/batchRenderer.h | 32 ++++++++------ 2 files changed, 60 insertions(+), 15 deletions(-) diff --git a/third_party/maya/lib/pxrUsdMayaGL/batchRenderer.cpp b/third_party/maya/lib/pxrUsdMayaGL/batchRenderer.cpp index 0b9e4d2b3d..43bb1c5d28 100644 --- a/third_party/maya/lib/pxrUsdMayaGL/batchRenderer.cpp +++ b/third_party/maya/lib/pxrUsdMayaGL/batchRenderer.cpp @@ -47,12 +47,13 @@ #include "px_vp20/utils_legacy.h" #include "pxrUsdMayaGL/batchRenderer.h" - #include +#include +#include #include #include -#include #include +#include #include @@ -78,9 +79,21 @@ void UsdMayaGLBatchRenderer::Init() { GlfGlewInit(); + + GetGlobalRenderer(); +} + +/* static */ +UsdMayaGLBatchRenderer& +UsdMayaGLBatchRenderer::GetGlobalRenderer() +{ + if (not _sGlobalRendererPtr) { + Reset(); + } + return *_sGlobalRendererPtr; } -UsdMayaGLBatchRenderer UsdMayaGLBatchRenderer::_sGlobalRenderer; +std::unique_ptr UsdMayaGLBatchRenderer::_sGlobalRendererPtr; /// \brief struct to hold all the information needed for a /// draw request in vp1 or vp2, without requiring shape querying at @@ -811,11 +824,35 @@ UsdMayaGLBatchRenderer::GetSoftSelectHelper() return _softSelectHelper; } +// Since we're using a static singleton UsdMayaGLBatchRenderer object, we need +// to make sure that we reset its state when switching to a new Maya scene. +static +void +_OnMayaSceneUpdateCallback(void* clientData) +{ + UsdMayaGLBatchRenderer::Reset(); +} + UsdMayaGLBatchRenderer::UsdMayaGLBatchRenderer() : _renderIndex(new HdRenderIndex()) , _taskDelegate(new TaskDelegate(_renderIndex, SdfPath("/mayaTask"))) , _intersector(new HdxIntersector(_renderIndex)) { + static MCallbackId sceneUpdateCallbackId = 0; + if (sceneUpdateCallbackId == 0) { + sceneUpdateCallbackId = + MSceneMessage::addCallback(MSceneMessage::kSceneUpdate, + _OnMayaSceneUpdateCallback); + } +} + +/* static */ +void UsdMayaGLBatchRenderer::Reset() +{ + if (_sGlobalRendererPtr) { + MGlobal::displayInfo("Resetting USD Batch Renderer"); + } + _sGlobalRendererPtr.reset(new UsdMayaGLBatchRenderer()); } void diff --git a/third_party/maya/lib/pxrUsdMayaGL/batchRenderer.h b/third_party/maya/lib/pxrUsdMayaGL/batchRenderer.h index 4742cf9d3c..19e9ac4c8d 100644 --- a/third_party/maya/lib/pxrUsdMayaGL/batchRenderer.h +++ b/third_party/maya/lib/pxrUsdMayaGL/batchRenderer.h @@ -44,18 +44,19 @@ #include "pxr/usdImaging/usdImaging/tokens.h" #include +#include #include -#include -#include +#include #include #include -#include -#include +#include +#include +#include +#include #include -#include #include -#include +#include TF_DEBUG_CODES( PXRUSDMAYAGL_QUEUE_INFO @@ -89,8 +90,8 @@ class UsdMayaGLBatchRenderer : private boost::noncopyable /// called at least once and it is OK to call it multiple times. This /// handles things like initializing Gl/Glew. static void Init(); - - static UsdMayaGLBatchRenderer& GetGlobalRenderer() { return _sGlobalRenderer; } + + static UsdMayaGLBatchRenderer& GetGlobalRenderer(); struct RenderParams { @@ -303,9 +304,16 @@ class UsdMayaGLBatchRenderer : private boost::noncopyable const UsdMayaGLSoftSelectHelper& GetSoftSelectHelper(); /// \brief Construct a new, unique BatchRenderer. In almost all cases, - /// this should not be used -- use \c GlobalBatchRenderer() instead. + /// this should not be used -- use \c GetGlobalRenderer() instead. UsdMayaGLBatchRenderer(); - + + /// \brief Reset the internal state of the global UsdMayaGLBatchRenderer. + /// In particular, it's important that this happen when switching to a new + /// Maya scene so that any UsdImagingDelegates held by ShapeRenderers that + /// have been populated with USD stages can have those stages released, + /// since the delegates hold a strong pointers to their stages. + static void Reset(); + /// \brief Render batch or bounds in VP1 based on \p request void Draw( const MDrawRequest& request, @@ -401,9 +409,9 @@ class UsdMayaGLBatchRenderer : private boost::noncopyable TaskDelegateSharedPtr _taskDelegate; HdxIntersectorSharedPtr _intersector; UsdMayaGLSoftSelectHelper _softSelectHelper; - + /// \brief Sole global batch renderer used by default. - static UsdMayaGLBatchRenderer _sGlobalRenderer; + static std::unique_ptr _sGlobalRendererPtr; }; #endif // PXRUSDMAYAGL_BATCHRENDERER_H From d84ec65092b6c2e6c38f0d3a16976038501a3955 Mon Sep 17 00:00:00 2001 From: poljere Date: Mon, 17 Oct 2016 13:35:10 -0700 Subject: [PATCH 206/380] This fix cleans the dirty bits after UpdateDrawItem is called. This changelist also refactors a bit the code in Rprim sync since we need to update the surfacce shader first and then prepare the buffers. Finally, it fixes another situation exposed by this change which is the fact that shaders worked the first time we initialize the rprim but not after updating them, mostly because the delegate get was returning relative paths instead of absolute paths to the shader (which are required by the renderindex). (Internal change: 1661167) --- pxr/imaging/lib/hd/mesh.cpp | 44 +++++++++++++++++----- pxr/imaging/lib/hd/mesh.h | 6 ++- pxr/imaging/lib/hd/rprim.cpp | 12 ++---- pxr/usdImaging/lib/usdImaging/delegate.cpp | 5 ++- 4 files changed, 45 insertions(+), 22 deletions(-) diff --git a/pxr/imaging/lib/hd/mesh.cpp b/pxr/imaging/lib/hd/mesh.cpp index 9a1a6597f1..9a33c2aa87 100644 --- a/pxr/imaging/lib/hd/mesh.cpp +++ b/pxr/imaging/lib/hd/mesh.cpp @@ -455,7 +455,8 @@ void HdMesh::_PopulateVertexPrimVars(HdDrawItem *drawItem, HdChangeTracker::DirtyBits *dirtyBits, bool isNew, - HdMeshReprDesc desc) + HdMeshReprDesc desc, + bool requireSmoothNormals) { HD_TRACE_FUNCTION(); HD_MALLOC_TAG_FUNCTION(); @@ -483,7 +484,7 @@ HdMesh::_PopulateVertexPrimVars(HdDrawItem *drawItem, HdBufferSourceSharedPtr points; bool cpuSmoothNormals = - desc.smoothNormals and (not IsEnabledSmoothNormalsGPU()); + requireSmoothNormals and (not IsEnabledSmoothNormalsGPU()); int refineLevel = _topology ? _topology->GetRefineLevel() : 0; // Don't call _GetRefineLevelForDesc(desc) instead of GetRefineLevel(). Why? @@ -552,14 +553,14 @@ HdMesh::_PopulateVertexPrimVars(HdDrawItem *drawItem, sources.push_back(source); // save the point buffer source for smooth normal computation. - if (desc.smoothNormals + if (requireSmoothNormals and *nameIt == HdTokens->points) { points = source; } } } - if (desc.smoothNormals and + if (requireSmoothNormals and HdChangeTracker::IsPrimVarDirty(*dirtyBits, id, HdTokens->normals)) { // note: normals gets dirty when points are marked as dirty, // at changetracker. @@ -869,7 +870,8 @@ void HdMesh::_UpdateDrawItem(HdDrawItem *drawItem, HdChangeTracker::DirtyBits *dirtyBits, bool isNew, - HdMeshReprDesc desc) + HdMeshReprDesc desc, + bool requireSmoothNormals) { HD_TRACE_FUNCTION(); HD_MALLOC_TAG_FUNCTION(); @@ -908,10 +910,10 @@ HdMesh::_UpdateDrawItem(HdDrawItem *drawItem, // normal dirtiness will be cleared without computing/populating normals. TfToken scheme = _topology->GetScheme(); if (scheme == PxOsdOpenSubdivTokens->bilinear) { - desc.smoothNormals = false; + requireSmoothNormals = false; } - if (desc.smoothNormals and not _vertexAdjacency) { + if (requireSmoothNormals and not _vertexAdjacency) { _PopulateAdjacency(); } @@ -922,7 +924,7 @@ HdMesh::_UpdateDrawItem(HdDrawItem *drawItem, /* VERTEX PRIMVARS */ if (isNew or HdChangeTracker::IsAnyPrimVarDirty(*dirtyBits, id)) { - _PopulateVertexPrimVars(drawItem, dirtyBits, isNew, desc); + _PopulateVertexPrimVars(drawItem, dirtyBits, isNew, desc, requireSmoothNormals); } /* ELEMENT PRIMVARS */ @@ -937,6 +939,12 @@ HdMesh::_UpdateDrawItem(HdDrawItem *drawItem, } } + // When we have multiple drawitems for the same mesh we need to clean the + // bits for all the data fields touched in this function, otherwise it + // will try to extract topology (for instance) twice, and this won't + // work with delegates that don't keep information around once extracted. + *dirtyBits &= ~HdChangeTracker::AllSceneDirtyBits; + TF_VERIFY(drawItem->GetConstantPrimVarRange()); // Topology and VertexPrimVar may be null, if the mesh has zero faces. // Element primvar, Facevarying primvar and Instance primvar are optional @@ -982,9 +990,13 @@ HdMesh::_UpdateDrawItemGeometricShader(HdDrawItem *drawItem, HdMeshReprDesc desc // resolve geom style, cull style HdCullStyle cullStyle = _cullStyle; + HdMeshGeomStyle geomStyle = desc.geomStyle; + + // We need to use smoothNormals flag per repr (and not requireSmoothNormals) + // here since the geometric shader needs to know if we are actually + // using normals or not. bool smoothNormals = desc.smoothNormals and _topology->GetScheme() != PxOsdOpenSubdivTokens->bilinear; - HdMeshGeomStyle geomStyle = desc.geomStyle; // if the prim doesn't have an opinion about cullstyle, // use repr's default (it could also be DontCare, then renderPass's @@ -1109,6 +1121,18 @@ HdMesh::_GetRepr(TfToken const &reprName, _ResetGeometricShaders(); } + // iterate through all reprs to figure out if any requires smoothnormals + // if so we will calculate the normals once (clean the bits) and reuse them. + // This is important for modes like FeyRay which requires 2 draw items + // and one requires smooth normals but the other doesn't. + bool requireSmoothNormals = false; + for (auto desc : descs) { + if (desc.smoothNormals) { + requireSmoothNormals = true; + break; + } + } + // iterate and update all draw items int drawItemIndex = 0; for (auto desc : descs) { @@ -1116,7 +1140,7 @@ HdMesh::_GetRepr(TfToken const &reprName, if (isNew or HdChangeTracker::IsDirty(*dirtyBits)) { HdDrawItem *drawItem = it->second->GetDrawItem(drawItemIndex); - _UpdateDrawItem(drawItem, dirtyBits, isNew, desc); + _UpdateDrawItem(drawItem, dirtyBits, isNew, desc, requireSmoothNormals); _UpdateDrawItemGeometricShader(drawItem, desc); } ++drawItemIndex; diff --git a/pxr/imaging/lib/hd/mesh.h b/pxr/imaging/lib/hd/mesh.h index cccc34e68c..0ab6f88c11 100644 --- a/pxr/imaging/lib/hd/mesh.h +++ b/pxr/imaging/lib/hd/mesh.h @@ -119,7 +119,8 @@ class HdMesh : public HdRprim { void _UpdateDrawItem(HdDrawItem *drawItem, HdChangeTracker::DirtyBits *dirtyBits, bool isNew, - HdMeshReprDesc desc); + HdMeshReprDesc desc, + bool requireSmoothNormals); void _UpdateDrawItemGeometricShader(HdDrawItem *drawItem, HdMeshReprDesc desc); @@ -137,7 +138,8 @@ class HdMesh : public HdRprim { void _PopulateVertexPrimVars(HdDrawItem *drawItem, HdChangeTracker::DirtyBits *dirtyBits, bool isNew, - HdMeshReprDesc desc); + HdMeshReprDesc desc, + bool requireSmoothNormals); void _PopulateFaceVaryingPrimVars(HdDrawItem *drawItem, HdChangeTracker::DirtyBits *dirtyBits, diff --git a/pxr/imaging/lib/hd/rprim.cpp b/pxr/imaging/lib/hd/rprim.cpp index 26028ad94e..20708cb9e3 100644 --- a/pxr/imaging/lib/hd/rprim.cpp +++ b/pxr/imaging/lib/hd/rprim.cpp @@ -66,10 +66,6 @@ void HdRprim::Sync(TfToken const &defaultReprName, bool forced, HdChangeTracker::DirtyBits *dirtyBits) { - TfToken reprName = _GetReprName(defaultReprName, - forced, dirtyBits); - _GetRepr(reprName, dirtyBits); - // Check if the rprim has a new surface shader associated to it, // if so, we will request the binding from the delegate and set it up in // this rprim. @@ -86,10 +82,10 @@ HdRprim::Sync(TfToken const &defaultReprName, bool forced, *dirtyBits &= ~HdChangeTracker::DirtySurfaceShader; } - // all scene-based dirty bits should have been cleared or handed off to - // repr-specific dirty bits. Otherwise sceneDelegate may be asked multiple - // times for same data. - *dirtyBits &= ~(HdChangeTracker::AllSceneDirtyBits); + TfToken reprName = _GetReprName(defaultReprName, forced, dirtyBits); + _GetRepr(reprName, dirtyBits); + + *dirtyBits &= ~HdChangeTracker::AllSceneDirtyBits; } TfToken diff --git a/pxr/usdImaging/lib/usdImaging/delegate.cpp b/pxr/usdImaging/lib/usdImaging/delegate.cpp index 39eff8544a..491d22ef23 100644 --- a/pxr/usdImaging/lib/usdImaging/delegate.cpp +++ b/pxr/usdImaging/lib/usdImaging/delegate.cpp @@ -1202,7 +1202,8 @@ UsdImagingDelegate::_PrepareWorkerForTimeUpdate(_Worker* worker) bool& isTimeVarying = it->second; if (isTimeVarying) { HdChangeTracker &tracker = GetRenderIndex().GetChangeTracker(); - tracker.MarkShaderDirty(it->first, HdChangeTracker::DirtyParams); + tracker.MarkShaderDirty( + GetPathForIndex(it->first), HdChangeTracker::DirtyParams); } } } @@ -2389,7 +2390,7 @@ UsdImagingDelegate::Get(SdfPath const& id, TfToken const& key) _UpdateSingleValue(usdPath,HdChangeTracker::DirtySurfaceShader); SdfPath pathValue; TF_VERIFY(_valueCache.ExtractSurfaceShader(usdPath, &pathValue)); - value = VtValue(pathValue); + value = VtValue(GetPathForIndex(pathValue)); } else if (key == HdTokens->transform) { GfMatrix4d xform(1.); bool resetsXformStack=false; From 294a816f7a8417608a95b3956f8debea849b6d34 Mon Sep 17 00:00:00 2001 From: poljere Date: Mon, 17 Oct 2016 13:36:01 -0700 Subject: [PATCH 207/380] [Glf] Fix for failing to load textures from disk. This changelist makes it so when user requests a degraded texture it will load it at that level and not use the chain (matching the previous behaviour prior to the introduction of miploading), we will let the gpu do that work. (Internal change: 1661170) --- pxr/imaging/lib/glf/uvTextureData.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pxr/imaging/lib/glf/uvTextureData.cpp b/pxr/imaging/lib/glf/uvTextureData.cpp index f71d87e7c1..8f4ef3b8a4 100644 --- a/pxr/imaging/lib/glf/uvTextureData.cpp +++ b/pxr/imaging/lib/glf/uvTextureData.cpp @@ -195,7 +195,7 @@ GlfUVTextureData::_ReadDegradedImageInput(bool generateMipmap, return _GetDegradedImageInputChain( double(image->GetWidth()) / fullImage->GetWidth(), double(image->GetHeight()) / fullImage->GetHeight(), - degradeLevel, numMipLevels); + degradeLevel, degradeLevel + 1); } // We actually have an image requiring more memory than targetMemory. @@ -328,7 +328,7 @@ GlfUVTextureData::Read(int degradeLevel, bool generateMipmap) int sizeAprox = _resizedWidth * _resizedHeight * _bytesPerPixel * scale; while ((_targetMemory > 0) - && (static_cast(sizeAprox) > _targetMemory)) { + and (static_cast(sizeAprox) > _targetMemory)) { _resizedWidth >>= 1; _resizedHeight >>= 1; sizeAprox = _resizedWidth * _resizedHeight * _bytesPerPixel * scale; From 7bad1b0a8877e1979861db9a1daa3cd79bcc5265 Mon Sep 17 00:00:00 2001 From: sdao Date: Mon, 17 Oct 2016 13:36:43 -0700 Subject: [PATCH 208/380] General mechanism for storing USD-specific data in "USD_" Maya attributes (Internal change: 1661180) --- .../maya/lib/usdMaya/AttributeConverter.cpp | 62 +++++++++ .../maya/lib/usdMaya/AttributeConverter.h | 97 +++++++++++++ .../usdMaya/AttributeConverterRegistry.cpp | 45 ++++++ .../lib/usdMaya/AttributeConverterRegistry.h | 45 ++++++ third_party/maya/lib/usdMaya/CMakeLists.txt | 4 + .../maya/lib/usdMaya/MayaPrimWriter.cpp | 35 ++--- .../UsdMetadataAttributeConverters.cpp | 129 ++++++++++++++++++ .../maya/lib/usdMaya/translatorPrim.cpp | 10 ++ third_party/maya/lib/usdMaya/util.cpp | 43 ++++++ third_party/maya/lib/usdMaya/util.h | 10 ++ 10 files changed, 456 insertions(+), 24 deletions(-) create mode 100644 third_party/maya/lib/usdMaya/AttributeConverter.cpp create mode 100644 third_party/maya/lib/usdMaya/AttributeConverter.h create mode 100644 third_party/maya/lib/usdMaya/AttributeConverterRegistry.cpp create mode 100644 third_party/maya/lib/usdMaya/AttributeConverterRegistry.h create mode 100644 third_party/maya/lib/usdMaya/UsdMetadataAttributeConverters.cpp diff --git a/third_party/maya/lib/usdMaya/AttributeConverter.cpp b/third_party/maya/lib/usdMaya/AttributeConverter.cpp new file mode 100644 index 0000000000..73503ce425 --- /dev/null +++ b/third_party/maya/lib/usdMaya/AttributeConverter.cpp @@ -0,0 +1,62 @@ +// +// 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. +// +#include "usdMaya/AttributeConverter.h" + +#include "pxr/usd/usd/prim.h" + +#include + +FunctionalAttributeConverter::FunctionalAttributeConverter( + MayaToUsdFn mayaToUsdFn, UsdToMayaFn usdToMayaFn) + : _mayaToUsdFn(mayaToUsdFn), _usdToMayaFn(usdToMayaFn) +{ +} + +bool +FunctionalAttributeConverter::MayaToUsd( + const MFnDependencyNode& srcNode, + UsdPrim& destPrim, + const UsdTimeCode usdTime) const +{ + if (_mayaToUsdFn) { + return _mayaToUsdFn(srcNode, destPrim, usdTime); + } + else { + return false; + } +} + +bool +FunctionalAttributeConverter::UsdToMaya( + const UsdPrim& srcPrim, + MFnDependencyNode& destNode, + const UsdTimeCode usdTime) const +{ + if (_usdToMayaFn) { + return _usdToMayaFn(srcPrim, destNode, usdTime); + } + else { + return false; + } +} diff --git a/third_party/maya/lib/usdMaya/AttributeConverter.h b/third_party/maya/lib/usdMaya/AttributeConverter.h new file mode 100644 index 0000000000..ef50e5e03b --- /dev/null +++ b/third_party/maya/lib/usdMaya/AttributeConverter.h @@ -0,0 +1,97 @@ +// +// 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 PXRUSDMAYA_ATTRIBUTECONVERTER_H +#define PXRUSDMAYA_ATTRIBUTECONVERTER_H + +/// \file AttributeConverter.h + +#include "pxr/usd/usd/prim.h" +#include "pxr/usd/usd/timeCode.h" + +#include + +#include + +/// \brief Provides a way to store USD-specific information on a Maya node +/// as an extra Maya attribute (e.g. "USD_hidden" for the hidden state) when no +/// existing Maya attribute maps cleanly. +/// +/// This way, we can store information such as the hidden state or the model +/// kind on a Maya node so that the information isn't lost in the USD to Maya to +/// USD roundtrip. +/// +/// This class encapsulates: +/// (1) a way to store non-attribute metadata or information (such as the hidden +/// state) on a Maya node when importing, and +/// (2) a way to write out the same metadata or information from a Maya node +/// into a \class UsdPrim when exporting. +class AttributeConverter { +public: + /// \brief Takes attribute(s) from a Maya node and modifies a + /// \class UsdPrim accordingly. + virtual bool MayaToUsd( + const MFnDependencyNode& depNode, + UsdPrim& destPrim, + const UsdTimeCode usdTime) const = 0; + + /// \brief Stores information about a source \class UsdPrim in a Maya node. + virtual bool UsdToMaya( + const UsdPrim& srcPrim, + MFnDependencyNode& destNode, + const UsdTimeCode usdTime) const = 0; +}; + +/// \brief An implementation of \class AttributeConverter that allows passing in +/// functions or lambdas to handle the conversion between Maya and USD. +class FunctionalAttributeConverter : public AttributeConverter { +public: + typedef std::function< bool (const MFnDependencyNode&, UsdPrim&, + UsdTimeCode) > MayaToUsdFn; + typedef std::function< bool (const UsdPrim&, MFnDependencyNode&, + UsdTimeCode) > UsdToMayaFn; + + virtual bool MayaToUsd( + const MFnDependencyNode& depNode, + UsdPrim& destPrim, + const UsdTimeCode usdTime) const override; + virtual bool UsdToMaya( + const UsdPrim& srcPrim, + MFnDependencyNode& destNode, + const UsdTimeCode usdTime) const override; + + /// \brief Constructs a FunctionalAttributeConverter that forwards calls to + /// MayaToUsd and UsdToMaya to the given functions. + /// + /// The functions can be empty functions, in which case MayaToUsd and/or + /// UsdToMaya will return false. + FunctionalAttributeConverter( + MayaToUsdFn mayaToUsdFn, + UsdToMayaFn usdToMayaFn); + +private: + const MayaToUsdFn _mayaToUsdFn; + const UsdToMayaFn _usdToMayaFn; +}; + +#endif // PXRUSDMAYA_ATTRIBUTECONVERTER_H diff --git a/third_party/maya/lib/usdMaya/AttributeConverterRegistry.cpp b/third_party/maya/lib/usdMaya/AttributeConverterRegistry.cpp new file mode 100644 index 0000000000..3ee1387bfc --- /dev/null +++ b/third_party/maya/lib/usdMaya/AttributeConverterRegistry.cpp @@ -0,0 +1,45 @@ +// +// 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. +// +#include "usdMaya/AttributeConverterRegistry.h" + +#include "pxr/base/tf/registryManager.h" + +static std::vector _reg; + +/* static */ +void +AttributeConverterRegistry::Register(AttributeConverter* converter) { + _reg.push_back(converter); +} + +/* static */ +std::vector +AttributeConverterRegistry::GetAllConverters() { + TfRegistryManager::GetInstance().SubscribeTo(); + std::vector ret; + for (AttributeConverter* converter : _reg) { + ret.push_back(converter); + } + return ret; +} diff --git a/third_party/maya/lib/usdMaya/AttributeConverterRegistry.h b/third_party/maya/lib/usdMaya/AttributeConverterRegistry.h new file mode 100644 index 0000000000..483cbdac33 --- /dev/null +++ b/third_party/maya/lib/usdMaya/AttributeConverterRegistry.h @@ -0,0 +1,45 @@ +// +// 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 PXRUSDMAYA_ATTRIBUTECONVERTERREGISTRY_H +#define PXRUSDMAYA_ATTRIBUTECONVERTERREGISTRY_H + +/// \file AttributeConverterRegistry.h + +#include + +class AttributeConverter; + +/// \brief A registry of all the converters used to import and export +/// USD-specific information stored in Maya attributes (e.g. "USD_hidden"). +struct AttributeConverterRegistry { + /// \brief Registers the given attribute converter. + /// Ownership of the converter \p converter transfers to + /// AttributeConverterRegistry. + static void Register(AttributeConverter* converter); + + /// \brief Gets a copy of the list of all registered converters. + static std::vector GetAllConverters(); +}; + +#endif // PXRUSDMAYA_ATTRIBUTECONVERTERREGISTRY_H diff --git a/third_party/maya/lib/usdMaya/CMakeLists.txt b/third_party/maya/lib/usdMaya/CMakeLists.txt index a11c7dd7d1..373ac8fd53 100644 --- a/third_party/maya/lib/usdMaya/CMakeLists.txt +++ b/third_party/maya/lib/usdMaya/CMakeLists.txt @@ -69,6 +69,9 @@ pxr_shared_library(${PXR_PACKAGE} Chaser ChaserRegistry + + AttributeConverter + AttributeConverterRegistry PRIVATE_CLASSES registryHelper @@ -97,6 +100,7 @@ pxr_shared_library(${PXR_PACKAGE} translatorMesh_SubDiv.cpp translatorXformable_decompose.cpp usdReadJob_ImportWithProxies.cpp + UsdMetadataAttributeConverters.cpp PYMODULE_CPPFILES module.cpp diff --git a/third_party/maya/lib/usdMaya/MayaPrimWriter.cpp b/third_party/maya/lib/usdMaya/MayaPrimWriter.cpp index 3fc1c37756..81c6d55bcb 100644 --- a/third_party/maya/lib/usdMaya/MayaPrimWriter.cpp +++ b/third_party/maya/lib/usdMaya/MayaPrimWriter.cpp @@ -27,6 +27,8 @@ #include "usdMaya/writeUtil.h" #include "usdMaya/translatorGprim.h" #include "usdMaya/primWriterContext.h" +#include "usdMaya/AttributeConverter.h" +#include "usdMaya/AttributeConverterRegistry.h" #include "pxr/base/gf/gamma.h" @@ -65,33 +67,12 @@ MayaPrimWriter::MayaPrimWriter(MDagPath & iDag, } } - -void -_writeUsdInfo( - const MDagPath& dag, - const UsdTimeCode& usdTime, - const UsdPrim& prim) -{ - MFnDependencyNode depFn(dag.node()); - - bool instanceable = false; - if (PxrUsdMayaUtil::getPlugValue(depFn, "USD_instanceable", &instanceable)) { - prim.SetInstanceable(instanceable); - } - - // We only author hidden if it's to set it to true. - bool hidden = false; - if (PxrUsdMayaUtil::getPlugValue(depFn, "USD_hidden", &hidden) and hidden) { - prim.SetHidden(hidden); - } -} - bool MayaPrimWriter::writePrimAttrs(const MDagPath &dagT, const UsdTimeCode &usdTime, UsdGeomImageable &primSchema) { MStatus status; MFnDependencyNode depFn(getDagPath().node()); - MFnDependencyNode depFn2(dagT.node()); // optionally also scan a shape's transform if merging transforms + MFnDependencyNode depFnT(dagT.node()); // optionally also scan a shape's transform if merging transforms if (getArgs().exportVisibility) { bool isVisible = true; // if BOTH shape or xform is animated, then visible @@ -101,7 +82,7 @@ MayaPrimWriter::writePrimAttrs(const MDagPath &dagT, const UsdTimeCode &usdTime, if ( dagT.isValid() ) { bool isVis, isAnim; - if (PxrUsdMayaUtil::getPlugValue(depFn2, "visibility", &isVis, &isAnim)){ + if (PxrUsdMayaUtil::getPlugValue(depFnT, "visibility", &isVis, &isAnim)){ isVisible = isVisible and isVis; isAnimated = isAnimated or isAnim; } @@ -132,7 +113,13 @@ MayaPrimWriter::writePrimAttrs(const MDagPath &dagT, const UsdTimeCode &usdTime, } - _writeUsdInfo(dagT, usdTime, usdPrim); + // Process special "USD_" attributes. + std::vector converters = + AttributeConverterRegistry::GetAllConverters(); + for (const AttributeConverter* converter : converters) { + // We want the node for the xform (depFnT). + converter->MayaToUsd(depFnT, usdPrim, usdTime); + } // Write user-tagged export attributes. Write attributes on the transform // first, and then attributes on the shape node. This means that attribute diff --git a/third_party/maya/lib/usdMaya/UsdMetadataAttributeConverters.cpp b/third_party/maya/lib/usdMaya/UsdMetadataAttributeConverters.cpp new file mode 100644 index 0000000000..3862dbc10d --- /dev/null +++ b/third_party/maya/lib/usdMaya/UsdMetadataAttributeConverters.cpp @@ -0,0 +1,129 @@ +// +// 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. +// + +/// \file UsdMetadataAttributeConverters.cpp +/// This file registers converters for storing USD-specific metadata, such +/// as model kind, in extra "USD_" attributes on Maya nodes. + +#include "usdMaya/AttributeConverter.h" +#include "usdMaya/AttributeConverterRegistry.h" +#include "usdMaya/util.h" + +#include "pxr/base/tf/registryManager.h" +#include "pxr/usd/usd/modelAPI.h" +#include "pxr/usd/usd/prim.h" +#include "pxr/usd/usd/timeCode.h" + +TF_DEFINE_PRIVATE_TOKENS( + _tokens, + (USD_hidden) + (USD_instanceable) + (USD_kind) +); + +// USD_hidden <-> UsdPrim.IsHidden() +TF_REGISTRY_FUNCTION(AttributeConverterRegistry) { + FunctionalAttributeConverter* converter = new FunctionalAttributeConverter( + [](const MFnDependencyNode& srcNode, UsdPrim& destPrim, + const UsdTimeCode) { + // We only author hidden if it's to set it to true. + bool hidden = false; + if (PxrUsdMayaUtil::getPlugValue(srcNode, + _tokens->USD_hidden.GetText(), &hidden) and hidden) { + destPrim.SetHidden(hidden); + } + return true; + }, + [](const UsdPrim& srcPrim, MFnDependencyNode& destNode, + const UsdTimeCode) { + if (srcPrim.IsHidden()) { + PxrUsdMayaUtil::createNumericAttribute(destNode, + _tokens->USD_hidden.GetText(), + MFnNumericData::kBoolean); + PxrUsdMayaUtil::setPlugValue(destNode, + _tokens->USD_hidden.GetText(), true); + } + return true; + } + ); + AttributeConverterRegistry::Register(converter); +} + +// USD_instanceable <-> UsdPrim.IsInstanceable() +TF_REGISTRY_FUNCTION(AttributeConverterRegistry) { + FunctionalAttributeConverter* converter = new FunctionalAttributeConverter( + [](const MFnDependencyNode& srcNode, UsdPrim& destPrim, + const UsdTimeCode) { + bool instanceable = false; + if (PxrUsdMayaUtil::getPlugValue(srcNode, + _tokens->USD_instanceable.GetText(), &instanceable)) { + destPrim.SetInstanceable(instanceable); + } + return true; + }, + [](const UsdPrim& srcPrim, MFnDependencyNode& destNode, + const UsdTimeCode) { + if (srcPrim.IsInstanceable()) { + PxrUsdMayaUtil::createNumericAttribute(destNode, + _tokens->USD_instanceable.GetText(), + MFnNumericData::kBoolean); + PxrUsdMayaUtil::setPlugValue(destNode, + _tokens->USD_instanceable.GetText(), true); + } + return true; + } + ); + AttributeConverterRegistry::Register(converter); +} + +// USD_kind <-> UsdModelAPI.GetKind() +TF_REGISTRY_FUNCTION(AttributeConverterRegistry) { + FunctionalAttributeConverter* converter = new FunctionalAttributeConverter( + [](const MFnDependencyNode& srcNode, UsdPrim& destPrim, + const UsdTimeCode) { + MString kind; + if (PxrUsdMayaUtil::getPlugValue(srcNode, + _tokens->USD_kind.GetText(), &kind)) { + UsdModelAPI model(destPrim); + TfToken kindToken(kind.asChar()); + model.SetKind(kindToken); + } + return true; + }, + [](const UsdPrim& srcPrim, MFnDependencyNode& destNode, + const UsdTimeCode) { + UsdModelAPI model(srcPrim); + TfToken kind; + if (model.GetKind(&kind)) { + PxrUsdMayaUtil::createStringAttribute(destNode, + _tokens->USD_kind.GetText()); + MString kindString(kind.GetText()); + PxrUsdMayaUtil::setPlugValue(destNode, + _tokens->USD_kind.GetText(), kindString); + } + return true; + } + ); + AttributeConverterRegistry::Register(converter); +} diff --git a/third_party/maya/lib/usdMaya/translatorPrim.cpp b/third_party/maya/lib/usdMaya/translatorPrim.cpp index fa5e816dd4..00843b46f5 100644 --- a/third_party/maya/lib/usdMaya/translatorPrim.cpp +++ b/third_party/maya/lib/usdMaya/translatorPrim.cpp @@ -24,6 +24,8 @@ #include "usdMaya/translatorPrim.h" #include "usdMaya/util.h" +#include "usdMaya/AttributeConverter.h" +#include "usdMaya/AttributeConverterRegistry.h" #include "pxr/usd/usdGeom/imageable.h" @@ -101,6 +103,14 @@ PxrUsdMayaTranslatorPrim::Read( } } } + + // Set "USD_" attributes to store USD-specific info on the Maya node. + // XXX: Handle animation properly in attribute converters. + std::vector converters = + AttributeConverterRegistry::GetAllConverters(); + for (const AttributeConverter* converter : converters) { + converter->UsdToMaya(prim, depFn, UsdTimeCode::EarliestTime()); + } // XXX What about all the "user attributes" that PrimWriter exports??? } diff --git a/third_party/maya/lib/usdMaya/util.cpp b/third_party/maya/lib/usdMaya/util.cpp index 42686b77b4..d85cde86e5 100644 --- a/third_party/maya/lib/usdMaya/util.cpp +++ b/third_party/maya/lib/usdMaya/util.cpp @@ -35,6 +35,8 @@ #include #include #include +#include +#include #include #include #include @@ -1122,3 +1124,44 @@ PxrUsdMayaUtil::setPlugValue( return true; } + +bool +PxrUsdMayaUtil::createStringAttribute( + MFnDependencyNode& depNode, + const MString& attr) { + MStatus status = MStatus::kFailure; + MFnTypedAttribute typedAttrFn; + MObject attrObj = typedAttrFn.create( + attr, + attr, + MFnData::kString, + MObject::kNullObj, + &status); + CHECK_MSTATUS_AND_RETURN(status, false); + + status = depNode.addAttribute(attrObj); + CHECK_MSTATUS_AND_RETURN(status, false); + + return true; +} + +bool +PxrUsdMayaUtil::createNumericAttribute( + MFnDependencyNode& depNode, + const MString& attr, + MFnNumericData::Type type) { + MStatus status = MStatus::kFailure; + MFnNumericAttribute numericAttrFn; + MObject attrObj = numericAttrFn.create( + attr, + attr, + type, + 0, + &status); + CHECK_MSTATUS_AND_RETURN(status, false); + + status = depNode.addAttribute(attrObj); + CHECK_MSTATUS_AND_RETURN(status, false); + + return true; +} diff --git a/third_party/maya/lib/usdMaya/util.h b/third_party/maya/lib/usdMaya/util.h index 365a10d329..4a783047ee 100644 --- a/third_party/maya/lib/usdMaya/util.h +++ b/third_party/maya/lib/usdMaya/util.h @@ -37,6 +37,7 @@ #include #include #include +#include #include #include @@ -320,6 +321,15 @@ bool setPlugValue(MFnDependencyNode const &depNode, return false; } +bool createStringAttribute( + MFnDependencyNode& depNode, + const MString& attr); + +bool createNumericAttribute( + MFnDependencyNode& depNode, + const MString& attr, + MFnNumericData::Type type); + } // namespace PxrUsdMayaUtil #endif // PXRUSDMAYA_UTIL_H From 1b236369f6953ff53b1231f2869026a11725d100 Mon Sep 17 00:00:00 2001 From: spiffmon Date: Mon, 17 Oct 2016 13:36:54 -0700 Subject: [PATCH 209/380] Clarify some ArResolver documentation. (Internal change: 1661264) --- pxr/usd/lib/ar/resolver.h | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/pxr/usd/lib/ar/resolver.h b/pxr/usd/lib/ar/resolver.h index e323970726..c61bc09422 100644 --- a/pxr/usd/lib/ar/resolver.h +++ b/pxr/usd/lib/ar/resolver.h @@ -134,33 +134,35 @@ class AR_API ArResolver /// @} // --------------------------------------------------------------------- // - /// \name Layer-specific Operations + /// \name File/asset-specific Operations /// - /// \see SdfLayer /// @{ // --------------------------------------------------------------------- // - /// Returns the resolved filesystem path for the layer identified + /// Returns the resolved filesystem path for the file identified /// by \p path following the same path resolution behavior as in /// \ref Resolve(const std::string&). /// - /// If the layer identified by \p path represents an asset and - /// \p assetInfo is not \c nullptr, it will be populated with - /// additional information about the asset. + /// If the file identified by \p path represents an asset and + /// \p assetInfo is not \c nullptr, the resolver should populate + /// \p assetInfo with whatever additional metadata it knows or can + /// reasonably compute about the asset without actually opening it. /// /// \see Resolve(const std::string&). virtual std::string ResolveWithAssetInfo( const std::string& path, ArAssetInfo* assetInfo) = 0; - /// Update \p assetInfo with respect to the given \p fileVersion + /// Update \p assetInfo with respect to the given \p fileVersion . + /// \note This API is currently in flux. In general, you should prefer + /// to call ResolveWithAssetInfo() virtual void UpdateAssetInfo( const std::string& identifier, const std::string& filePath, const std::string& fileVersion, ArAssetInfo* assetInfo) = 0; - /// Returns true if a layer may be written to the given \p path, false + /// Returns true if a file may be written to the given \p path, false /// otherwise. /// /// If this function returns false and \p whyNot is not \c nullptr, @@ -169,7 +171,7 @@ class AR_API ArResolver const std::string& path, std::string* whyNot) = 0; - /// Returns true if a new layer may be created using the given + /// Returns true if a new file may be created using the given /// \p identifier, false otherwise. /// /// If this function returns false and \p whyNot is not \c nullptr, From c56892d1b2204036261f7fe97d40a5c69168a689 Mon Sep 17 00:00:00 2001 From: superfunc Date: Mon, 17 Oct 2016 13:37:26 -0700 Subject: [PATCH 210/380] [Usd] Add template metadata to Usd's ClipsAPI. (Internal change: 1661275) --- pxr/usd/lib/usd/clipsAPI.cpp | 129 +++++++++++++++++++++++++++ pxr/usd/lib/usd/clipsAPI.h | 73 ++++++++++++++- pxr/usd/lib/usd/generatedSchema.usda | 17 +++- pxr/usd/lib/usd/plugInfo.json | 24 +++++ pxr/usd/lib/usd/schema.usda | 53 ++++++++++- pxr/usd/lib/usd/tokens.h | 8 ++ pxr/usd/lib/usd/wrapClipsAPI.cpp | 53 +++++++++++ 7 files changed, 345 insertions(+), 12 deletions(-) diff --git a/pxr/usd/lib/usd/clipsAPI.cpp b/pxr/usd/lib/usd/clipsAPI.cpp index ca1b7b01db..bc510fdff2 100644 --- a/pxr/usd/lib/usd/clipsAPI.cpp +++ b/pxr/usd/lib/usd/clipsAPI.cpp @@ -209,3 +209,132 @@ UsdClipsAPI::GetClipTimes(VtVec2dArray* clipTimes) const return GetPrim().GetMetadata(UsdTokens->clipTimes, clipTimes); } + +bool +UsdClipsAPI::GetClipTemplateAssetPath(std::string* clipTemplateAssetPath) const +{ + if (GetPath() == SdfPath::AbsoluteRootPath()) { + // Special-case to pre-empt coding errors. + return false; + } + + return GetPrim().GetMetadata(UsdTokens->clipTemplateAssetPath, + clipTemplateAssetPath); +} + +bool +UsdClipsAPI::SetClipTemplateAssetPath(const std::string& clipTemplateAssetPath) +{ + if (GetPath() == SdfPath::AbsoluteRootPath()) { + // Special-case to pre-empt coding errors. + return false; + } + + return GetPrim().SetMetadata(UsdTokens->clipTemplateAssetPath, + clipTemplateAssetPath); +} + +bool +UsdClipsAPI::GetClipTemplateStride(double* clipTemplateStride) const +{ + if (GetPath() == SdfPath::AbsoluteRootPath()) { + // Special-case to pre-empt coding errors. + return false; + } + + return GetPrim().GetMetadata(UsdTokens->clipTemplateStride, + clipTemplateStride); +} + +bool +UsdClipsAPI::SetClipTemplateStride(const double clipTemplateStride) +{ + if (GetPath() == SdfPath::AbsoluteRootPath()) { + // Special-case to pre-empt coding errors. + return false; + } + + return GetPrim().SetMetadata(UsdTokens->clipTemplateStride, + clipTemplateStride); +} + +bool +UsdClipsAPI::GetClipTemplateStartTime(double* clipTemplateStartTime) const +{ + if (GetPath() == SdfPath::AbsoluteRootPath()) { + // Special-case to pre-empt coding errors. + return false; + } + + return GetPrim().GetMetadata(UsdTokens->clipTemplateStartTime, + clipTemplateStartTime); +} + +bool +UsdClipsAPI::SetClipTemplateStartTime(const double clipTemplateStartTime) +{ + if (GetPath() == SdfPath::AbsoluteRootPath()) { + // Special-case to pre-empt coding errors. + return false; + } + + return GetPrim().SetMetadata(UsdTokens->clipTemplateStartTime, + clipTemplateStartTime); +} + +bool +UsdClipsAPI::GetClipTemplateEndTime(double* clipTemplateEndTime) const +{ + if (GetPath() == SdfPath::AbsoluteRootPath()) { + // Special-case to pre-empt coding errors. + return false; + } + + return GetPrim().GetMetadata(UsdTokens->clipTemplateEndTime, + clipTemplateEndTime); +} + +bool +UsdClipsAPI::SetClipTemplateEndTime(const double clipTemplateEndTime) +{ + if (GetPath() == SdfPath::AbsoluteRootPath()) { + // Special-case to pre-empt coding errors. + return false; + } + + return GetPrim().SetMetadata(UsdTokens->clipTemplateEndTime, + clipTemplateEndTime); +} + +bool +UsdClipsAPI::ClearTemplateClipMetadata() +{ + if (GetPath() == SdfPath::AbsoluteRootPath()) { + // Special-case to pre-empt coding errors. + return false; + } + + auto prim = GetPrim(); + prim.ClearMetadata(UsdTokens->clipTemplateAssetPath); + prim.ClearMetadata(UsdTokens->clipTemplateStride); + prim.ClearMetadata(UsdTokens->clipTemplateEndTime); + prim.ClearMetadata(UsdTokens->clipTemplateStartTime); + + return true; +} + +bool +UsdClipsAPI::ClearNonTemplateClipMetadata() +{ + if (GetPath() == SdfPath::AbsoluteRootPath()) { + // Special-case to pre-empt coding errors. + return false; + } + + auto prim = GetPrim(); + prim.ClearMetadata(UsdTokens->clipAssetPaths); + prim.ClearMetadata(UsdTokens->clipTimes); + prim.ClearMetadata(UsdTokens->clipActive); + + return true; +} diff --git a/pxr/usd/lib/usd/clipsAPI.h b/pxr/usd/lib/usd/clipsAPI.h index f08d5895c9..5846145a92 100644 --- a/pxr/usd/lib/usd/clipsAPI.h +++ b/pxr/usd/lib/usd/clipsAPI.h @@ -62,10 +62,19 @@ class SdfAssetPath; /// SetClipActive() specifies the ordering of clip application over time /// (clips can be repeated), while SetClipTimes() specifies time-mapping /// from stage-time to clip-time for the clip active at a given stage-time, -/// which allows for time-dilation and repetition of clips. Finally, -/// SetClipPrimPath() determines the path within each clip that will map +/// which allows for time-dilation and repetition of clips. +/// Finally, SetClipPrimPath() determines the path within each clip that will map /// to this prim, i.e. the location within the clip at which we will look -/// for opinions for this prim. +/// for opinions for this prim. +/// +/// The clipAssetPaths, clipTimes and clipActive metadata can also be specified +/// through template clip metadata. This can be desirable when your set of +/// assets is very large, as the template metadata is much more concise. +/// SetClipTemplateAssetPath() establishes the asset identifier pattern of the set of +/// clips to be consulted. SetClipTemplateStride(), SetClipTemplateEndTime(), +/// and SetClipTemplateStartTime() specify the range in which USD will search, based +/// on the template. From the set of resolved asset paths, clipTimes, and clipActive +/// will be derived internally. /// /// Important facts about clips: /// li Within the layerstack in which clips are established, the @@ -208,9 +217,65 @@ class UsdClipsAPI : public UsdSchemaBase /// only look within this prim's clips if the attribute /// exists and is varying in the manifest. bool GetClipManifestAssetPath(SdfAssetPath* manifestAssetPath) const; - /// Get the clipManifestAssetPath metadata for this prim. + /// Set the clipManifestAssetPath metadata for this prim. /// \sa GetClipManifestAssetPath() bool SetClipManifestAssetPath(const SdfAssetPath& manifestAssetPath); + + /// A template string representing a set of assets. This string + /// can be of two forms: path/basename.###.usd and path/basename.##.##.usd. + /// In either case, the number of hash marks in each section is variable. + /// These control the amount of padding USD will supply when looking up + /// the assets. For instance, a value of 'foo.###.usd', + /// with clipTemplateStartTime=11, clipTemplateEndTime=15, and clipTemplateStride=1: + /// USD will look for: foo.11.usd, foo.12.usd, foo.13.usd, foo.14.usd, foo.15.usd, + /// foo.011.usd, foo.012.usd, foo.013.usd, foo.014.usd and foo.015.usd. + bool GetClipTemplateAssetPath(std::string* clipTemplateAssetPath) const; + /// Set the clipTemplateAssetPath metadata for this prim. + /// \sa GetClipTemplateAssetPath + bool SetClipTemplateAssetPath(const std::string& clipTemplateAssetPath); + + /// A double representing the increment value USD will use when + /// searching for asset paths. For example usage see clipTemplateAssetPath. + bool GetClipTemplateStride(double* clipTemplateStride) const; + /// Set the clipTemplateStride metadata for this prim + /// \sa GetClipTemplateStride() + bool SetClipTemplateStride(const double clipTemplateStride); + + /// A double which indicates the start of the range USD will use + /// to search for asset paths. This value is inclusive in that range. + /// For example usage see clipTemplateAssetPath. + bool GetClipTemplateStartTime(double* clipTemplateStartTime) const; + /// Set the clipTemplateStartTime metadata for this prim + /// \sa GetClipTemplateStartTime + bool SetClipTemplateStartTime(const double clipTemplateStartTime); + + /// A double which indicates the end of the range USD will use to + /// to search for asset paths. This value is inclusive in that range. + /// For example usage see clipTemplateAssetPath. + bool GetClipTemplateEndTime(double* clipTemplateEndTime) const; + /// Set the clipTemplateEndTime metadata for this prim + /// \sa GetClipTemplateEndTime() + bool SetClipTemplateEndTime(const double clipTemplateEndTime); + + /// Clear out the following metadata from the current edit target: + /// + /// clipTemplateAssetPath + /// clipTemplateStride + /// clipTemplateStartTime + /// clipTemplateEndTime + /// + /// \sa ClearNonTemplateClipMetadata() + bool ClearTemplateClipMetadata(); + + /// Clear out the following metadata from the current edit target: + /// + /// clipTimes + /// clipActive + /// clipAssetPaths + /// + /// \sa ClearTemplateClipMetadata() + bool ClearNonTemplateClipMetadata(); + }; #endif diff --git a/pxr/usd/lib/usd/generatedSchema.usda b/pxr/usd/lib/usd/generatedSchema.usda index f2db58426e..3e687b78d4 100644 --- a/pxr/usd/lib/usd/generatedSchema.usda +++ b/pxr/usd/lib/usd/generatedSchema.usda @@ -41,11 +41,20 @@ class "ClipsAPI" ( SetClipActive() specifies the ordering of clip application over time (clips can be repeated), while SetClipTimes() specifies time-mapping from stage-time to clip-time for the clip active at a given stage-time, - which allows for time-dilation and repetition of clips. Finally, - SetClipPrimPath() determines the path within each clip that will map + which allows for time-dilation and repetition of clips. + Finally, SetClipPrimPath() determines the path within each clip that will map to this prim, i.e. the location within the clip at which we will look - for opinions for this prim. - + for opinions for this prim. + + The clipAssetPaths, clipTimes and clipActive metadata can also be specified + through template clip metadata. This can be desirable when your set of + assets is very large, as the template metadata is much more concise. + SetClipTemplateAssetPath() establishes the asset identifier pattern of the set of + clips to be consulted. SetClipTemplateStride(), SetClipTemplateEndTime(), + and SetClipTemplateStartTime() specify the range in which USD will search, based + on the template. From the set of resolved asset paths, clipTimes, and clipActive + will be derived internally. + Important facts about clips: li Within the layerstack in which clips are established, the opinions within the clips will be em weaker than any direct opinions diff --git a/pxr/usd/lib/usd/plugInfo.json b/pxr/usd/lib/usd/plugInfo.json index 38d777a94e..f160f96152 100644 --- a/pxr/usd/lib/usd/plugInfo.json +++ b/pxr/usd/lib/usd/plugInfo.json @@ -30,6 +30,30 @@ ], "type": "string" }, + "clipTemplateAssetPath": { + "appliesTo": [ + "prims" + ], + "type": "string" + }, + "clipTemplateEndTime": { + "appliesTo": [ + "prims" + ], + "type": "double" + }, + "clipTemplateStartTime": { + "appliesTo": [ + "prims" + ], + "type": "double" + }, + "clipTemplateStride": { + "appliesTo": [ + "prims" + ], + "type": "double" + }, "clipTimes": { "appliesTo": [ "prims" diff --git a/pxr/usd/lib/usd/schema.usda b/pxr/usd/lib/usd/schema.usda index 579fa295c0..257eb027b2 100644 --- a/pxr/usd/lib/usd/schema.usda +++ b/pxr/usd/lib/usd/schema.usda @@ -70,6 +70,42 @@ def "GLOBAL" ( at time 0 and clip 1 is active at time 20. """ } + + dictionary clipTemplateAssetPath = { + string doc = """ + A template string representing a set of assets. This string + can be of two forms: path/basename.###.usd and path/basename.##.##.usd. + In either case, the number of hash marks in each section is variable. + These control the amount of padding USD will supply when looking up + the assets. For instance, a value of 'foo.###.usd', + with clipTemplateStartTime=11, clipTemplateEndTime=15, and clipTemplateStride=1: + USD will look for: foo.11.usd, foo.12.usd, foo.13.usd, foo.14.usd, foo.15.usd, + foo.011.usd, foo.012.usd, foo.013.usd, foo.014.usd and foo.015.usd. + """ + } + + dictionary clipTemplateStride = { + string doc = """ + A double representing the increment value USD will use when + searching for asset paths. For example usage see clipTemplateAssetPath. + """ + } + + dictionary clipTemplateStartTime = { + string doc = """ + A double which indicates the start of the range USD will use + to search for asset paths. This value is inclusive in that range. + For example usage see clipTemplateAssetPath. + """ + } + + dictionary clipTemplateEndTime = { + string doc = """ + A double which indicates the end of the range USD will use to + to search for asset paths. This value is inclusive in that range. + For example usage see clipTemplateAssetPath. + """ + } } } ) @@ -128,11 +164,20 @@ class "ClipsAPI" SetClipActive() specifies the ordering of clip application over time (clips can be repeated), while SetClipTimes() specifies time-mapping from stage-time to clip-time for the clip active at a given stage-time, - which allows for time-dilation and repetition of clips. Finally, - SetClipPrimPath() determines the path within each clip that will map + which allows for time-dilation and repetition of clips. + Finally, SetClipPrimPath() determines the path within each clip that will map to this prim, i.e. the location within the clip at which we will look - for opinions for this prim. - + for opinions for this prim. + + The clipAssetPaths, clipTimes and clipActive metadata can also be specified + through template clip metadata. This can be desirable when your set of + assets is very large, as the template metadata is much more concise. + SetClipTemplateAssetPath() establishes the asset identifier pattern of the set of + clips to be consulted. SetClipTemplateStride(), SetClipTemplateEndTime(), + and SetClipTemplateStartTime() specify the range in which USD will search, based + on the template. From the set of resolved asset paths, clipTimes, and clipActive + will be derived internally. + Important facts about clips: \li Within the layerstack in which clips are established, the opinions within the clips will be \em weaker than any direct opinions diff --git a/pxr/usd/lib/usd/tokens.h b/pxr/usd/lib/usd/tokens.h index 60a777d07c..feb8861168 100644 --- a/pxr/usd/lib/usd/tokens.h +++ b/pxr/usd/lib/usd/tokens.h @@ -41,6 +41,10 @@ (clipAssetPaths) \ (clipManifestAssetPath) \ (clipPrimPath) \ + (clipTemplateAssetPath) \ + (clipTemplateEndTime) \ + (clipTemplateStartTime) \ + (clipTemplateStride) \ (clipTimes) /// \anchor UsdTokens @@ -67,6 +71,10 @@ /// \li clipAssetPaths - List of asset paths to the clips for this prim. This list is unordered, but elements in this list are referred to by index in other clip-related fields. /// \li clipManifestAssetPath - Asset path for the clip manifest. The clip manifest indicates which attributes have time samples authored in the clips specified on this prim. During value resolution, we will only look for time samples in clips if the attribute exists and is declared as varying in the manifest. Note that the clip manifest is only consulted to check check if an attribute exists and what its variability is. Other values and metadata authored in the manifest will be ignored. For instance, if this prims' path is '/Prim_1', the clip prim path is '/Prim', and we want values for the attribute '/Prim_1.size', we will only look within this prims' clips if the attribute '/Prim.size' exists and is varying in the manifest. /// \li clipPrimPath - Path to the prim in the clips from which time samples will be read. This prim's path will be substituted with this value to determine the final path in the clip from which to read data. For instance, if this prims' path is '/Prim_1', the clip prim path is '/Prim', and we want to get values for the attribute '/Prim_1.size'. The clip prim path will be substituted in, yielding '/Prim.size', and each clip will be examined for values at that path. +/// \li clipTemplateAssetPath - A template string representing a set of assets. This string can be of two forms: path/basename.###.usd and path/basename.##.##.usd. In either case, the number of hash marks in each section is variable. These control the amount of padding USD will supply when looking up the assets. For instance, a value of 'foo.###.usd', with clipTemplateStartTime=11, clipTemplateEndTime=15, and clipTemplateStride=1: USD will look for: foo.11.usd, foo.12.usd, foo.13.usd, foo.14.usd, foo.15.usd, foo.011.usd, foo.012.usd, foo.013.usd, foo.014.usd and foo.015.usd. +/// \li clipTemplateEndTime - A double which indicates the end of the range USD will use to to search for asset paths. This value is inclusive in that range. For example usage see clipTemplateAssetPath. +/// \li clipTemplateStartTime - A double which indicates the start of the range USD will use to search for asset paths. This value is inclusive in that range. For example usage see clipTemplateAssetPath. +/// \li clipTemplateStride - A double representing the increment value USD will use when searching for asset paths. For example usage see clipTemplateAssetPath. /// \li clipTimes - List of pairs (stage time, clip time) indicating the time in the active clip that should be consulted for values at the corresponding stage time. During value resolution, this list will be sorted by stage time; times will then be linearly interpolated between consecutive entries. For instance, for clip times [(0.0, 0.0), (10.0, 20.0)], at stage time 0, values from the active clip at time 0 will be used, at stage time 5, values from the active clip at time 10, and at stage time 10, clip values at time 20. TF_DECLARE_PUBLIC_TOKENS(UsdTokens, USD_TOKENS); diff --git a/pxr/usd/lib/usd/wrapClipsAPI.cpp b/pxr/usd/lib/usd/wrapClipsAPI.cpp index 585720fe89..3bf6006692 100644 --- a/pxr/usd/lib/usd/wrapClipsAPI.cpp +++ b/pxr/usd/lib/usd/wrapClipsAPI.cpp @@ -157,6 +157,40 @@ static SdfAssetPath _GetClipManifestAssetPath(UsdClipsAPI &self) { return manifestAssetPath; } +static void _SetClipTemplateAssetPath(UsdClipsAPI& self, TfPyObjWrapper pyVal) { + VtValue v = UsdPythonToSdfType(pyVal, SdfValueTypeNames->String); + if (not v.IsHolding()) { + TF_CODING_ERROR("Invalid value for 'clipTemplateAssetPath' on %s", + UsdDescribe(self.GetPrim()).c_str()); + return; + } + + self.SetClipTemplateAssetPath(v.UncheckedGet()); +} + +static std::string _GetClipTemplateAssetPath(UsdClipsAPI &self) { + std::string clipTemplateAssetPath; + self.GetClipTemplateAssetPath(&clipTemplateAssetPath); + return clipTemplateAssetPath; +} + +static double _GetClipTemplateStride(UsdClipsAPI &self) { + double clipTemplateStride; + self.GetClipTemplateStride(&clipTemplateStride); + return clipTemplateStride; +} + +static double _GetClipTemplateStartTime(UsdClipsAPI &self) { + double clipTemplateStartTime; + self.GetClipTemplateStartTime(&clipTemplateStartTime); + return clipTemplateStartTime; +} + +static double _GetClipTemplateEndTime(UsdClipsAPI &self) { + double clipTemplateEndTime; + self.GetClipTemplateEndTime(&clipTemplateEndTime); + return clipTemplateEndTime; +} WRAP_CUSTOM { _class @@ -172,5 +206,24 @@ WRAP_CUSTOM { .def("GetClipManifestAssetPath", _GetClipManifestAssetPath) .def("SetClipManifestAssetPath", &UsdClipsAPI::SetClipManifestAssetPath, arg("manifestAssetPath")) + .def("GetClipTemplateAssetPath", _GetClipTemplateAssetPath) + .def("SetClipTemplateAssetPath", _SetClipTemplateAssetPath, + arg("clipTemplateAssetPath")) + .def("GetClipTemplateStride", _GetClipTemplateStride) + .def("SetClipTemplateStride", &UsdClipsAPI::SetClipTemplateStride, + arg("clipTemplateStride")) + .def("GetClipTemplateStride", _GetClipTemplateStride) + .def("SetClipTemplateStride", &UsdClipsAPI::SetClipTemplateStride, + arg("clipTemplateStride")) + .def("GetClipTemplateStartTime", _GetClipTemplateStartTime) + .def("SetClipTemplateStartTime", &UsdClipsAPI::SetClipTemplateStartTime, + arg("clipTemplateStartTime")) + .def("GetClipTemplateEndTime", _GetClipTemplateEndTime) + .def("SetClipTemplateEndTime", &UsdClipsAPI::SetClipTemplateEndTime, + arg("clipTemplateEndTime")) + .def("ClearNonTemplateClipMetadata", + &UsdClipsAPI::ClearNonTemplateClipMetadata) + .def("ClearTemplateClipMetadata", + &UsdClipsAPI::ClearTemplateClipMetadata) ; } From e7d5f1faa347060cd4c15459882d4eacefef9ca2 Mon Sep 17 00:00:00 2001 From: blevin Date: Mon, 17 Oct 2016 13:37:39 -0700 Subject: [PATCH 211/380] Pcp: PcpMapExpression optimizations aimed at inherits arcs. - Add a fast path for manipulating constant identity ops; they occur when propagating inherits across relocates and variant arcs. - Only fold in expression terms for relocations when needed. (Internal change: 1661309) --- pxr/usd/lib/pcp/mapExpression.cpp | 15 +++++++++++++++ pxr/usd/lib/pcp/mapExpression.h | 6 ++++++ pxr/usd/lib/pcp/primIndex.cpp | 9 +++++++++ 3 files changed, 30 insertions(+) diff --git a/pxr/usd/lib/pcp/mapExpression.cpp b/pxr/usd/lib/pcp/mapExpression.cpp index c5522f5edb..687d601982 100644 --- a/pxr/usd/lib/pcp/mapExpression.cpp +++ b/pxr/usd/lib/pcp/mapExpression.cpp @@ -88,6 +88,13 @@ PcpMapExpression::Constant( const Value & value ) PcpMapExpression PcpMapExpression::Compose(const PcpMapExpression &f) const { + // Fast path short-circuits for identities + if (IsConstantIdentity()) { + return f; + } + if (f.IsConstantIdentity()) { + return *this; + } if (_node->key.op == _OpConstant and f._node->key.op == _OpConstant) { // Apply constant folding return Constant( Evaluate().Compose( f.Evaluate() ) ); @@ -98,6 +105,10 @@ PcpMapExpression::Compose(const PcpMapExpression &f) const PcpMapExpression PcpMapExpression::Inverse() const { + // Fast path short-circuits for identities + if (IsConstantIdentity()) { + return *this; + } if (_node->key.op == _OpConstant) { // Apply constant folding return Constant( Evaluate().GetInverse() ); @@ -108,6 +119,10 @@ PcpMapExpression::Inverse() const PcpMapExpression PcpMapExpression::AddRootIdentity() const { + // Fast path short-circuits for identities + if (IsConstantIdentity()) { + return *this; + } if (_node->key.op == _OpConstant) { // Apply constant folding return Constant( _AddRootIdentity(Evaluate()) ); diff --git a/pxr/usd/lib/pcp/mapExpression.h b/pxr/usd/lib/pcp/mapExpression.h index 0cdd283d6b..0f66566456 100644 --- a/pxr/usd/lib/pcp/mapExpression.h +++ b/pxr/usd/lib/pcp/mapExpression.h @@ -116,6 +116,12 @@ class PcpMapExpression /// (if necessary) mapping from to . PcpMapExpression AddRootIdentity() const; + /// Return true if the map function is the constant identity function. + bool IsConstantIdentity() const { + return _node && _node->key.op == _OpConstant && + _node->key.valueForConstant.IsIdentity(); + } + /// @} /// \name Convenience API diff --git a/pxr/usd/lib/pcp/primIndex.cpp b/pxr/usd/lib/pcp/primIndex.cpp index d1a3aacd1e..beda080387 100644 --- a/pxr/usd/lib/pcp/primIndex.cpp +++ b/pxr/usd/lib/pcp/primIndex.cpp @@ -2256,6 +2256,10 @@ static PcpMapExpression _GetImpliedClass( const PcpMapExpression & transfer, const PcpMapExpression & classArc ) { + if (transfer.IsConstantIdentity()) { + return classArc; + } + return transfer.Compose( classArc.Compose( transfer.Inverse() )) .AddRootIdentity(); } @@ -2480,6 +2484,11 @@ _EvalImpliedClasses( return; } + // Optimization: early-out if there are no class arcs to propagate. + if (not _HasClassBasedChild(node)) { + return; + } + // Grab the mapping to the parent node. // We will use it to map ("transfer") the class to the parent. // The mapping to the parent may have a restricted domain, such as From d3ac09412dcd28aac8b7c0a6a4b4d3f99d24fe55 Mon Sep 17 00:00:00 2001 From: blevin Date: Mon, 17 Oct 2016 13:38:18 -0700 Subject: [PATCH 212/380] Pcp: 15% speedup to PcpMapFunction::Compose(). Time measured running Compose() on 100k pairs logged from a presto production project. - when mapping paths, look for the longest path that has a prefix, rather than walking up the parent nodes -- this is equivalent but avoids extra atomic refcount ops - use SdfPath pointer order for map entry ordering - when canonicalizing mappings, hoist the trivial redundant-entry check to the top - speculatively reserve working std::vector size of 2 based on stats from production (Internal change: 1661311) --- pxr/usd/lib/pcp/mapFunction.cpp | 201 +++++++++++++++++++------------- 1 file changed, 120 insertions(+), 81 deletions(-) diff --git a/pxr/usd/lib/pcp/mapFunction.cpp b/pxr/usd/lib/pcp/mapFunction.cpp index c8cb858168..6ed09f6d78 100644 --- a/pxr/usd/lib/pcp/mapFunction.cpp +++ b/pxr/usd/lib/pcp/mapFunction.cpp @@ -29,6 +29,26 @@ #include "pxr/base/tf/staticData.h" #include +namespace { + // Order PathPairs using FastLessThan. + struct _PathPairOrder + { + bool operator()(const PcpMapFunction::PathPair &lhs, + const PcpMapFunction::PathPair &rhs) { + if (SdfPath::FastLessThan()(lhs.first, rhs.first)) { + return true; + } + if (SdfPath::FastLessThan()(rhs.first, lhs.first)) { + return false; + } + if (SdfPath::FastLessThan()(lhs.second, rhs.second)) { + return true; + } + return false; + } + }; +}; + PcpMapFunction::PcpMapFunction() { } @@ -69,9 +89,20 @@ _Canonicalize(PcpMapFunction::PathPairVector *vec) i != vec->end(); /* increment below */) { bool redundant = false; + + // Check for trivial dupes before doing further work. + for (PcpMapFunction::PathPairVector::iterator j = vec->begin(); + j != i; ++j) { + if (*i == *j) { + redundant = true; + break; + } + } + // Find the closest enclosing mapping. If the trailing name // components do not match, this pair cannot be redundant. - if (i->first.GetNameToken() == i->second.GetNameToken()) { + if (not redundant && + i->first.GetNameToken() == i->second.GetNameToken()) { // The tail component matches. Walk up the prefixes. for (SdfPath source = i->first, target = i->second; not source.IsEmpty() and not target.IsEmpty() @@ -103,17 +134,6 @@ _Canonicalize(PcpMapFunction::PathPairVector *vec) } } - // Check for trivial dupes. - if (not redundant) { - for (PcpMapFunction::PathPairVector::iterator j = vec->begin(); - j != i; ++j) { - if (*i == *j) { - redundant = true; - break; - } - } - } - if (redundant) { // Entries are not sorted yet so swap to back for O(1) erase. std::swap(*i, vec->back()); @@ -124,7 +144,7 @@ _Canonicalize(PcpMapFunction::PathPairVector *vec) } // Final sort to canonical order. - std::sort(vec->begin(), vec->end()); + std::sort(vec->begin(), vec->end(), _PathPairOrder()); } PcpMapFunction @@ -254,77 +274,80 @@ _Map(const SdfPath& path, // Find longest prefix that has a mapping; // this represents the most-specific mapping to apply. - SdfPath result; - int entryFound = -1; - for (SdfPath p = path; result.IsEmpty() and not p.IsEmpty(); - p = p.GetParentPath()) { - for (int i=0; i < numPairs; ++i) { - const SdfPath &source = invert? pairs[i].second : pairs[i].first; - const SdfPath &target = invert? pairs[i].first : pairs[i].second; - if (p == source) { - result = path.ReplacePrefix( source, target, - /* fixTargetPaths = */ false); - entryFound = i; - break; - } + int bestIndex = -1; + size_t bestElemCount = 0; + for (int i=0; i < numPairs; ++i) { + const SdfPath &source = invert? pairs[i].second : pairs[i].first; + const size_t count = source.GetPathElementCount(); + if (count >= bestElemCount and path.HasPrefix(source)) { + bestElemCount = count; + bestIndex = i; } } + if (bestIndex == -1) { + // No mapping found. + return SdfPath(); + } + const SdfPath &source = + invert? pairs[bestIndex].second : pairs[bestIndex].first; + const SdfPath &target = + invert? pairs[bestIndex].first : pairs[bestIndex].second; + SdfPath result = + path.ReplacePrefix(source, target, /* fixTargetPaths = */ false); + if (result.IsEmpty()) { + return result; + } - if (not result.IsEmpty()) { - // To maintain the bijection, we need to check if the mapped path - // would translate back to the original path. For instance, given - // the mapping: - // { / -> /, /_class_Model -> /Model } - // - // mapping /Model shouldn't be allowed, as the result is noninvertible: - // source to target: /Model -> /Model (due to identity mapping) - // target to source: /Model -> /_class_Model - // - // However, given the mapping: - // { /A -> /A/B } - // - // mapping /A/B should be allowed, as the result is invertible: - // source to target: /A/B -> /A/B/B - // target to source: /A/B/B -> /A/B - // - // Another example: - // { /A -> /B, /C -> /B/C } - // - // mapping /A/C should not be allowed, as the result is noninvertible: - // source to target: /A/C -> /B/C - // target to source: /B/C -> /C - // - // For examples, see test case for bug 74847 and bug 112645 in - // testPcpMapFunction. - // - // XXX: It seems inefficient to have to do this check every time - // we do a path mapping. I think it might be possible to figure - // out the 'disallowed' mappings and mark them in the mapping - // in PcpMapFunction's c'tor. That would let us get rid of this - // code. Figuring out the 'disallowed' mappings might be - // expensive though, possibly O(n^2) where n is the number of - // paths in the mapping. - // - for (SdfPath p = result; not p.IsEmpty(); p = p.GetParentPath()) { - for (int i=0; i < numPairs; ++i) { - const SdfPath &target = - invert? pairs[i].first : pairs[i].second; - if (p == target) { - // Found the applicable mapping. - if (i == entryFound) { - // This mapping provides a bijection, so use it. - return result; - } else { - // The input path maps outside the range, - // so we must exclude it from the domain too. - return SdfPath(); - } - } - } + // To maintain the bijection, we need to check if the mapped path + // would translate back to the original path. For instance, given + // the mapping: + // { / -> /, /_class_Model -> /Model } + // + // mapping /Model shouldn't be allowed, as the result is noninvertible: + // source to target: /Model -> /Model (due to identity mapping) + // target to source: /Model -> /_class_Model + // + // However, given the mapping: + // { /A -> /A/B } + // + // mapping /A/B should be allowed, as the result is invertible: + // source to target: /A/B -> /A/B/B + // target to source: /A/B/B -> /A/B + // + // Another example: + // { /A -> /B, /C -> /B/C } + // + // mapping /A/C should not be allowed, as the result is noninvertible: + // source to target: /A/C -> /B/C + // target to source: /B/C -> /C + // + // For examples, see test case for bug 74847 and bug 112645 in + // testPcpMapFunction. + // + // XXX: It seems inefficient to have to do this check every time + // we do a path mapping. I think it might be possible to figure + // out the 'disallowed' mappings and mark them in the mapping + // in PcpMapFunction's c'tor. That would let us get rid of this + // code. Figuring out the 'disallowed' mappings might be + // expensive though, possibly O(n^2) where n is the number of + // paths in the mapping. + // + + // Optimistically assume the same mapping will be the best; + // we can skip even considering any mapping that is shorter. + bestElemCount = target.GetPathElementCount(); + for (int i=0; i < numPairs; ++i) { + if (i == bestIndex) { + continue; + } + const SdfPath &target = invert? pairs[i].first : pairs[i].second; + const size_t count = target.GetPathElementCount(); + if (count > bestElemCount and result.HasPrefix(target)) { + // There is a more-specific reverse mapping for this path. + return SdfPath(); } } - - return SdfPath(); + return result; } SdfPath @@ -347,18 +370,32 @@ PcpMapFunction::Compose(const PcpMapFunction &inner) const TfAutoMallocTag2 tag("Pcp", "PcpMapFunction"); TRACE_FUNCTION(); + // Fast path identities. These do occur in practice and are + // worth special-casing since it lets us avoid heap allocation. + if (IsIdentity()) + return inner; + if (inner.IsIdentity()) + return *this; + // The composition of this function over inner is the result // of first applying inner, then this function. Build a list // of all of the (source,target) path pairs that result. std::vector pairs; + // A 100k random test subset from a production + // shot show a mean result size of 1.906050; + // typically a root identity + other path pair. + pairs.reserve(2); + // Apply outer function to the output range of inner. const _Data& data_inner = inner._GetData(); for (int i=0; i < data_inner._numPairs; ++i) { PathPair pair = data_inner._pairs[i]; pair.second = MapSourceToTarget(pair.second); if (not pair.second.IsEmpty()) { - pairs.push_back(pair); + if (std::find(pairs.begin(), pairs.end(), pair) == pairs.end()) { + pairs.push_back(pair); + } } } @@ -368,7 +405,9 @@ PcpMapFunction::Compose(const PcpMapFunction &inner) const PathPair pair = data_outer._pairs[i]; pair.first = inner.MapTargetToSource(pair.first); if (not pair.first.IsEmpty()) { - pairs.push_back(pair); + if (std::find(pairs.begin(), pairs.end(), pair) == pairs.end()) { + pairs.push_back(pair); + } } } From 070f3169b5f8749147c710ec40d47c0f92655ad2 Mon Sep 17 00:00:00 2001 From: gitamohr Date: Mon, 17 Oct 2016 13:39:11 -0700 Subject: [PATCH 213/380] sdf: Refactor SdfData time samples implementation so GetBracketingTimeSamplesForPath doesn't have to do any heap allocation. Also some other cleanup. (Internal change: 1661312) --- pxr/usd/lib/sdf/data.cpp | 102 ++++++++++++++++++++++----------------- 1 file changed, 57 insertions(+), 45 deletions(-) diff --git a/pxr/usd/lib/sdf/data.cpp b/pxr/usd/lib/sdf/data.cpp index 712ac4578e..d2710bfdcf 100644 --- a/pxr/usd/lib/sdf/data.cpp +++ b/pxr/usd/lib/sdf/data.cpp @@ -247,7 +247,7 @@ SdfData::ListAllTimeSamples() const TF_FOR_ALL(i, _data) { std::set timesForPath = ListTimeSamplesForPath(SdfAbstractDataSpecId(&i->first)); - times.insert( timesForPath.begin(), timesForPath.end() ); + times.insert(timesForPath.begin(), timesForPath.end()); } return times; @@ -270,54 +270,69 @@ SdfData::ListTimeSamplesForPath(const SdfAbstractDataSpecId& id) const return times; } +template static bool -_GetBracketingTimeSamples(const std::set & samples, - const double time, double* tLower, double* tUpper) +_GetBracketingTimeSamplesImpl( + const Container &samples, const GetTime &getTime, + const double time, double* tLower, double* tUpper) { if (samples.empty()) { // No samples. return false; - } else if (time <= *samples.begin()) { + } else if (time <= getTime(*samples.begin())) { // Time is at-or-before the first sample. - *tLower = *tUpper = *samples.begin(); - } else if (time >= *samples.rbegin()) { + *tLower = *tUpper = getTime(*samples.begin()); + } else if (time >= getTime(*samples.rbegin())) { // Time is at-or-after the last sample. - *tLower = *tUpper = *samples.rbegin(); + *tLower = *tUpper = getTime(*samples.rbegin()); } else { - std::set::const_iterator i = samples.lower_bound(time); - if (*i == time) { + auto iter = samples.lower_bound(time); + if (getTime(*iter) == time) { // Time is exactly on a sample. - *tLower = *tUpper = *i; + *tLower = *tUpper = getTime(*iter); } else { // Time is in-between samples; return the bracketing times. - *tUpper = *i; - --i; - *tLower = *i; + *tUpper = getTime(*iter); + --iter; + *tLower = getTime(*iter); } } return true; } +static bool +_GetBracketingTimeSamples(const std::set &samples, double time, + double *tLower, double *tUpper) +{ + return _GetBracketingTimeSamplesImpl(samples, [](double t) { return t; }, + time, tLower, tUpper); +} + +static bool +_GetBracketingTimeSamples(const SdfTimeSampleMap &samples, double time, + double *tLower, double *tUpper) +{ + return _GetBracketingTimeSamplesImpl( + samples, [](SdfTimeSampleMap::value_type const &p) { return p.first; }, + time, tLower, tUpper); +} + bool SdfData::GetBracketingTimeSamples( double time, double* tLower, double* tUpper) const { - std::set times = ListAllTimeSamples(); - - return _GetBracketingTimeSamples(times, time, tLower, tUpper); + return _GetBracketingTimeSamples( + ListAllTimeSamples(), time, tLower, tUpper); } size_t SdfData::GetNumTimeSamplesForPath(const SdfAbstractDataSpecId& id) const { - if (const VtValue* fieldValue = - _GetFieldValue(id, SdfDataTokens->TimeSamples)) { - - if (fieldValue->IsHolding()) { - return fieldValue->UncheckedGet().size(); + if (const VtValue *fval = _GetFieldValue(id, SdfDataTokens->TimeSamples)) { + if (fval->IsHolding()) { + return fval->UncheckedGet().size(); } } - return 0; } @@ -326,25 +341,25 @@ SdfData::GetBracketingTimeSamplesForPath( const SdfAbstractDataSpecId& id, double time, double* tLower, double* tUpper) const { - std::set times = ListTimeSamplesForPath(id); - return _GetBracketingTimeSamples(times, time, tLower, tUpper); + const VtValue *fval = _GetFieldValue(id, SdfDataTokens->TimeSamples); + if (fval && fval->IsHolding()) { + auto const &tsmap = fval->UncheckedGet(); + return _GetBracketingTimeSamples(tsmap, time, tLower, tUpper); + } + return false; } bool SdfData::QueryTimeSample(const SdfAbstractDataSpecId& id, double time, VtValue *value) const { - // XXX: This could be made more efficient by using _GetFieldValue - // instead of making a full copy of the time sample map. - VtValue sampleMapValue = Get(id, SdfDataTokens->TimeSamples); - if (sampleMapValue.IsHolding()) { - const SdfTimeSampleMap & timeSampleMap = - sampleMapValue.UncheckedGet(); - SdfTimeSampleMap::const_iterator i = timeSampleMap.find(time); - if (i != timeSampleMap.end()) { - if (value) { - *value = i->second; - } + const VtValue *fval = _GetFieldValue(id, SdfDataTokens->TimeSamples); + if (fval && fval->IsHolding()) { + auto const &tsmap = fval->UncheckedGet(); + auto iter = tsmap.find(time); + if (iter != tsmap.end()) { + if (value) + *value = iter->second; return true; } } @@ -354,16 +369,13 @@ SdfData::QueryTimeSample(const SdfAbstractDataSpecId& id, double time, bool SdfData::QueryTimeSample(const SdfAbstractDataSpecId& id, double time, SdfAbstractDataValue* value) const -{ - // XXX: This could be made more efficient by using _GetFieldValue - // instead of making a full copy of the time sample map. - VtValue sampleMapValue = Get(id, SdfDataTokens->TimeSamples); - if (sampleMapValue.IsHolding()) { - const SdfTimeSampleMap & timeSampleMap = - sampleMapValue.UncheckedGet(); - SdfTimeSampleMap::const_iterator i = timeSampleMap.find(time); - if (i != timeSampleMap.end()) { - return not value or value->StoreValue(i->second); +{ + const VtValue *fval = _GetFieldValue(id, SdfDataTokens->TimeSamples); + if (fval && fval->IsHolding()) { + auto const &tsmap = fval->UncheckedGet(); + auto iter = tsmap.find(time); + if (iter != tsmap.end()) { + return not value or value->StoreValue(iter->second); } } return false; From d644b2dfd269d46e6f38b660e06af1020cf04f64 Mon Sep 17 00:00:00 2001 From: superfunc Date: Mon, 17 Oct 2016 13:39:57 -0700 Subject: [PATCH 214/380] [Usdview] Add template clip metadata info. When a prim with these metadata authored is highlighted in the upper left pane, the corresponding values will be populated in the metadata tab in the lower right. (Internal change: 1661318) --- pxr/usdImaging/lib/usdviewq/mainWindow.py | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/pxr/usdImaging/lib/usdviewq/mainWindow.py b/pxr/usdImaging/lib/usdviewq/mainWindow.py index e65873ad36..1be4a2c796 100644 --- a/pxr/usdImaging/lib/usdviewq/mainWindow.py +++ b/pxr/usdImaging/lib/usdviewq/mainWindow.py @@ -3141,15 +3141,24 @@ def _updateMetadataView(self, obj=None): m = obj.GetAllMetadata() # We have to explicitly add in metadata related to composition arcs - # here, since GetAllMetadata prunes them out. + # and value clips here, since GetAllMetadata prunes them out. # # XXX: Would be nice to have some official facility to query # this. - compKeys = ["references", "inheritPaths", "specializes", + compKeys = [# composition related metadata + "references", "inheritPaths", "specializes", "payload", "subLayers", - "clipAssetPaths", "clipTimes", "clipManifestAssetPath", - "clipActive", "clipPrimPath"] + # non-template clip metadata + "clipAssetPaths", "clipTimes", "clipManifestAssetPath", + "clipActive", "clipPrimPath", + + # template clip metadata + "clipTemplateAssetPath", + "clipTemplateStartTime", "clipTemplateEndTime", + "clipTemplateStride"] + + for k in compKeys: v = obj.GetMetadata(k) if not v is None: From ba8f03241ef9e76748cfb66afe8f8ea1ba2bf33d Mon Sep 17 00:00:00 2001 From: superfunc Date: Mon, 17 Oct 2016 13:40:05 -0700 Subject: [PATCH 215/380] [Usd] Change references clipTemplateAssetPath to point to the function containing documentation(GetClipTemplateAssetPath). (Internal change: 1661322) --- pxr/usd/lib/usd/clipsAPI.h | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/pxr/usd/lib/usd/clipsAPI.h b/pxr/usd/lib/usd/clipsAPI.h index 5846145a92..c98dd9c12d 100644 --- a/pxr/usd/lib/usd/clipsAPI.h +++ b/pxr/usd/lib/usd/clipsAPI.h @@ -227,15 +227,14 @@ class UsdClipsAPI : public UsdSchemaBase /// These control the amount of padding USD will supply when looking up /// the assets. For instance, a value of 'foo.###.usd', /// with clipTemplateStartTime=11, clipTemplateEndTime=15, and clipTemplateStride=1: - /// USD will look for: foo.11.usd, foo.12.usd, foo.13.usd, foo.14.usd, foo.15.usd, - /// foo.011.usd, foo.012.usd, foo.013.usd, foo.014.usd and foo.015.usd. + /// USD will look for: foo.011.usd, foo.012.usd, foo.013.usd, foo.014.usd and foo.015.usd. bool GetClipTemplateAssetPath(std::string* clipTemplateAssetPath) const; /// Set the clipTemplateAssetPath metadata for this prim. /// \sa GetClipTemplateAssetPath bool SetClipTemplateAssetPath(const std::string& clipTemplateAssetPath); /// A double representing the increment value USD will use when - /// searching for asset paths. For example usage see clipTemplateAssetPath. + /// searching for asset paths. For example usage \sa GetClipTemplateAssetPath. bool GetClipTemplateStride(double* clipTemplateStride) const; /// Set the clipTemplateStride metadata for this prim /// \sa GetClipTemplateStride() @@ -243,7 +242,7 @@ class UsdClipsAPI : public UsdSchemaBase /// A double which indicates the start of the range USD will use /// to search for asset paths. This value is inclusive in that range. - /// For example usage see clipTemplateAssetPath. + /// For example usage \sa GetClipTemplateAssetPath. bool GetClipTemplateStartTime(double* clipTemplateStartTime) const; /// Set the clipTemplateStartTime metadata for this prim /// \sa GetClipTemplateStartTime @@ -251,7 +250,7 @@ class UsdClipsAPI : public UsdSchemaBase /// A double which indicates the end of the range USD will use to /// to search for asset paths. This value is inclusive in that range. - /// For example usage see clipTemplateAssetPath. + /// For example usage \sa GetClipTemplateAssetPath. bool GetClipTemplateEndTime(double* clipTemplateEndTime) const; /// Set the clipTemplateEndTime metadata for this prim /// \sa GetClipTemplateEndTime() From 1863986fab86e1e367b120d0a1f8e203ad9d3977 Mon Sep 17 00:00:00 2001 From: superfunc Date: Mon, 17 Oct 2016 13:40:45 -0700 Subject: [PATCH 216/380] [Usd] Update clipsAPI docs. (Internal change: 1661328) --- pxr/usd/lib/usd/schema.usda | 3 +-- pxr/usd/lib/usd/tokens.h | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/pxr/usd/lib/usd/schema.usda b/pxr/usd/lib/usd/schema.usda index 257eb027b2..0f91349cdf 100644 --- a/pxr/usd/lib/usd/schema.usda +++ b/pxr/usd/lib/usd/schema.usda @@ -79,8 +79,7 @@ def "GLOBAL" ( These control the amount of padding USD will supply when looking up the assets. For instance, a value of 'foo.###.usd', with clipTemplateStartTime=11, clipTemplateEndTime=15, and clipTemplateStride=1: - USD will look for: foo.11.usd, foo.12.usd, foo.13.usd, foo.14.usd, foo.15.usd, - foo.011.usd, foo.012.usd, foo.013.usd, foo.014.usd and foo.015.usd. + USD will look for: foo.011.usd, foo.012.usd, foo.013.usd, foo.014.usd and foo.015.usd. """ } diff --git a/pxr/usd/lib/usd/tokens.h b/pxr/usd/lib/usd/tokens.h index feb8861168..76b2c90ea2 100644 --- a/pxr/usd/lib/usd/tokens.h +++ b/pxr/usd/lib/usd/tokens.h @@ -71,7 +71,7 @@ /// \li clipAssetPaths - List of asset paths to the clips for this prim. This list is unordered, but elements in this list are referred to by index in other clip-related fields. /// \li clipManifestAssetPath - Asset path for the clip manifest. The clip manifest indicates which attributes have time samples authored in the clips specified on this prim. During value resolution, we will only look for time samples in clips if the attribute exists and is declared as varying in the manifest. Note that the clip manifest is only consulted to check check if an attribute exists and what its variability is. Other values and metadata authored in the manifest will be ignored. For instance, if this prims' path is '/Prim_1', the clip prim path is '/Prim', and we want values for the attribute '/Prim_1.size', we will only look within this prims' clips if the attribute '/Prim.size' exists and is varying in the manifest. /// \li clipPrimPath - Path to the prim in the clips from which time samples will be read. This prim's path will be substituted with this value to determine the final path in the clip from which to read data. For instance, if this prims' path is '/Prim_1', the clip prim path is '/Prim', and we want to get values for the attribute '/Prim_1.size'. The clip prim path will be substituted in, yielding '/Prim.size', and each clip will be examined for values at that path. -/// \li clipTemplateAssetPath - A template string representing a set of assets. This string can be of two forms: path/basename.###.usd and path/basename.##.##.usd. In either case, the number of hash marks in each section is variable. These control the amount of padding USD will supply when looking up the assets. For instance, a value of 'foo.###.usd', with clipTemplateStartTime=11, clipTemplateEndTime=15, and clipTemplateStride=1: USD will look for: foo.11.usd, foo.12.usd, foo.13.usd, foo.14.usd, foo.15.usd, foo.011.usd, foo.012.usd, foo.013.usd, foo.014.usd and foo.015.usd. +/// \li clipTemplateAssetPath - A template string representing a set of assets. This string can be of two forms: path/basename.###.usd and path/basename.##.##.usd. In either case, the number of hash marks in each section is variable. These control the amount of padding USD will supply when looking up the assets. For instance, a value of 'foo.###.usd', with clipTemplateStartTime=11, clipTemplateEndTime=15, and clipTemplateStride=1: USD will look for: foo.011.usd, foo.012.usd, foo.013.usd, foo.014.usd and foo.015.usd. /// \li clipTemplateEndTime - A double which indicates the end of the range USD will use to to search for asset paths. This value is inclusive in that range. For example usage see clipTemplateAssetPath. /// \li clipTemplateStartTime - A double which indicates the start of the range USD will use to search for asset paths. This value is inclusive in that range. For example usage see clipTemplateAssetPath. /// \li clipTemplateStride - A double representing the increment value USD will use when searching for asset paths. For example usage see clipTemplateAssetPath. From f6e43d8ef46ba4a01f6810aff18a4d59f0903067 Mon Sep 17 00:00:00 2001 From: mattyjams Date: Mon, 17 Oct 2016 13:40:55 -0700 Subject: [PATCH 217/380] add support for importing indexed primvars as sparsely authored color sets (Internal change: 1661347) --- .../maya/lib/usdMaya/MayaMeshWriter.cpp | 14 +- third_party/maya/lib/usdMaya/meshUtil.cpp | 18 +- third_party/maya/lib/usdMaya/meshUtil.h | 11 + .../maya/lib/usdMaya/translatorMesh.cpp | 54 ++- third_party/maya/lib/usdMaya/translatorMesh.h | 7 +- .../lib/usdMaya/translatorMesh_PrimVars.cpp | 340 ++++++++++++------ 6 files changed, 277 insertions(+), 167 deletions(-) diff --git a/third_party/maya/lib/usdMaya/MayaMeshWriter.cpp b/third_party/maya/lib/usdMaya/MayaMeshWriter.cpp index 1c74544e52..3a6d67fc21 100644 --- a/third_party/maya/lib/usdMaya/MayaMeshWriter.cpp +++ b/third_party/maya/lib/usdMaya/MayaMeshWriter.cpp @@ -26,20 +26,14 @@ #include "usdMaya/meshUtil.h" #include "pxr/base/gf/vec3f.h" -#include "pxr/base/tf/staticTokens.h" #include "pxr/usd/usdGeom/mesh.h" #include "pxr/usd/usdGeom/pointBased.h" #include "pxr/usd/usdUtils/pipeline.h" #include -#include #include #include - -TF_DEFINE_PRIVATE_TOKENS(_tokens, - ((DisplayColorColorSetName, "displayColor")) - ((DisplayOpacityColorSetName, "displayOpacity")) -); +#include const GfVec2f MayaMeshWriter::_DefaultUV = GfVec2f(-1.0e30); @@ -292,17 +286,17 @@ bool MayaMeshWriter::writeMeshAttrs(const UsdTimeCode &usdTime, UsdGeomMesh &pri bool isDisplayColor = false; - if (colorSetNames[i] == _tokens->DisplayColorColorSetName.GetText()) { + if (colorSetNames[i] == PxrUsdMayaMeshColorSetTokens->DisplayColorColorSetName.GetText()) { if (not getArgs().exportDisplayColor) { continue; } isDisplayColor=true; } - if (colorSetNames[i] == _tokens->DisplayOpacityColorSetName.GetText()) { + if (colorSetNames[i] == PxrUsdMayaMeshColorSetTokens->DisplayOpacityColorSetName.GetText()) { MGlobal::displayWarning("Mesh \"" + lMesh.fullPathName() + "\" has a color set named \"" + - MString(_tokens->DisplayOpacityColorSetName.GetText()) + + MString(PxrUsdMayaMeshColorSetTokens->DisplayOpacityColorSetName.GetText()) + "\" which is a reserved Primvar name in USD. Skipping..."); continue; } diff --git a/third_party/maya/lib/usdMaya/meshUtil.cpp b/third_party/maya/lib/usdMaya/meshUtil.cpp index 0d9b09f264..6958ff1539 100644 --- a/third_party/maya/lib/usdMaya/meshUtil.cpp +++ b/third_party/maya/lib/usdMaya/meshUtil.cpp @@ -23,16 +23,21 @@ // #include "usdMaya/meshUtil.h" +#include "pxr/base/tf/staticTokens.h" +#include "pxr/base/tf/token.h" +#include "pxr/usd/usdGeom/mesh.h" + #include -#include -#include -#include -#include -#include #include +#include #include +#include +#include +#include +#include -#include "pxr/usd/usdGeom/mesh.h" +TF_DEFINE_PUBLIC_TOKENS(PxrUsdMayaMeshColorSetTokens, + PXRUSDMAYA_MESH_COLOR_SET_TOKENS); // These tokens are supported Maya attributes used for Mesh surfaces TF_DEFINE_PRIVATE_TOKENS( @@ -55,6 +60,7 @@ TF_DEFINE_PRIVATE_TOKENS( (USD_faceVaryingInterpolateBoundary) ); + // This can be customized for specific pipeline // We read the USD bool attribute, if not present we look for the mojito bool attribute bool PxrUsdMayaMeshUtil::getEmitNormals(const MFnMesh &mesh) diff --git a/third_party/maya/lib/usdMaya/meshUtil.h b/third_party/maya/lib/usdMaya/meshUtil.h index 49a2ca5584..45e235a0fe 100644 --- a/third_party/maya/lib/usdMaya/meshUtil.h +++ b/third_party/maya/lib/usdMaya/meshUtil.h @@ -27,12 +27,23 @@ #ifndef PXRUSDMAYA_MESH_UTIL_H #define PXRUSDMAYA_MESH_UTIL_H +#include "pxr/base/tf/staticTokens.h" #include "pxr/base/tf/token.h" class MFnMesh; class MString; class UsdGeomMesh; +#define PXRUSDMAYA_MESH_COLOR_SET_TOKENS \ + (Authored) \ + (Clamped) \ + ((DisplayColorColorSetName, "displayColor")) \ + ((DisplayOpacityColorSetName, "displayOpacity")) + +TF_DECLARE_PUBLIC_TOKENS(PxrUsdMayaMeshColorSetTokens, + PXRUSDMAYA_MESH_COLOR_SET_TOKENS); + + namespace PxrUsdMayaMeshUtil { diff --git a/third_party/maya/lib/usdMaya/translatorMesh.cpp b/third_party/maya/lib/usdMaya/translatorMesh.cpp index 68945cfa37..54c5a84e55 100644 --- a/third_party/maya/lib/usdMaya/translatorMesh.cpp +++ b/third_party/maya/lib/usdMaya/translatorMesh.cpp @@ -29,6 +29,7 @@ #include "usdMaya/translatorUtil.h" #include "pxr/usd/usdGeom/mesh.h" +#include "pxr/usd/usdGeom/primvar.h" #include #include @@ -229,26 +230,31 @@ PxrUsdMayaTranslatorMesh::Create( meshFn.fullPathName().asChar()).c_str()); } } - + // GETTING PRIMVARS - std::vector primvars = mesh.GetPrimvars(); + std::vector primvars = mesh.GetPrimvars(); TF_FOR_ALL(iter, primvars) { const UsdGeomPrimvar& primvar = *iter; - TfToken name, interpolation; - SdfValueTypeName typeName; - int elementSize; - primvar.GetDeclarationInfo(&name, &typeName, &interpolation, &elementSize); - + const TfToken& name = primvar.GetBaseName(); + const SdfValueTypeName& typeName = primvar.GetTypeName(); + // If the primvar is called either displayColor or displayOpacity check // if it has the Authored custom data and it's set to true. If not skip since // the primvar was generated by shader values and not an authored colorset/entity // displayColor and displayOpacity are required to provide the Authored custom data - if (name == "displayColor" or name == "displayOpacity") { - if (not PxrUsdMayaUtil::GetBoolCustomData(primvar.GetAttr(), TfToken("Authored"), false)) { + if (name == PxrUsdMayaMeshColorSetTokens->DisplayColorColorSetName or + name == PxrUsdMayaMeshColorSetTokens->DisplayOpacityColorSetName) { + if (not PxrUsdMayaUtil::GetBoolCustomData(primvar.GetAttr(), + PxrUsdMayaMeshColorSetTokens->Authored, + false)) { continue; } } - + + // XXX: Maya stores UVs in MFloatArrays and color set data in MColors + // which store floats, so we currently only import primvars holding + // float-typed arrays. Should we still consider other precisions + // (double, half, ...) and/or numeric types (int)? if (typeName == SdfValueTypeNames->Float2Array) { // We assume that Float2Array primvars are UV sets. if (not _AssignUVSetPrimvarToMesh(primvar, meshFn)) { @@ -257,24 +263,16 @@ PxrUsdMayaTranslatorMesh::Create( name.GetText(), mesh.GetPrim().GetPath().GetText()).c_str()); } - } else if (interpolation == UsdGeomTokens->vertex || - interpolation == UsdGeomTokens->faceVarying || - interpolation == UsdGeomTokens->uniform) { - if (typeName == SdfValueTypeNames->FloatArray) { - if (_AssignColorSetPrimvarToMesh(mesh, primvar, meshFn, polygonCounts, polygonConnects, MFnMesh::kAlpha)==false) { - MGlobal::displayWarning(TfStringPrintf("Unable to retrieve and assign data for Alpha ColorSet <%s> on mesh <%s>", - name.GetText(), mesh.GetPrim().GetPath().GetText()).c_str()); - } - } else if (typeName == SdfValueTypeNames->Color3fArray) { - if (_AssignColorSetPrimvarToMesh(mesh, primvar, meshFn, polygonCounts, polygonConnects, MFnMesh::kRGB)==false) { - MGlobal::displayWarning(TfStringPrintf("Unable to retrieve and assign data for RGB ColorSet <%s> on mesh <%s>", - name.GetText(), mesh.GetPrim().GetPath().GetText()).c_str()); - } - } else if (typeName == SdfValueTypeNames->Float4Array) { - if (_AssignColorSetPrimvarToMesh(mesh, primvar, meshFn, polygonCounts, polygonConnects, MFnMesh::kRGBA)==false) { - MGlobal::displayWarning(TfStringPrintf("Unable to retrieve and assign data for RGBA ColorSet <%s> on mesh <%s>", - name.GetText(), mesh.GetPrim().GetPath().GetText()).c_str()); - } + } else if (typeName == SdfValueTypeNames->FloatArray or + typeName == SdfValueTypeNames->Float3Array or + typeName == SdfValueTypeNames->Color3fArray or + typeName == SdfValueTypeNames->Float4Array or + typeName == SdfValueTypeNames->Color4fArray) { + if (not _AssignColorSetPrimvarToMesh(mesh, primvar, meshFn)) { + MGlobal::displayWarning( + TfStringPrintf("Unable to retrieve and assign data for color set <%s> on mesh <%s>", + name.GetText(), + mesh.GetPrim().GetPath().GetText()).c_str()); } } } diff --git a/third_party/maya/lib/usdMaya/translatorMesh.h b/third_party/maya/lib/usdMaya/translatorMesh.h index d47d19cd41..96a061896f 100644 --- a/third_party/maya/lib/usdMaya/translatorMesh.h +++ b/third_party/maya/lib/usdMaya/translatorMesh.h @@ -34,7 +34,6 @@ #include "pxr/usd/usdGeom/primvar.h" #include -#include #include @@ -61,11 +60,7 @@ struct PxrUsdMayaTranslatorMesh static bool _AssignColorSetPrimvarToMesh( const UsdGeomMesh& primSchema, const UsdGeomPrimvar& primvar, - MFnMesh& meshFn, - MIntArray& polygonCounts, - MIntArray& polygonConnects, - MFnMesh::MColorRepresentation colorRep); - + MFnMesh& meshFn); }; diff --git a/third_party/maya/lib/usdMaya/translatorMesh_PrimVars.cpp b/third_party/maya/lib/usdMaya/translatorMesh_PrimVars.cpp index e83ef2145b..17d7ebc853 100644 --- a/third_party/maya/lib/usdMaya/translatorMesh_PrimVars.cpp +++ b/third_party/maya/lib/usdMaya/translatorMesh_PrimVars.cpp @@ -23,6 +23,7 @@ // #include "usdMaya/translatorMesh.h" +#include "usdMaya/meshUtil.h" #include "usdMaya/util.h" #include "pxr/base/gf/gamma.h" @@ -38,6 +39,7 @@ #include #include #include +#include #include @@ -55,7 +57,7 @@ PxrUsdMayaTranslatorMesh::_AssignUVSetPrimvarToMesh( MGlobal::displayWarning( TfStringPrintf("Could not read UV values from primvar '%s' on mesh: %s", primvarName.GetText(), - meshFn.fullPathName().asChar()).c_str()); + primvar.GetAttr().GetPrimPath().GetText()).c_str()); return false; } @@ -196,130 +198,234 @@ PxrUsdMayaTranslatorMesh::_AssignUVSetPrimvarToMesh( } /* static */ -bool -PxrUsdMayaTranslatorMesh::_AssignColorSetPrimvarToMesh(const UsdGeomMesh &primSchema, const UsdGeomPrimvar &primvar, MFnMesh &meshFn, MIntArray &polygonCounts, MIntArray &polygonConnects, MFnMesh::MColorRepresentation colorRep) +bool +PxrUsdMayaTranslatorMesh::_AssignColorSetPrimvarToMesh( + const UsdGeomMesh& primSchema, + const UsdGeomPrimvar& primvar, + MFnMesh& meshFn) { - TfToken name, interpolation; - SdfValueTypeName typeName; - int elementSize; - primvar.GetDeclarationInfo(&name, &typeName, &interpolation, &elementSize); - - // If the primvar is displayOpacity and is a float array - // Check if displayColor is authored. - // If not, rename displayOpacity to displayColor and create it on the mesh - // This supports cases where the user created a single channel value for displayColor - // XXX for now we are not able to fully recover authored RGBA displayColor - if (name == "displayOpacity" and typeName == SdfValueTypeNames->FloatArray) { - if (not PxrUsdMayaUtil::GetBoolCustomData(primSchema.GetDisplayColorPrimvar(), TfToken("Authored"), false)) { - name = TfToken("displayColor"); + const TfToken& primvarName = primvar.GetBaseName(); + const SdfValueTypeName& typeName = primvar.GetTypeName(); + + MString colorSetName(primvarName.GetText()); + + // If the primvar is displayOpacity and it is a FloatArray, check if + // displayColor is authored. If not, we'll import this 'displayOpacity' + // primvar as a 'displayColor' color set. This supports cases where the + // user created a single channel value for displayColor. + // Note that if BOTH displayColor and displayOpacity are authored, they will + // be imported as separate color sets. We do not attempt to combine them + // into a single color set. + if (primvarName == PxrUsdMayaMeshColorSetTokens->DisplayOpacityColorSetName and + typeName == SdfValueTypeNames->FloatArray) { + if (not PxrUsdMayaUtil::GetBoolCustomData(primSchema.GetDisplayColorPrimvar(), + PxrUsdMayaMeshColorSetTokens->Authored, + false)) { + colorSetName = PxrUsdMayaMeshColorSetTokens->DisplayColorColorSetName.GetText(); + } + } + + // We'll need to convert colors from linear to display if this color set is + // for display colors. + const bool convertToDisplay = + (colorSetName == PxrUsdMayaMeshColorSetTokens->DisplayColorColorSetName.GetText()); + + // Get the raw data before applying any indexing. We'll only populate one + // of these arrays based on the primvar's typeName, and we'll also set the + // color representation so we know which array to use later. + VtFloatArray alphaArray; + VtVec3fArray rgbArray; + VtVec4fArray rgbaArray; + MFnMesh::MColorRepresentation colorRep; + size_t numValues = 0; + + MStatus status = MS::kSuccess; + + if (typeName == SdfValueTypeNames->FloatArray) { + colorRep = MFnMesh::kAlpha; + if (not primvar.Get(&alphaArray) or alphaArray.empty()) { + status = MS::kFailure; } else { - return true; + numValues = alphaArray.size(); } + } else if (typeName == SdfValueTypeNames->Float3Array or + typeName == SdfValueTypeNames->Color3fArray) { + colorRep = MFnMesh::kRGB; + if (not primvar.Get(&rgbArray) or rgbArray.empty()) { + status = MS::kFailure; + } else { + numValues = rgbArray.size(); + } + } else if (typeName == SdfValueTypeNames->Float4Array or + typeName == SdfValueTypeNames->Color4fArray) { + colorRep = MFnMesh::kRGBA; + if (not primvar.Get(&rgbaArray) or rgbaArray.empty()) { + status = MS::kFailure; + } else { + numValues = rgbaArray.size(); + } + } else { + MGlobal::displayWarning( + TfStringPrintf("Unsupported color set primvar type '%s' for primvar '%s' on mesh: %s", + typeName.GetAsToken().GetText(), + primvarName.GetText(), + primvar.GetAttr().GetPrimPath().GetText()).c_str()); + return false; + } + + if (status != MS::kSuccess or numValues == 0) { + MGlobal::displayWarning( + TfStringPrintf("Could not read color set values from primvar '%s' on mesh: %s", + primvarName.GetText(), + primvar.GetAttr().GetPrimPath().GetText()).c_str()); + return false; } - VtValue vtValue; - if (primvar.Get(&vtValue, UsdTimeCode::Default())) { - MColorArray colorArray; + VtIntArray assignmentIndices; + int unauthoredValuesIndex = -1; + if (primvar.GetIndices(&assignmentIndices)) { + // The primvar IS indexed, so the indices array is what determines the + // number of color values. + numValues = assignmentIndices.size(); + unauthoredValuesIndex = primvar.GetUnauthoredValuesIndex(); + } + + // Go through the color data and translate the values into MColors in the + // colorArray, taking into consideration that indexed data may have been + // authored sparsely. If the assignmentIndices array is empty then the data + // is NOT indexed. + // Note that with indexed data, the data is added to the arrays in ascending + // component ID order according to the primvar's interpolation (ascending + // face ID for uniform interpolation, ascending vertex ID for vertex + // interpolation, etc.). This ordering may be different from the way the + // values are ordered in the primvar. Because of this, we recycle the + // assignmentIndices array as we go to store the new mapping from component + // index to color index. + MColorArray colorArray; + for (size_t i = 0; i < numValues; ++i) { + int valueIndex = i; + + if (i < assignmentIndices.size()) { + // The data is indexed, so consult the indices array for the + // correct index into the data. + valueIndex = assignmentIndices[i]; + + if (valueIndex == unauthoredValuesIndex) { + // This component is unauthored, so just update the + // mapping in assignmentIndices and then skip the value. + // We don't actually use the value at the unassigned index. + assignmentIndices[i] = -1; + continue; + } + + // We'll be appending a new value, so the current length of the + // array gives us the new value's index. + assignmentIndices[i] = colorArray.length(); + } + + GfVec4f colorValue(1.0); + switch(colorRep) { - case MFnMesh::kAlpha: { - VtArray floatData; - if (vtValue.IsHolding >() and - primvar.ComputeFlattened(&floatData)) - { - colorArray.setLength( floatData.size() ); - for (unsigned int i=0; i < floatData.size(); i++) { - colorArray.set(i, 1.0, 1.0, 1.0, floatData[i]); - } - } else { - MGlobal::displayWarning(TfStringPrintf("Single channel " - "colorset primvar <%s> doesn't hold an array of float", - name.GetText()).c_str()); - } - } break; - case MFnMesh::kRGB: { - VtArray RGBData; - if (vtValue.IsHolding>() and - primvar.ComputeFlattened(&RGBData)) - { - bool convertToDisplay= (name == "displayColor"); - - colorArray.setLength( RGBData.size() ); - GfVec3f color; - for (unsigned int i=0; i < RGBData.size(); i++) { - if (convertToDisplay) { - color = GfConvertLinearToDisplay(RGBData[i]); - } else { - color = RGBData[i]; - } - colorArray.set(i, color[0], color[1], color[2], 1.0); - } - } else { - MGlobal::displayWarning(TfStringPrintf("RGB colorset primvar <%s> doesn't hold an array of Vec3f", name.GetText()).c_str()); - } - } break; - case MFnMesh::kRGBA: { - VtArray RGBData; - if (vtValue.IsHolding>() and - primvar.ComputeFlattened(&RGBData)) { - - colorArray.setLength( RGBData.size() ); - GfVec4f color; - for (unsigned int i=0; i < RGBData.size(); i++) { - color = GfConvertLinearToDisplay(RGBData[i]); - colorArray.set(i, color[0], color[1], color[2], color[3]); - } - } else { - MGlobal::displayWarning(TfStringPrintf("RGBA colorset primvar <%s> doesn't hold an array of Vec4f", name.GetText()).c_str()); - } - } break; + case MFnMesh::kAlpha: + colorValue[3] = alphaArray[valueIndex]; + break; + case MFnMesh::kRGB: + colorValue[0] = rgbArray[valueIndex][0]; + colorValue[1] = rgbArray[valueIndex][1]; + colorValue[2] = rgbArray[valueIndex][2]; + break; + case MFnMesh::kRGBA: + colorValue[0] = rgbaArray[valueIndex][0]; + colorValue[1] = rgbaArray[valueIndex][1]; + colorValue[2] = rgbaArray[valueIndex][2]; + colorValue[3] = rgbaArray[valueIndex][3]; + break; + default: + break; } - - if (colorArray.length()) { - MString colorSetName(name.GetText()); - // When the Clamped custom data is not present, we assume unclamped colorset - bool clamped = PxrUsdMayaUtil::GetBoolCustomData(primvar.GetAttr(), TfToken("Clamped"), false); - if (interpolation == UsdGeomTokens->uniform && - colorArray.length() == static_cast(meshFn.numPolygons())) { - MIntArray faceIds; - faceIds.setLength( colorArray.length() ); - for (size_t i=0; i < faceIds.length(); i++) { - faceIds.set(i,i); - } - meshFn.createColorSet(colorSetName, NULL, clamped, colorRep); - meshFn.setCurrentColorSetName(colorSetName); - meshFn.setFaceColors(colorArray, faceIds, colorRep); // per-vertex colors - return true; - } - if (interpolation == UsdGeomTokens->vertex && - colorArray.length() == static_cast(meshFn.numVertices())) { - MIntArray vertIds; - vertIds.setLength( colorArray.length() ); - for (size_t i=0; i < vertIds.length(); i++) { - vertIds.set(i,i); - } - meshFn.createColorSet(colorSetName, NULL, clamped, colorRep); - meshFn.setCurrentColorSetName(colorSetName); - meshFn.setVertexColors(colorArray, vertIds, NULL, colorRep); // per-vertex colors - return true; - } - if (interpolation == UsdGeomTokens->faceVarying && - colorArray.length() == static_cast(meshFn.numFaceVertices())) { - MIntArray faceIds; - for (size_t i=0; i < polygonCounts.length(); i++) { - for (int j=0;j(meshFn.numFaceVertices())) { - meshFn.createColorSet(colorSetName, NULL, clamped, colorRep); - meshFn.setCurrentColorSetName(colorSetName); - meshFn.setFaceVertexColors(colorArray, faceIds, polygonConnects, NULL, colorRep); // per-vertex colors - return true; - } + + if (convertToDisplay) { + colorValue = GfConvertLinearToDisplay(colorValue); + } + + MColor mColor(colorValue[0], colorValue[1], colorValue[2], colorValue[3]); + colorArray.append(mColor); + } + + // colorArray now stores all of the values and any unassigned components + // have had their indices set to -1, so update the unauthored values index. + unauthoredValuesIndex = -1; + + // When the Clamped custom data is not present, we assume unclamped. + const bool clamped = + PxrUsdMayaUtil::GetBoolCustomData(primvar.GetAttr(), + PxrUsdMayaMeshColorSetTokens->Clamped, + false); + + status = meshFn.createColorSet(colorSetName, NULL, clamped, colorRep); + if (status != MS::kSuccess) { + MGlobal::displayWarning( + TfStringPrintf("Unable to create color set '%s' for mesh: %s", + colorSetName.asChar(), + meshFn.fullPathName().asChar()).c_str()); + return false; + } + + // Create colors on the mesh from the values we collected out of the + // primvar. We'll assign mesh components to these values below. + status = meshFn.setColors(colorArray, &colorSetName, colorRep); + if (status != MS::kSuccess) { + MGlobal::displayWarning( + TfStringPrintf("Unable to set color data on color set '%s' for mesh: %s", + colorSetName.asChar(), + meshFn.fullPathName().asChar()).c_str()); + return false; + } + + const TfToken& interpolation = primvar.GetInterpolation(); + + // Assigning all of the colors in one shot with MFnMesh::assignColors() is + // MUCH faster than assigning each face vertex individually with + // MFnMesh::assignColor(), so we build an array of value assignments for + // each face vertex in the mesh. Any assignments left as -1 will not be + // assigned a value. + MIntArray colorIds(meshFn.numFaceVertices(), -1); + MItMeshFaceVertex itFV(meshFn.object()); + unsigned int fvi = 0; + for (itFV.reset(); not itFV.isDone(); itFV.next(), ++fvi) { + int colorId = 0; + if (interpolation == UsdGeomTokens->constant) { + colorId = 0; + } else if (interpolation == UsdGeomTokens->uniform) { + colorId = itFV.faceId(); + } else if (interpolation == UsdGeomTokens->vertex) { + colorId = itFV.vertId(); + } else if (interpolation == UsdGeomTokens->faceVarying) { + colorId = fvi; + } + + if (static_cast(colorId) < assignmentIndices.size()) { + // The data is indexed, so consult the indices array for the + // correct index into the data. + colorId = assignmentIndices[colorId]; + + if (colorId == unauthoredValuesIndex) { + // This component had no authored value, so leave it unassigned. + continue; } } - } else { - MGlobal::displayWarning(TfStringPrintf("Unable to get primvar data for colorset <%s>", name.GetText()).c_str()); + + colorIds[fvi] = colorId; } - return false; + + status = meshFn.assignColors(colorIds, &colorSetName); + if (status != MS::kSuccess) { + MGlobal::displayWarning( + TfStringPrintf("Could not assign color values to color set '%s' on mesh: %s", + colorSetName.asChar(), + meshFn.fullPathName().asChar()).c_str()); + return false; + } + + return true; } From c2f9676160e67b087ca60596a346a419be64a497 Mon Sep 17 00:00:00 2001 From: mattyjams Date: Mon, 17 Oct 2016 13:54:39 -0700 Subject: [PATCH 218/380] export user-tagged regular USD attributes into the 'userProperties' namespace when no other USD name is specified (Internal change: 1661469) --- .../lib/usdMaya/userExportedAttributesUI.py | 4 +- third_party/maya/lib/usdMaya/writeUtil.cpp | 42 ++++++++++++------- 2 files changed, 31 insertions(+), 15 deletions(-) diff --git a/third_party/maya/lib/usdMaya/userExportedAttributesUI.py b/third_party/maya/lib/usdMaya/userExportedAttributesUI.py index 8c635dd987..3914715939 100644 --- a/third_party/maya/lib/usdMaya/userExportedAttributesUI.py +++ b/third_party/maya/lib/usdMaya/userExportedAttributesUI.py @@ -287,7 +287,9 @@ def headerData(self, section, orientation, role): COLUMN_TOOLTIPS = [ 'The name of the Maya node attribute to be exported to USD', 'The type of attribute to create in USD', - 'Which name to use for the attribute in USD (defaults to Maya Attribute Name if empty)', + 'Which name to use for the attribute in USD\n' + + '(If empty, the Maya Attribute Name will be used, and for USD-type\n' + + 'attributes, they will be exported into the "userProperties" namespace)', 'Which interpolation to use for primvar-type attributes' ] diff --git a/third_party/maya/lib/usdMaya/writeUtil.cpp b/third_party/maya/lib/usdMaya/writeUtil.cpp index 9806ad3d2c..619a5fc380 100644 --- a/third_party/maya/lib/usdMaya/writeUtil.cpp +++ b/third_party/maya/lib/usdMaya/writeUtil.cpp @@ -76,6 +76,7 @@ TF_DEFINE_PRIVATE_TOKENS( (usdAttrType) ((USDAttrTypePrimvar, "primvar")) ((USDAttrTypeUsdRi, "usdRi")) + ((UserPropertiesNamespace, "userProperties:")) ); @@ -600,7 +601,9 @@ _GetExportAttributeMetadata( // // If the attribute metadata contains a value for "usdAttrName", the attribute // will be given that name in USD. Otherwise, the Maya attribute name will be -// used. Maya attributes in the JSON will be processed in sorted order, and any +// used for primvars and UsdRi attributes, or the Maya attribute name prepended +// with the "userProperties" namespace will be used for regular USD attributes. +// Maya attributes in the JSON will be processed in sorted order, and any // USD attribute name collisions will be resolved by using the first attribute // visited and warning about subsequent attribute tags. // @@ -660,12 +663,35 @@ PxrUsdMayaWriteUtil::WriteUserExportedAttributes( const JsObject& attrMetadata = iter->second.GetJsObject(); + // Check if this is a particular type of attribute (e.g. primvar or + // usdRi attribute). If we don't recognize the type specified, we'll + // fall back to a regular USD attribute. + TfToken usdAttrType( + _GetExportAttributeMetadata(attrMetadata, _tokens->usdAttrType)); + + // Check whether an interpolation type was specified. This is only + // relevant for primvars. + TfToken interpolation( + _GetExportAttributeMetadata(attrMetadata, + UsdGeomTokens->interpolation)); + // Check whether the USD attribute name should be different than the // Maya attribute name. std::string usdAttrName = _GetExportAttributeMetadata(attrMetadata, _tokens->usdAttrName); if (usdAttrName.empty()) { - usdAttrName = mayaAttrName; + if (usdAttrType == _tokens->USDAttrTypePrimvar or + usdAttrType == _tokens->USDAttrTypeUsdRi) { + // Primvars and UsdRi attributes will be given a type-specific + // namespace, so just use the Maya attribute name. + usdAttrName = mayaAttrName; + } else { + // For regular USD attributes, when no name was specified we + // prepend the userProperties namespace to the Maya attribute + // name to get the USD attribute name. + usdAttrName = _tokens->UserPropertiesNamespace.GetString() + + mayaAttrName; + } } const auto& insertIter = exportedUsdAttrNames.insert(usdAttrName); @@ -678,18 +704,6 @@ PxrUsdMayaWriteUtil::WriteUserExportedAttributes( continue; } - // Check if this is a particular type of attribute (e.g. primvar or - // usdRi attribute). If we don't recognize the type specified, we'll - // fall back to a regular USD attribute. - TfToken usdAttrType( - _GetExportAttributeMetadata(attrMetadata, _tokens->usdAttrType)); - - // Check whether an interpolation type was specified. This is only - // relevant for primvars. - TfToken interpolation( - _GetExportAttributeMetadata(attrMetadata, - UsdGeomTokens->interpolation)); - UsdAttribute usdAttr; if (usdAttrType == _tokens->USDAttrTypePrimvar) { From 9e9b1787520398bcf8bf3843301f300f7737980e Mon Sep 17 00:00:00 2001 From: gitamohr Date: Mon, 17 Oct 2016 13:54:49 -0700 Subject: [PATCH 219/380] usd: Locally buffer usdc output in memory. This speeds export times for files that are heavy on recursive dictionaries. In one example, the usdcat time drops by ~64% in wall time, and by 89% in system time. Since we're buffering now we also employ a producer/consumer arrangement so we can avoid blocking for the I/O calls. % time usdcat -o tmp.usdc a517_4_metrics.usd before : 47.03user 52.97system 1:22.96elapsed 120%CPU after : 42.99user 5.94system 0:30.02elapsed 162%CPU (Internal change: 1661477) --- pxr/usd/lib/usd/crateFile.cpp | 201 ++++++++++++++++++++++++++++++---- pxr/usd/lib/usd/crateFile.h | 1 + 2 files changed, 180 insertions(+), 22 deletions(-) diff --git a/pxr/usd/lib/usd/crateFile.cpp b/pxr/usd/lib/usd/crateFile.cpp index e865544c01..54de92be61 100644 --- a/pxr/usd/lib/usd/crateFile.cpp +++ b/pxr/usd/lib/usd/crateFile.cpp @@ -26,6 +26,7 @@ #include "pxr/base/arch/demangle.h" #include "pxr/base/arch/errno.h" #include "pxr/base/arch/fileSystem.h" +#include "pxr/base/arch/nap.h" #include "pxr/base/gf/half.h" #include "pxr/base/gf/matrix2d.h" #include "pxr/base/gf/matrix3d.h" @@ -59,6 +60,7 @@ #include "pxr/base/vt/value.h" #include "pxr/base/work/arenaDispatcher.h" #include "pxr/base/work/dispatcher.h" +#include "pxr/base/work/singularTask.h" #include "pxr/base/work/utils.h" #include "pxr/usd/sdf/assetPath.h" #include "pxr/usd/sdf/layerOffset.h" @@ -71,6 +73,8 @@ #include "pxr/base/tf/registryManager.h" #include "pxr/base/tf/type.h" +#include + #include #include #include @@ -414,15 +418,167 @@ CrateFile::_TableOfContents::GetMinimumSectionStart() const } //////////////////////////////////////////////////////////////////////// -// PackingContext +// _BufferedOutput +class CrateFile::_BufferedOutput +{ +public: + // Current buffer size is 512k. + static const size_t BufferCap = 512*1024; + + // Helper move-only buffer object -- memory + valid size. + struct _Buffer { + _Buffer() = default; + _Buffer(_Buffer const &) = delete; + _Buffer &operator=(_Buffer const &) = delete; + _Buffer(_Buffer &&) = default; + _Buffer &operator=(_Buffer &&) = default; + + unique_ptr bytes { new char[BufferCap] }; + int64_t size = 0; + }; + + explicit _BufferedOutput(FILE *file) + : _filePos(0) + , _file(file) + , _bufferPos(0) + , _writeTask( + _dispatcher, std::bind(&_BufferedOutput::_DoWrites, this)) { + // Create NumBuffers buffers. One is _buffer, the remainder live in + // _freeBuffers. + constexpr const int NumBuffers = 8; + for (int i = 1; i != NumBuffers; ++i) { + _freeBuffers.push(_Buffer()); + } + } + + inline FILE *GetFile() const { return _file; } + + inline void Flush() { + _FlushBuffer(); + _dispatcher.Wait(); + } + + inline void Write(void const *bytes, int64_t nBytes) { + // Write and flush as needed. + while (nBytes) { + int64_t available = BufferCap - (_filePos - _bufferPos); + int64_t numToWrite = std::min(available, nBytes); + + _WriteToBuffer(bytes, numToWrite); + + bytes = static_cast(bytes) + numToWrite; + nBytes -= numToWrite; + + if (numToWrite == available) + _FlushBuffer(); + } + } + + inline int64_t Tell() const { return _filePos; } + + inline void Seek(int64_t offset) { + // If the seek lands in a valid buffer region, then just adjust the + // _filePos. Otherwise _FlushBuffer() and reset. + if (offset >= _bufferPos && offset <= (_bufferPos + _buffer.size)) { + _filePos = offset; + } + else { + _FlushBuffer(); + _bufferPos = _filePos = offset; + } + } + +private: + inline void _FlushBuffer() { + if (_buffer.size) { + // Queue a write of _buffer bytes to the file at _bufferPos. Set + // _bufferPos to be _filePos. + _QueueWrite(std::move(_buffer), _bufferPos); + // Get a new _buffer. May have to wait if all are pending writes. + while (!_freeBuffers.try_pop(_buffer)) + ArchThreadYield(); + } + // Adjust the buffer to start at the write head. + _bufferPos = _filePos; + } + + inline void _WriteToBuffer(void const *bytes, int64_t nBytes) { + // Fill the buffer, update its size and update the write head. Client + // guarantees no overrun. + size_t writeStart = (_filePos - _bufferPos); + if (writeStart + nBytes > _buffer.size) { + _buffer.size = writeStart + nBytes; + } + void *bufPtr = static_cast(_buffer.bytes.get() + writeStart); + memcpy(bufPtr, bytes, nBytes); + _filePos += nBytes; + } + + // Move-only write operation for the writer task to process. + struct _WriteOp { + _WriteOp() = default; + _WriteOp(_WriteOp const &) = delete; + _WriteOp(_WriteOp &&) = default; + _WriteOp &operator=(_WriteOp &&) = default; + _WriteOp(_Buffer &&buf, int64_t pos) : buf(std::move(buf)), pos(pos) {} + _Buffer buf; + int64_t pos = 0; + }; + + inline int64_t _QueueWrite(_Buffer &&buf, int64_t pos) { + // Arrange to write the buffered data. Enqueue the op and wake the + // writer task. + int64_t sz = static_cast(buf.size); + _writeQueue.push(_WriteOp(std::move(buf), pos)); + _writeTask.Wake(); + return sz; + } + + void _DoWrites() { + // This is the writer task. It just pops off ops and writes them, then + // moves the buffer to the free list. + _WriteOp op; + while (_writeQueue.try_pop(op)) { + // Write the bytes. + WriteToFd(_file, op.buf.bytes.get(), op.buf.size, op.pos); + // Add the buffer back to _freeBuffers for reuse. + op.buf.size = 0; + _freeBuffers.push(std::move(op.buf)); + } + } + + // Write head in the file. Always inside the buffer region. + int64_t _filePos; + FILE *_file; + + // Start of current buffer is at this file offset. + int64_t _bufferPos; + _Buffer _buffer; + + // Queue of free buffer objects. + tbb::concurrent_queue<_Buffer> _freeBuffers; + // Queue of pending write operations. + tbb::concurrent_queue<_WriteOp> _writeQueue; + + WorkDispatcher _dispatcher; + WorkSingularTask _writeTask; +}; + +//////////////////////////////////////////////////////////////////////// +// _PackingContext struct CrateFile::_PackingContext { + _PackingContext() = delete; + _PackingContext(_PackingContext const &) = delete; + _PackingContext &operator=(_PackingContext const &) = delete; + _PackingContext(CrateFile *crate, FILE *file, std::string const &fileName) - : file(file) - , fileName(fileName) + : fileName(fileName) , writeVersion(crate->_fileName.empty() ? GetVersionForNewlyCreatedFiles() : - Version(crate->_boot)) { + Version(crate->_boot)) + , bufferedOutput(file) { + // Populate this context with everything we need from \p crate in order // to do deduplication, etc. WorkArenaDispatcher wd; @@ -478,11 +634,12 @@ struct CrateFile::_PackingContext }); // Set file pos to start of the structural sections in the current TOC. - outFilePos = crate->_toc.GetMinimumSectionStart(); - + bufferedOutput.Seek(crate->_toc.GetMinimumSectionStart()); wd.Wait(); } + inline FILE *GetFile() const { return bufferedOutput.GetFile(); } + // Read the bytes of some unknown section into memory so we can rewrite them // out later (to preserve it). unique_ptr @@ -505,13 +662,13 @@ struct CrateFile::_PackingContext // Unknown sections we're moving to the new structural area. vector, size_t>> unknownSections; - // File and filename we're writing to. - FILE *file; + // Filename we're writing to. std::string fileName; // Version we're writing. Version writeVersion; - // Current position in output file. - int64_t outFilePos; + // BufferedOutput helper. + _BufferedOutput bufferedOutput; + }; ///////////////////////////////////////////////////////////////////////// @@ -761,7 +918,8 @@ class CrateFile::_Writer { public: explicit _Writer(CrateFile *crate) - : crate(crate), sink(crate->_packCtx->file) {} + : crate(crate) + , sink(&crate->_packCtx->bufferedOutput) {} // Recursive write helper. We use these when writing values if we may // invoke _PackValue() recursively. Since _PackValue() may or may not write @@ -785,9 +943,9 @@ class CrateFile::_Writer public: - int64_t Tell() const { return crate->_packCtx->outFilePos; } - - void Seek(int64_t offset) { crate->_packCtx->outFilePos = offset; } + int64_t Tell() const { return sink->Tell(); } + void Seek(int64_t offset) { sink->Seek(offset); } + void Flush() { sink->Flush(); } template uint32_t GetInlinedValue(T x) { @@ -817,10 +975,7 @@ class CrateFile::_Writer // Basic Write template typename std::enable_if<_IsBitwiseReadWrite::value>::type - Write(T const &bits) { - crate->_packCtx->outFilePos += WriteToFd( - sink, &bits, sizeof(bits), crate->_packCtx->outFilePos); - } + Write(T const &bits) { sink->Write(&bits, sizeof(bits)); } template void WriteAs(T const &obj) { return Write(static_cast(obj)); } @@ -905,8 +1060,7 @@ class CrateFile::_Writer template typename std::enable_if<_IsBitwiseReadWrite::value>::type WriteContiguous(T const *values, size_t sz) { - crate->_packCtx->outFilePos += WriteToFd( - sink, values, sizeof(*values) * sz, crate->_packCtx->outFilePos); + sink->Write(values, sizeof(*values) * sz); } template @@ -916,7 +1070,7 @@ class CrateFile::_Writer } CrateFile *crate; - FILE *sink; + _BufferedOutput *sink; }; @@ -1241,7 +1395,7 @@ CrateFile::Packer::Close() if (not TF_VERIFY(_crate)) return false; - if (FILE *fp = _crate->_packCtx->file) { + if (FILE *fp = _crate->_packCtx->GetFile()) { // Write contents. bool writeResult = _crate->_Write(); @@ -1431,6 +1585,9 @@ CrateFile::_Write() w.Seek(0); w.Write(boot); + // Flush any buffered writes. + w.Flush(); + _toc = toc; _boot = boot; diff --git a/pxr/usd/lib/usd/crateFile.h b/pxr/usd/lib/usd/crateFile.h index 60f7bb8acd..c62adf48c1 100644 --- a/pxr/usd/lib/usd/crateFile.h +++ b/pxr/usd/lib/usd/crateFile.h @@ -526,6 +526,7 @@ class CrateFile static ArchConstFileMapping _MmapFile(char const *fileName, FILE *file); class _Writer; + class _BufferedOutput; class _ReaderBase; template class _Reader; From fb77ee61c5de8249d7454580af2f87dd1d2d7682 Mon Sep 17 00:00:00 2001 From: gitamohr Date: Mon, 17 Oct 2016 13:56:28 -0700 Subject: [PATCH 220/380] usd: crateData perf tweaks - avoid heap allocating empty spec data in a serial section upfront only to replace it later. Also we can access elements from the flat map directly instead of calling at() since we're walking in sorted order. This avoids a binary search for each element. (Internal change: 1661479) --- pxr/usd/lib/usd/crateData.cpp | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/pxr/usd/lib/usd/crateData.cpp b/pxr/usd/lib/usd/crateData.cpp index 0610c7b4db..9f28bae9ed 100644 --- a/pxr/usd/lib/usd/crateData.cpp +++ b/pxr/usd/lib/usd/crateData.cpp @@ -646,8 +646,8 @@ class Usd_CrateDataImpl using result_type = _FlatMap::value_type; explicit _SpecToPair(CrateFile *crateFile) : crateFile(crateFile) {} result_type operator()(CrateFile::Spec const &spec) const { - result_type r; - r.first = crateFile->GetPath(spec.pathIndex); + result_type r(crateFile->GetPath(spec.pathIndex), + _FlatSpecData(Usd_EmptySharedTag)); TF_AXIOM(!r.first.IsTargetPath()); return r; } @@ -675,9 +675,7 @@ class Usd_CrateDataImpl TfAutoMallocTag tag2("Usd_CrateDataImpl main hash table"); specDataPtrs.resize(specs.size()); for (size_t i = 0; i != specs.size(); ++i) { - auto const &s = specs[i]; - specDataPtrs[i] = - &_flatData.at(_crateFile->GetPath(s.pathIndex)); + specDataPtrs[i] = &(_flatData.begin()[i].second); } }); @@ -908,6 +906,9 @@ class Usd_CrateDataImpl struct _FlatSpecData { inline void DetachIfNotUnique() { fields.MakeUnique(); } + _FlatSpecData() = default; + explicit _FlatSpecData(Usd_EmptySharedTagType) + : fields(Usd_EmptySharedTag) {} Usd_Shared<_FieldValuePairVector> fields; }; From 298397550d0143ccc122a37e7a403f577e785803 Mon Sep 17 00:00:00 2001 From: gitamohr Date: Mon, 17 Oct 2016 13:56:44 -0700 Subject: [PATCH 221/380] work: Refactor WorkSingularTask so it can work with both WorkDispatcher and WorkArenaDispatcher. (Internal change: 1661584) --- pxr/base/lib/work/singularTask.cpp | 30 --------------- pxr/base/lib/work/singularTask.h | 62 +++++++++++++++++++++++++----- 2 files changed, 53 insertions(+), 39 deletions(-) diff --git a/pxr/base/lib/work/singularTask.cpp b/pxr/base/lib/work/singularTask.cpp index 5fa448818f..c5f0f1821f 100644 --- a/pxr/base/lib/work/singularTask.cpp +++ b/pxr/base/lib/work/singularTask.cpp @@ -22,33 +22,3 @@ // language governing permissions and limitations under the Apache License. // #include "pxr/base/work/singularTask.h" - -#include "pxr/base/work/dispatcher.h" - -struct WorkSingularTask::_Invoker -{ - explicit _Invoker(WorkSingularTask *task) : _task(task) {} - - void operator()() const { - // We read the current refCount into oldCount, then we invoke the task - // function. Finally we try to CAS the refCount to zero. If we fail, - // it means some other clients have invoked Wake() in the meantime. In - // that case we start over to ensure the task can do whatever it was - // awakened to do. Once we successfully take the count to zero, we - // stop. - size_t oldCount = _task->_refCount; - do { - _task->_fn(); - } while (not _task->_refCount.compare_exchange_strong(oldCount, 0)); - } - -private: - WorkSingularTask *_task; -}; - -void -WorkSingularTask::Wake() -{ - if (++_refCount == 1) - _dispatcher.Run(_Invoker(this)); -} diff --git a/pxr/base/lib/work/singularTask.h b/pxr/base/lib/work/singularTask.h index b3d5ceca38..176825a563 100644 --- a/pxr/base/lib/work/singularTask.h +++ b/pxr/base/lib/work/singularTask.h @@ -28,8 +28,10 @@ #include #include +#include class WorkDispatcher; +class WorkArenaDispatcher; /// \class WorkSingularTask /// @@ -69,28 +71,70 @@ class WorkSingularTask WorkSingularTask(WorkDispatcher &dispatcher, Callable &&c, A1 &&a1, A2 &&a2, ... AN &&aN); + /// \overload + template + WorkSingularTask(WorkArenaDispatcher &dispatcher, + Callable &&c, A1 &&a1, A2 &&a2, ... AN &&aN); + #else // doxygen template WorkSingularTask(WorkDispatcher &d, Callable &&c, Args&&... args) - : _dispatcher(d) - , _fn(std::bind(std::forward(c), - std::forward(args)...)) - , _refCount(0) {} + : _waker(_MakeWaker(d, std::bind(std::forward(c), + std::forward(args)...))) + , _count(0) {} + + template + WorkSingularTask(WorkArenaDispatcher &d, Callable &&c, Args&&... args) + : _waker(_MakeWaker(d, std::bind(std::forward(c), + std::forward(args)...))) + , _count(0) {} #endif // doxygen /// Ensure that this task runs at least once after this call. The task is /// not guaranteed to run as many times as Wake() is invoked, only that it /// run at least once after a call to Wake(). - void Wake(); + inline void Wake() { + if (++_count == 1) + _waker(_count); + } private: - struct _Invoker; + template + struct _Waker { + explicit _Waker(Dispatcher &d, Fn &&fn) + : _dispatcher(d), _fn(std::move(fn)) {} + + void operator()(std::atomic_size_t &count) const { + _dispatcher.Run( + [this, &count]() { + // We read the current refCount into oldCount, then we + // invoke the task function. Finally we try to CAS the + // refCount to zero. If we fail, it means some other + // clients have invoked Wake() in the meantime. In that + // case we go again to ensure the task can do whatever it + // was awakened to do. Once we successfully take the count + // to zero, we stop. + size_t old = count; + do { _fn(); } while ( + !count.compare_exchange_strong(old, 0)); + }); + } + Dispatcher &_dispatcher; + Fn _fn; + }; + + template + static std::function + _MakeWaker(Dispatcher &d, Fn &&fn) { + return std::function( + _Waker::type>( + d, std::forward(fn))); + } - WorkDispatcher &_dispatcher; - std::function _fn; - std::atomic_size_t _refCount; + std::function _waker; + std::atomic_size_t _count; }; #endif // WORK_SINGULARTASK_H From ec18f52487629d22b1a83eff6b779fcefa05652f Mon Sep 17 00:00:00 2001 From: gitamohr Date: Mon, 17 Oct 2016 13:58:23 -0700 Subject: [PATCH 222/380] usd: Use WorkArenaDispatcher in CrateFile::_BufferedOutput. (Internal change: 1661585) --- pxr/usd/lib/usd/crateFile.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/pxr/usd/lib/usd/crateFile.cpp b/pxr/usd/lib/usd/crateFile.cpp index 54de92be61..583d1dd92a 100644 --- a/pxr/usd/lib/usd/crateFile.cpp +++ b/pxr/usd/lib/usd/crateFile.cpp @@ -59,7 +59,6 @@ #include "pxr/base/vt/dictionary.h" #include "pxr/base/vt/value.h" #include "pxr/base/work/arenaDispatcher.h" -#include "pxr/base/work/dispatcher.h" #include "pxr/base/work/singularTask.h" #include "pxr/base/work/utils.h" #include "pxr/usd/sdf/assetPath.h" @@ -560,7 +559,7 @@ class CrateFile::_BufferedOutput // Queue of pending write operations. tbb::concurrent_queue<_WriteOp> _writeQueue; - WorkDispatcher _dispatcher; + WorkArenaDispatcher _dispatcher; WorkSingularTask _writeTask; }; From 473cc64eba487048dc146ec86392dfedea5432d7 Mon Sep 17 00:00:00 2001 From: mattyjams Date: Mon, 17 Oct 2016 13:58:30 -0700 Subject: [PATCH 223/380] optimize UV set importing by assigning all UVs at once This change applies a similar optimization already being used for importing color sets to importing UVs as well. We use Maya's assignUVs() method to batch assign all UVs on the mesh at once rather than using assignUV() to assign them individually, as that seems to incur some kind of expensive copy operation inside Maya. Doing that, we can also generalize a helper method for building the MIntArray that stores these assignments before calling the UV set or color set specific API. (Internal change: 1661833) --- .../lib/usdMaya/translatorMesh_PrimVars.cpp | 141 +++++++++--------- 1 file changed, 70 insertions(+), 71 deletions(-) diff --git a/third_party/maya/lib/usdMaya/translatorMesh_PrimVars.cpp b/third_party/maya/lib/usdMaya/translatorMesh_PrimVars.cpp index 17d7ebc853..bad3893670 100644 --- a/third_party/maya/lib/usdMaya/translatorMesh_PrimVars.cpp +++ b/third_party/maya/lib/usdMaya/translatorMesh_PrimVars.cpp @@ -43,6 +43,47 @@ #include +static +MIntArray +_GetMayaFaceVertexAssignmentIds( + const MFnMesh& meshFn, + const TfToken& interpolation, + const VtIntArray& assignmentIndices, + const int unauthoredValuesIndex) +{ + MIntArray valueIds(meshFn.numFaceVertices(), -1); + + MItMeshFaceVertex itFV(meshFn.object()); + unsigned int fvi = 0; + for (itFV.reset(); not itFV.isDone(); itFV.next(), ++fvi) { + int valueId = 0; + if (interpolation == UsdGeomTokens->constant) { + valueId = 0; + } else if (interpolation == UsdGeomTokens->uniform) { + valueId = itFV.faceId(); + } else if (interpolation == UsdGeomTokens->vertex) { + valueId = itFV.vertId(); + } else if (interpolation == UsdGeomTokens->faceVarying) { + valueId = fvi; + } + + if (static_cast(valueId) < assignmentIndices.size()) { + // The data is indexed, so consult the indices array for the + // correct index into the data. + valueId = assignmentIndices[valueId]; + + if (valueId == unauthoredValuesIndex) { + // This component had no authored value, so leave it unassigned. + continue; + } + } + + valueIds[fvi] = valueId; + } + + return valueIds; +} + /* static */ bool PxrUsdMayaTranslatorMesh::_AssignUVSetPrimvarToMesh( @@ -152,46 +193,31 @@ PxrUsdMayaTranslatorMesh::_AssignUVSetPrimvarToMesh( const TfToken& interpolation = primvar.GetInterpolation(); - // Iterate through the mesh's face vertices assigning UV values to them. - MItMeshFaceVertex itFV(meshFn.object()); - unsigned int fvi = 0; - for (itFV.reset(); not itFV.isDone(); itFV.next(), ++fvi) { - int faceId = itFV.faceId(); - int vertexId = itFV.vertId(); - int faceVertexId = itFV.faceVertId(); - - // Primvars with constant or uniform interpolation are not really - // meaningful as UV sets, but we support them anyway. - int uvId = 0; - if (interpolation == UsdGeomTokens->constant) { - uvId = 0; - } else if (interpolation == UsdGeomTokens->uniform) { - uvId = faceId; - } else if (interpolation == UsdGeomTokens->vertex) { - uvId = vertexId; - } else if (interpolation == UsdGeomTokens->faceVarying) { - uvId = fvi; - } - - if (static_cast(uvId) < assignmentIndices.size()) { - // The data is indexed, so consult the indices array for the - // correct index into the data. - uvId = assignmentIndices[uvId]; + // Build an array of value assignments for each face vertex in the mesh. + // Any assignments left as -1 will not be assigned a value. + MIntArray uvIds = _GetMayaFaceVertexAssignmentIds(meshFn, + interpolation, + assignmentIndices, + unauthoredValuesIndex); - if (uvId == unauthoredValuesIndex) { - // This component had no authored value, so skip it. - continue; - } - } + MIntArray vertexCounts; + MIntArray vertexList; + status = meshFn.getVertices(vertexCounts, vertexList); + if (status != MS::kSuccess) { + MGlobal::displayWarning( + TfStringPrintf("Could not get vertex counts for UV set '%s' on mesh: %s", + uvSetName.asChar(), + meshFn.fullPathName().asChar()).c_str()); + return false; + } - status = meshFn.assignUV(faceId, faceVertexId, uvId, &uvSetName); - if (status != MS::kSuccess) { - MGlobal::displayWarning( - TfStringPrintf("Could not assign UV value to UV set '%s' on mesh: %s", - uvSetName.asChar(), - meshFn.fullPathName().asChar()).c_str()); - return false; - } + status = meshFn.assignUVs(vertexCounts, uvIds, &uvSetName); + if (status != MS::kSuccess) { + MGlobal::displayWarning( + TfStringPrintf("Could not assign UV values to UV set '%s' on mesh: %s", + uvSetName.asChar(), + meshFn.fullPathName().asChar()).c_str()); + return false; } return true; @@ -384,39 +410,12 @@ PxrUsdMayaTranslatorMesh::_AssignColorSetPrimvarToMesh( const TfToken& interpolation = primvar.GetInterpolation(); - // Assigning all of the colors in one shot with MFnMesh::assignColors() is - // MUCH faster than assigning each face vertex individually with - // MFnMesh::assignColor(), so we build an array of value assignments for - // each face vertex in the mesh. Any assignments left as -1 will not be - // assigned a value. - MIntArray colorIds(meshFn.numFaceVertices(), -1); - MItMeshFaceVertex itFV(meshFn.object()); - unsigned int fvi = 0; - for (itFV.reset(); not itFV.isDone(); itFV.next(), ++fvi) { - int colorId = 0; - if (interpolation == UsdGeomTokens->constant) { - colorId = 0; - } else if (interpolation == UsdGeomTokens->uniform) { - colorId = itFV.faceId(); - } else if (interpolation == UsdGeomTokens->vertex) { - colorId = itFV.vertId(); - } else if (interpolation == UsdGeomTokens->faceVarying) { - colorId = fvi; - } - - if (static_cast(colorId) < assignmentIndices.size()) { - // The data is indexed, so consult the indices array for the - // correct index into the data. - colorId = assignmentIndices[colorId]; - - if (colorId == unauthoredValuesIndex) { - // This component had no authored value, so leave it unassigned. - continue; - } - } - - colorIds[fvi] = colorId; - } + // Build an array of value assignments for each face vertex in the mesh. + // Any assignments left as -1 will not be assigned a value. + MIntArray colorIds = _GetMayaFaceVertexAssignmentIds(meshFn, + interpolation, + assignmentIndices, + unauthoredValuesIndex); status = meshFn.assignColors(colorIds, &colorSetName); if (status != MS::kSuccess) { From 37d35fb4875153a24a1338e868295a8b12adfd84 Mon Sep 17 00:00:00 2001 From: mrawde Date: Mon, 17 Oct 2016 13:58:42 -0700 Subject: [PATCH 224/380] Update script to take a flag that specifies if the shadingVariant layer should be referenced or not. (Internal change: 1661866) --- .../tutorials/endToEnd/assets/Table/Table.usd | 6 +----- .../endToEnd/scripts/create_asset.py | 21 ++++++++++++------- 2 files changed, 15 insertions(+), 12 deletions(-) diff --git a/extras/usd/tutorials/endToEnd/assets/Table/Table.usd b/extras/usd/tutorials/endToEnd/assets/Table/Table.usd index 7849aebf9e..796a57ddf0 100644 --- a/extras/usd/tutorials/endToEnd/assets/Table/Table.usd +++ b/extras/usd/tutorials/endToEnd/assets/Table/Table.usd @@ -10,12 +10,8 @@ def Xform "Table" ( string name = "Table" } kind = "component" - add references = [ - @./Table.shadingVariants.usda@, - @./Table.maya.usd@ - ] + add references = @./Table.maya.usd@ ) { } - diff --git a/extras/usd/tutorials/endToEnd/scripts/create_asset.py b/extras/usd/tutorials/endToEnd/scripts/create_asset.py index 4a3e8ec1b4..47414df37b 100644 --- a/extras/usd/tutorials/endToEnd/scripts/create_asset.py +++ b/extras/usd/tutorials/endToEnd/scripts/create_asset.py @@ -41,6 +41,9 @@ def main(): help="sets asset's model kind") parser.add_option('-o', '--outputDir', help='directory to create assets. if none specified, will use modelName.') + parser.add_option('-s', '--shadingVariantLayer', + help='add .shadingVariants.usda to model references.', default=False, + action='store_true') parser.add_option('-f', '--force', default=False, action='store_true', help='if False, this will error if [outputDir] exists') options, args = parser.parse_args() @@ -61,9 +64,9 @@ def main(): else: os.makedirs(outputDir) - _CreateAsset(asset, outputDir, options.kind) + _CreateAsset(asset, outputDir, options.kind, options.shadingVariantLayer) -def _CreateAsset(assetName, assetDir, assetKind): +def _CreateAsset(assetName, assetDir, assetKind, addShadingVariantLayer): assetFilePath = os.path.join(assetDir, '%s.usd' % assetName) print "Creating asset at %s" % assetFilePath @@ -87,11 +90,15 @@ def _CreateAsset(assetName, assetDir, assetKind): model.SetAssetName(assetName) model.SetAssetIdentifier('%s/%s.usd' % (assetName, assetName)) - # shading is stronger than geom - _CreateAndReferenceLayers(assetPrim, assetDir, [ - './%s.shadingVariants.usda' % assetName, - './%s.maya.usd' % assetName, - ]) + refs = [] + if addShadingVariantLayer: + # if we're going to add it, then shading is stronger than geom and needs + # to be added first + refs.append('./%s.shadingVariants.usda' % assetName) + + refs.append('./%s.maya.usd' % assetName) + + _CreateAndReferenceLayers(assetPrim, assetDir, refs) assetStage.GetRootLayer().Save() From 8a48a75503149d4d07a57581f35b86a5a592ac48 Mon Sep 17 00:00:00 2001 From: superfunc Date: Mon, 17 Oct 2016 13:59:36 -0700 Subject: [PATCH 225/380] [UsdUtils] Remove iterative behavior in stitchclips utility code. (Internal change: 1661901) --- pxr/usd/bin/usdstitchclips/usdstitchclips.py | 13 +-- pxr/usd/lib/usdUtils/stitchClips.cpp | 103 +++++++++---------- pxr/usd/lib/usdUtils/stitchClips.h | 15 +-- pxr/usd/lib/usdUtils/wrapStitchClips.cpp | 3 - 4 files changed, 58 insertions(+), 76 deletions(-) diff --git a/pxr/usd/bin/usdstitchclips/usdstitchclips.py b/pxr/usd/bin/usdstitchclips/usdstitchclips.py index 29fa45156d..6b56a6ec37 100644 --- a/pxr/usd/bin/usdstitchclips/usdstitchclips.py +++ b/pxr/usd/bin/usdstitchclips/usdstitchclips.py @@ -45,11 +45,6 @@ help='specify a start time') parser.add_argument('-e', '--endTimeCode', action='store', help='specify an end time') -parser.add_argument('-r', '--reuseExistingTopology', - action='store_true', - help='Pre-existing topology layer named ' - 'ROOTLAYER.topology.usd will be reused if ' - 'it exists.') # useful for debugging with diffs parser.add_argument('-n', '--noComment', action='store_true', help='''do not write a comment specifying how the @@ -64,9 +59,10 @@ if os.path.isfile(results.out): print "Warning: merging with current result layer" +outLayerGenerated = False + try: outLayer = Sdf.Layer.FindOrOpen(results.out) - outLayerGenerated = False if not outLayer: outLayerGenerated = True outLayer = Sdf.Layer.CreateNew(results.out) @@ -78,8 +74,7 @@ results.endTimeCode = float(results.endTimeCode) UsdUtils.StitchClips(outLayer, results.usdFiles, results.clipPath, - results.reuseExistingTopology, results.startTimeCode, - results.endTimeCode) + results.startTimeCode, results.endTimeCode) if not results.noComment: outLayer.comment = 'Generated with ' + ' '.join(sys.argv) @@ -87,6 +82,6 @@ except Tf.ErrorException as e: # if something in the authoring fails, remove the output file - if outLayerGenerated: + if outLayerGenerated and os.path.isfile(results.out): os.remove(results.out) sys.exit(e) diff --git a/pxr/usd/lib/usdUtils/stitchClips.cpp b/pxr/usd/lib/usdUtils/stitchClips.cpp index 3fccff333f..72da11ba4b 100644 --- a/pxr/usd/lib/usdUtils/stitchClips.cpp +++ b/pxr/usd/lib/usdUtils/stitchClips.cpp @@ -24,7 +24,6 @@ #include "pxr/usd/usdUtils/stitchClips.h" #include "pxr/usd/usdUtils/stitch.h" -#include "pxr/base/vt/value.h" #include "pxr/usd/sdf/path.h" #include "pxr/usd/sdf/layer.h" #include "pxr/usd/sdf/spec.h" @@ -41,6 +40,8 @@ #include "pxr/base/tf/pyLock.h" #include "pxr/base/tf/fileUtils.h" #include "pxr/base/tf/nullPtr.h" +#include "pxr/base/arch/fileSystem.h" +#include "pxr/base/vt/value.h" #include "pxr/base/gf/vec2d.h" #include "pxr/base/work/loops.h" @@ -572,37 +573,6 @@ namespace { delimiter+topologyFileBaseName); } - std::tuple - _CreateTopologyLayer(const SdfLayerHandle& resultLayer, - const bool reuseExistingTopology) - { - const auto topologyName - = _CreateTopologyName(resultLayer->GetIdentifier()); - - bool topologyWasGenerated = false; - - SdfLayerRefPtr topologyLayer = SdfLayer::FindOrOpen(topologyName); - - if (not _LayerIsWritable(topologyLayer)) { - return std::make_tuple(TfNullPtr, topologyWasGenerated); - } - - if (not reuseExistingTopology) { - topologyWasGenerated = true; - if (topologyLayer) { - topologyLayer->Clear(); - } else { - topologyLayer = SdfLayer::CreateNew(topologyName); - } - - } else if (not topologyLayer) { - topologyWasGenerated = true; - topologyLayer = SdfLayer::CreateNew(topologyName); - } - - return std::make_tuple(topologyLayer, topologyWasGenerated); - } - struct _StitchLayersResult { SdfPath clipPath; SdfLayerRefPtr topology; @@ -710,12 +680,14 @@ namespace { _UsdUtilsStitchClipsTopologyImpl(const SdfLayerRefPtr& topologyLayer, const SdfLayerRefPtrVector& clipLayers) { + TfErrorMark errorMark; + // Note that we don't specify a unique clipPath since we're only // interested in aggregating topology. auto result = _AggregateDataFromClips(topologyLayer, clipLayers); UsdUtilsStitchLayers(topologyLayer, result.topology, true); - topologyLayer->Save(); - return true; + + return errorMark.IsClean(); } bool @@ -726,13 +698,12 @@ namespace { const double startTimeCode, const double endTimeCode) { + TfErrorMark errorMark; + _StitchLayers(resultLayer, topologyLayer, clipLayers, clipPath); _SetTimeCodeRange(resultLayer, clipPath, startTimeCode, endTimeCode); - topologyLayer->Save(); - resultLayer->Save(); - - return true; + return errorMark.IsClean(); } bool @@ -769,6 +740,8 @@ namespace { const _ClipFileVector& clipLayerFiles, const SdfPath& clipPath) { + TfErrorMark errorMark; + // Pre-allocate our destination vector for the clip layer handles clipLayers->resize(clipLayerFiles.size()); @@ -781,7 +754,8 @@ namespace { } }); - return _ClipLayersAreValid(*clipLayers, clipLayerFiles, clipPath); + return errorMark.IsClean() + && _ClipLayersAreValid(*clipLayers, clipLayerFiles, clipPath); } } @@ -797,54 +771,79 @@ UsdUtilsStitchClipsTopology(const SdfLayerHandle& topologyLayer, // will need to acquire the GIL, we need to explicitly release it. TF_PY_ALLOW_THREADS_IN_SCOPE(); - if (not _LayerIsWritable(topologyLayer)) { + // Prepare topology layer for editing + if (!_LayerIsWritable(topologyLayer)) { return false; + } else { + topologyLayer->Clear(); } + // Open all clip layers and validate clipPath SdfLayerRefPtrVector clipLayers; const bool clipLayersAreValid = _OpenClipLayers(&clipLayers, clipLayerFiles, SdfPath::AbsoluteRootPath()); - if (not clipLayersAreValid) { + if (!clipLayersAreValid + || !_UsdUtilsStitchClipsTopologyImpl(topologyLayer, clipLayers)) { return false; } - return _UsdUtilsStitchClipsTopologyImpl(topologyLayer, clipLayers); + topologyLayer->Save(); + + return true; } bool UsdUtilsStitchClips(const SdfLayerHandle& resultLayer, const _ClipFileVector& clipLayerFiles, const SdfPath& clipPath, - const bool reuseExistingTopology, const double startTimeCode, const double endTimeCode) { // XXX: See comment in UsdUtilsStitchClipsTopology above. TF_PY_ALLOW_THREADS_IN_SCOPE(); - if (not _LayerIsWritable(resultLayer)) { + // Prepare result layer for editing + if (!_LayerIsWritable(resultLayer)) { return false; + } else { + resultLayer->Clear(); } - SdfLayerRefPtr topologyLayer; - bool topologyWasGenerated; + // Prepare topology layer for editing, create if necessary + bool topologyPreExisting = true; + std::string topologyLayerId + = _CreateTopologyName(resultLayer->GetIdentifier()); + SdfLayerRefPtr topologyLayer = SdfLayer::FindOrOpen(topologyLayerId); + if (!topologyLayer) { + topologyPreExisting = false; + topologyLayer = SdfLayer::CreateNew(topologyLayerId); + } - std::tie(topologyLayer, topologyWasGenerated) - = _CreateTopologyLayer(resultLayer, reuseExistingTopology); + if (!_LayerIsWritable(topologyLayer)) { + return false; + } else { + topologyLayer->Clear(); + } + // Open all clip layers and validate clipPath SdfLayerRefPtrVector clipLayers; const bool clipLayersAreValid = _OpenClipLayers(&clipLayers, clipLayerFiles, clipPath); - if (not clipLayersAreValid) { - if (topologyWasGenerated) { + if (!clipLayersAreValid + || !_UsdUtilsStitchClipsImpl(resultLayer, topologyLayer, clipLayers, + clipPath, startTimeCode, endTimeCode)) { + if (!topologyPreExisting) { TfDeleteFile(topologyLayer->GetIdentifier()); } return false; } - return _UsdUtilsStitchClipsImpl(resultLayer, topologyLayer, clipLayers, - clipPath, startTimeCode, endTimeCode); + // Note that we don't apply edits until all other + // actions have completed. + topologyLayer->Save(); + resultLayer->Save(); + return true; } diff --git a/pxr/usd/lib/usdUtils/stitchClips.h b/pxr/usd/lib/usdUtils/stitchClips.h index 1a8e2276b6..8adbbb06e5 100644 --- a/pxr/usd/lib/usdUtils/stitchClips.h +++ b/pxr/usd/lib/usdUtils/stitchClips.h @@ -51,9 +51,6 @@ SDF_DECLARE_HANDLES(SdfLayer); /// /// \p clipPath The path at which we will put the clip meta data. /// -/// \p reuseExistingTopology Whether or not we will attempt to reuse an -/// existing topology file. -/// /// \p startTimeCode The first time coordinate for the rootLayer /// to point to. If none is provided, it will be /// the lowest startTimeCode available from @@ -67,11 +64,9 @@ SDF_DECLARE_HANDLES(SdfLayer); /// /// Details on how this is accomplished can be found below: /// -/// This will begin by generating a topology layer, if necessary. -/// If the user has marked \p reuseExistingTopology as true, and a layer -/// exists, it will be reused. Otherwise, a fresh one will be generated. -/// In either case, topology layers will be named/looked up -/// via the following scheme: +/// Pre-existing opinions will be wiped away upon success. Upon failure, the +/// original topology layer, if it was pre-existing, will be preserved. +/// Topology layers will be named/looked up via the following scheme: /// /// topologyLayerName = .topology. /// @@ -100,14 +95,10 @@ SDF_DECLARE_HANDLES(SdfLayer); /// Note: an invalid clip path(because the prim doesn't exist in /// the aggregate topologyLayer) will result in a TF_CODING_ERROR. /// -/// Note: if this function fails, the root layer will be not be created. -/// If the topology is not being reused, it will not be generated either. bool UsdUtilsStitchClips(const SdfLayerHandle& resultLayer, const std::vector& clipLayerFiles, const SdfPath& clipPath, - const bool reuseExistingTopology - = true, const double startTimeCode = std::numeric_limits::max(), const double endTimeCode diff --git a/pxr/usd/lib/usdUtils/wrapStitchClips.cpp b/pxr/usd/lib/usdUtils/wrapStitchClips.cpp index 47b6e2b77f..79019459c1 100644 --- a/pxr/usd/lib/usdUtils/wrapStitchClips.cpp +++ b/pxr/usd/lib/usdUtils/wrapStitchClips.cpp @@ -48,13 +48,11 @@ void _ConvertStitchClips(const SdfLayerHandle& resultLayer, const std::vector& clipLayerFiles, const SdfPath& clipPath, - const boost::python::object reuseExistingTopology, const boost::python::object pyStartFrame, const boost::python::object pyEndFrame) { constexpr double dmax = std::numeric_limits::max(); UsdUtilsStitchClips(resultLayer, clipLayerFiles, clipPath, - _ConvertWithDefault(reuseExistingTopology, true), _ConvertWithDefault(pyStartFrame, dmax), _ConvertWithDefault(pyEndFrame, dmax)); } @@ -73,7 +71,6 @@ wrapStitchClips() (arg("resultLayer"), arg("clipLayerFiles"), arg("clipPath"), - arg("reuseExistingTopology")=boost::python::object(), arg("startFrame")=boost::python::object(), arg("endFrame")=boost::python::object())); From 261d87286f10dd9ce3340e75a9b33cdf943c4739 Mon Sep 17 00:00:00 2001 From: shriramiyer Date: Mon, 17 Oct 2016 14:29:49 -0700 Subject: [PATCH 226/380] Enhanced UsdImagingInstanceAdapter::GetPathForInstanceIndex to optionally return the instance context as a vector of UsdPrims. The instance context contains the chain of instance prims that must be traversed to get to the resolved rprim. The last entry in the vector contains the rprim associated with the input proto path. (Internal change: 1661947) --- pxr/usdImaging/lib/usdImaging/delegate.cpp | 21 ++++++---- pxr/usdImaging/lib/usdImaging/delegate.h | 8 +++- pxr/usdImaging/lib/usdImaging/engine.cpp | 8 ++-- pxr/usdImaging/lib/usdImaging/engine.h | 8 +++- pxr/usdImaging/lib/usdImaging/gl.cpp | 6 ++- pxr/usdImaging/lib/usdImaging/gl.h | 3 +- pxr/usdImaging/lib/usdImaging/hdEngine.cpp | 6 ++- pxr/usdImaging/lib/usdImaging/hdEngine.h | 4 +- .../lib/usdImaging/instanceAdapter.cpp | 40 +++++++++++++++---- .../lib/usdImaging/instanceAdapter.h | 4 +- pxr/usdImaging/lib/usdImaging/primAdapter.cpp | 10 +++-- pxr/usdImaging/lib/usdImaging/primAdapter.h | 3 +- pxr/usdImaging/lib/usdImaging/version.h | 4 +- 13 files changed, 93 insertions(+), 32 deletions(-) diff --git a/pxr/usdImaging/lib/usdImaging/delegate.cpp b/pxr/usdImaging/lib/usdImaging/delegate.cpp index 491d22ef23..2a77678c3f 100644 --- a/pxr/usdImaging/lib/usdImaging/delegate.cpp +++ b/pxr/usdImaging/lib/usdImaging/delegate.cpp @@ -2176,7 +2176,8 @@ UsdImagingDelegate::SetCollectionMap(CollectionMap const &collectionMap) SdfPath UsdImagingDelegate::GetPathForInstanceIndex(SdfPath const& protoPrimPath, int instanceIndex, - int *absoluteInstanceIndex) + int *absoluteInstanceIndex, + std::vector *instanceContext) { SdfPath usdPath = GetPathForUsd(protoPrimPath); @@ -2188,6 +2189,7 @@ UsdImagingDelegate::GetPathForInstanceIndex(SdfPath const& protoPrimPath, int instanceCount = 0; int protoInstanceIndex = instanceIndex; int absIndex = ALL_INSTANCES; // PointInstancer may overwrite. + std::vector resolvedInstanceContext; do { _AdapterSharedPtr const& adapter = _AdapterLookupByPath(usdPath); if (not TF_VERIFY(adapter, "can't find primAdapter for %s", @@ -2196,7 +2198,8 @@ UsdImagingDelegate::GetPathForInstanceIndex(SdfPath const& protoPrimPath, } usdPath = adapter->GetPathForInstanceIndex( - usdPath, instanceIndex, &instanceCount, &absIndex); + usdPath, instanceIndex, &instanceCount, &absIndex, + &resolvedInstanceContext); if (usdPath.IsEmpty()) { break; @@ -2214,15 +2217,19 @@ UsdImagingDelegate::GetPathForInstanceIndex(SdfPath const& protoPrimPath, } while(true); - TF_DEBUG(USDIMAGING_SELECTION).Msg("GetPathForInstanceIndex(%s, %d) = (%s, %d)\n", - protoPrimPath.GetText(), - protoInstanceIndex, - usdPath.GetText(), - absIndex); + TF_DEBUG(USDIMAGING_SELECTION).Msg("GetPathForInstanceIndex(%s, %d) = " + "(%s, %d, %s)\n", protoPrimPath.GetText(), protoInstanceIndex, + usdPath.GetText(), absIndex, + resolvedInstanceContext.back().GetPath().GetText()); + if (absoluteInstanceIndex) { *absoluteInstanceIndex = absIndex; } + if (instanceContext) { + *instanceContext = resolvedInstanceContext; + } + return GetPathForIndex(usdPath); } diff --git a/pxr/usdImaging/lib/usdImaging/delegate.h b/pxr/usdImaging/lib/usdImaging/delegate.h index 1c1bb92c9a..0c1ee40a4b 100644 --- a/pxr/usdImaging/lib/usdImaging/delegate.h +++ b/pxr/usdImaging/lib/usdImaging/delegate.h @@ -317,12 +317,18 @@ class UsdImagingDelegate : public HdSceneDelegate, public TfWeakBase { /// is an instanceIndex of the instancer for the given instanceIndex of /// the prototype. /// + /// If \p instanceContext is not NULL, it is populated with the list of + /// instance roots that must be traversed to get to the rprim. The last prim + /// in this list is always the forwarded rprim. + /// /// ALL_INSTANCES may be returned if the protoPrimPath isn't instanced. /// static constexpr int ALL_INSTANCES = -1; virtual SdfPath GetPathForInstanceIndex(const SdfPath &protoPrimPath, int instanceIndex, - int *absoluteInstanceIndex); + int *absoluteInstanceIndex, + std::vector * + instanceContext=NULL); private: typedef TfHashMap _PathToPathMap; diff --git a/pxr/usdImaging/lib/usdImaging/engine.cpp b/pxr/usdImaging/lib/usdImaging/engine.cpp index 777c1d1d54..c86ab250c4 100644 --- a/pxr/usdImaging/lib/usdImaging/engine.cpp +++ b/pxr/usdImaging/lib/usdImaging/engine.cpp @@ -618,9 +618,11 @@ UsdImagingEngine::GetPrimPathFromPrimIdColor(GfVec4i const &/*primIdColor*/, /* virtual */ SdfPath -UsdImagingEngine::GetPrimPathFromInstanceIndex(SdfPath const& protoPrimPath, - int instanceIndex, - int *absoluteInstanceIndex) +UsdImagingEngine::GetPrimPathFromInstanceIndex( + SdfPath const& protoPrimPath, + int instanceIndex, + int *absoluteInstanceIndex, + std::vector *instanceContext) { return SdfPath(); } diff --git a/pxr/usdImaging/lib/usdImaging/engine.h b/pxr/usdImaging/lib/usdImaging/engine.h index bff72d3b3e..25964fa30b 100644 --- a/pxr/usdImaging/lib/usdImaging/engine.h +++ b/pxr/usdImaging/lib/usdImaging/engine.h @@ -290,10 +290,16 @@ class UsdImagingEngine : private boost::noncopyable { /// of all instances in the instancer. Note that if the instancer instances /// heterogeneously, instanceIndex of the prototype rprim doesn't match /// the absoluteInstanceIndex in the instancer (see hd/sceneDelegate.h) + /// + /// If \p instanceContext is not NULL, it is populated with the list of + /// instance roots that must be traversed to get to the rprim. The last prim + /// in this vector is always the resolved (or forwarded) rprim. + /// virtual SdfPath GetPrimPathFromInstanceIndex( SdfPath const& protoRprimPath, int instanceIndex, - int *absoluteInstanceIndex=NULL); + int *absoluteInstanceIndex=NULL, + std::vector *instanceContext=NULL); /// Returns true if the resulting image is fully converged. /// (otherwise, caller may need to call Render() again to refine the result) diff --git a/pxr/usdImaging/lib/usdImaging/gl.cpp b/pxr/usdImaging/lib/usdImaging/gl.cpp index fc70bf4d6e..d2fab606c2 100644 --- a/pxr/usdImaging/lib/usdImaging/gl.cpp +++ b/pxr/usdImaging/lib/usdImaging/gl.cpp @@ -206,10 +206,12 @@ UsdImagingGL::GetPrimPathFromPrimIdColor( SdfPath UsdImagingGL::GetPrimPathFromInstanceIndex(const SdfPath& protoPrimPath, int instanceIndex, - int *absoluteInstanceIndex) + int *absoluteInstanceIndex, + std::vector *instanceContext) { return _engine->GetPrimPathFromInstanceIndex(protoPrimPath, instanceIndex, - absoluteInstanceIndex); + absoluteInstanceIndex, + instanceContext); } /* virtual */ diff --git a/pxr/usdImaging/lib/usdImaging/gl.h b/pxr/usdImaging/lib/usdImaging/gl.h index fe5138a980..214acb852d 100644 --- a/pxr/usdImaging/lib/usdImaging/gl.h +++ b/pxr/usdImaging/lib/usdImaging/gl.h @@ -136,7 +136,8 @@ class UsdImagingGL : public UsdImagingEngine { virtual SdfPath GetPrimPathFromInstanceIndex( const SdfPath& protoPrimPath, int instanceIndex, - int *absoluteInstanceIndex = NULL); + int *absoluteInstanceIndex = NULL, + std::vector *instanceContext=NULL); virtual bool IsConverged() const; diff --git a/pxr/usdImaging/lib/usdImaging/hdEngine.cpp b/pxr/usdImaging/lib/usdImaging/hdEngine.cpp index c68dcb7247..da2a059847 100644 --- a/pxr/usdImaging/lib/usdImaging/hdEngine.cpp +++ b/pxr/usdImaging/lib/usdImaging/hdEngine.cpp @@ -579,10 +579,12 @@ UsdImagingHdEngine::GetPrimPathFromPrimIdColor(GfVec4i const & primIdColor, SdfPath UsdImagingHdEngine::GetPrimPathFromInstanceIndex(SdfPath const& protoPrimPath, int instanceIndex, - int *absoluteInstanceIndex) + int *absoluteInstanceIndex, + std::vector *instanceContext) { return _delegate.GetPathForInstanceIndex(protoPrimPath, instanceIndex, - absoluteInstanceIndex); + absoluteInstanceIndex, + instanceContext); } /* virtual */ diff --git a/pxr/usdImaging/lib/usdImaging/hdEngine.h b/pxr/usdImaging/lib/usdImaging/hdEngine.h index c7bdd3bfb0..2d5b08ab28 100644 --- a/pxr/usdImaging/lib/usdImaging/hdEngine.h +++ b/pxr/usdImaging/lib/usdImaging/hdEngine.h @@ -105,7 +105,9 @@ class UsdImagingHdEngine : public UsdImagingEngine virtual SdfPath GetPrimPathFromInstanceIndex(SdfPath const& protoPrimPath, int instanceIndex, - int *absoluteInstanceIndex=NULL); + int *absoluteInstanceIndex=NULL, + std::vector + *instanceContext=NULL); virtual bool IsConverged() const; diff --git a/pxr/usdImaging/lib/usdImaging/instanceAdapter.cpp b/pxr/usdImaging/lib/usdImaging/instanceAdapter.cpp index caa35a0d90..5fb76f322a 100644 --- a/pxr/usdImaging/lib/usdImaging/instanceAdapter.cpp +++ b/pxr/usdImaging/lib/usdImaging/instanceAdapter.cpp @@ -1269,8 +1269,10 @@ struct UsdImagingInstanceAdapter::_GetPathForInstanceIndexFn _GetPathForInstanceIndexFn( UsdImagingInstanceAdapter* adapter_, SdfPath const &usdPath_, - int instanceIndex_) - : adapter(adapter_), usdPath(usdPath_), instanceIndex(instanceIndex_) + int instanceIndex_, + std::vector *instanceContextPtr_) + : adapter(adapter_), usdPath(usdPath_), instanceIndex(instanceIndex_), + instanceContextPtr(instanceContextPtr_) { } void Initialize(size_t numInstances) @@ -1282,9 +1284,13 @@ struct UsdImagingInstanceAdapter::_GetPathForInstanceIndexFn { if (instanceIdx == static_cast(instanceIndex) && instanceContext.size() > 0) { instancePath = instanceContext.back().GetPath(); + + if (instanceContextPtr) { + *instanceContextPtr = instanceContext; + } + return false; } - return true; } @@ -1292,13 +1298,15 @@ struct UsdImagingInstanceAdapter::_GetPathForInstanceIndexFn SdfPath usdPath; SdfPath instancePath; int instanceIndex; + std::vector *instanceContextPtr; }; /*virtual*/ SdfPath UsdImagingInstanceAdapter::GetPathForInstanceIndex( SdfPath const &path, int instanceIndex, int *instanceCount, - int *absoluteInstanceIndex) + int *absoluteInstanceIndex, + std::vector *instanceContext) { UsdPrim const &prim = _GetPrim(path.GetAbsoluteRootOrPrimPath()); if (not prim) { @@ -1327,7 +1335,8 @@ UsdImagingInstanceAdapter::GetPathForInstanceIndex( return GetPathForInstanceIndex(instIt->first, instanceIndex, instanceCount, - absoluteInstanceIndex); + absoluteInstanceIndex, + instanceContext); } } } @@ -1361,9 +1370,9 @@ UsdImagingInstanceAdapter::GetPathForInstanceIndex( instanceIndex = instanceIndices[instanceIndex]; break; } - + _GetPathForInstanceIndexFn getPathForInstanceIndexFn( - this, instancerPath, instanceIndex); + this, instancerPath, instanceIndex, instanceContext); _RunForAllInstancesToDraw(prim, &getPathForInstanceIndexFn); @@ -1377,6 +1386,23 @@ UsdImagingInstanceAdapter::GetPathForInstanceIndex( if (instanceCount) { *instanceCount = 0; } + + // instanceContext doesn't contain the rprim itself yet. Add it here. + if (instanceContext) { + const auto rprimPathIt = instIt->second.primMap.find(path); + if (rprimPathIt != instIt->second.primMap.end()) { + SdfPath rprimPath = rprimPathIt->second.path; + + TF_DEBUG(USDIMAGING_SELECTION).Msg( + "NI: rprimPath %s\n", rprimPath.GetText()); + + instanceContext->push_back(prim.GetStage()->GetPrimAtPath(rprimPath)); + } else { + TF_WARN("Failed to find rprimPath for <%s>, instanceIndex = %d", + path.GetText(), instanceIndex); + } + } + // intentionally leave absoluteInstanceIndex as it is, so that // partial selection of point instancer can be passed through. diff --git a/pxr/usdImaging/lib/usdImaging/instanceAdapter.h b/pxr/usdImaging/lib/usdImaging/instanceAdapter.h index 08bd6dbc24..39d06cfbf5 100644 --- a/pxr/usdImaging/lib/usdImaging/instanceAdapter.h +++ b/pxr/usdImaging/lib/usdImaging/instanceAdapter.h @@ -104,7 +104,9 @@ class UsdImagingInstanceAdapter : public UsdImagingPrimAdapter virtual SdfPath GetPathForInstanceIndex(SdfPath const &path, int instanceIndex, int *instanceCount, - int *absoluteInstanceIndex); + int *absoluteInstanceIndex, + std::vector * + instanceContext); virtual SdfPath GetInstancer(SdfPath const &cachePath); diff --git a/pxr/usdImaging/lib/usdImaging/primAdapter.cpp b/pxr/usdImaging/lib/usdImaging/primAdapter.cpp index d37cfc172d..14a7b92de2 100644 --- a/pxr/usdImaging/lib/usdImaging/primAdapter.cpp +++ b/pxr/usdImaging/lib/usdImaging/primAdapter.cpp @@ -109,10 +109,12 @@ UsdImagingPrimAdapter::GetInstancer(SdfPath const &cachePath) /*virtual*/ SdfPath -UsdImagingPrimAdapter::GetPathForInstanceIndex(SdfPath const &path, - int instanceIndex, - int *instanceCount, - int *absoluteInstanceIndex) +UsdImagingPrimAdapter::GetPathForInstanceIndex( + SdfPath const &path, + int instanceIndex, + int *instanceCount, + int *absoluteInstanceIndex, + std::vector *instanceContext) { if (absoluteInstanceIndex) { *absoluteInstanceIndex = UsdImagingDelegate::ALL_INSTANCES; diff --git a/pxr/usdImaging/lib/usdImaging/primAdapter.h b/pxr/usdImaging/lib/usdImaging/primAdapter.h index dd5921de0a..7b20d8fffe 100644 --- a/pxr/usdImaging/lib/usdImaging/primAdapter.h +++ b/pxr/usdImaging/lib/usdImaging/primAdapter.h @@ -151,7 +151,8 @@ class UsdImagingPrimAdapter /// return the instanceCountForThisLevel as the number of instances. virtual SdfPath GetPathForInstanceIndex( SdfPath const &path, int instanceIndex, - int *instanceCountForThisLevel, int *absoluteInstanceIndex); + int *instanceCountForThisLevel, int *absoluteInstanceIndex, + std::vector *instanceContext); /// Returns the instancer path for given \p instancePath. If it's not /// instanced path, returns empty. diff --git a/pxr/usdImaging/lib/usdImaging/version.h b/pxr/usdImaging/lib/usdImaging/version.h index cef28ddfe2..4be4eb6010 100644 --- a/pxr/usdImaging/lib/usdImaging/version.h +++ b/pxr/usdImaging/lib/usdImaging/version.h @@ -28,6 +28,8 @@ // Version 4 -- Populate returns SdfPath, HdxSelectionInstanceMap // Version 5 -- GetPathForInstanceIndex returns absoluteInstanceIndex. // Version 6 -- PrimAdater::GetDependPaths -#define USD_IMAGING_API 6 +// Version 7 -- GetPathForInstanceIndex returns instanceContext. + +#define USD_IMAGING_API 7 #endif // USD_IMAGING_VERSION_H From 82a4814fdca057af251433147158d09f93b29e5a Mon Sep 17 00:00:00 2001 From: gitamohr Date: Mon, 17 Oct 2016 14:30:05 -0700 Subject: [PATCH 227/380] usd: In CrateFile::_BufferedOutput, instead of yielding the CPU when no free buffers are available, invoke Wait() on the dispatcher to flush pending writes. This fixes the single-threaded case where there are no workers -- in that case yielding the CPU just waits forever. Now we just fill all the buffers, then flush them all, and repeat. (Internal change: 1662012) --- pxr/usd/lib/usd/crateFile.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/pxr/usd/lib/usd/crateFile.cpp b/pxr/usd/lib/usd/crateFile.cpp index 583d1dd92a..363dabdfae 100644 --- a/pxr/usd/lib/usd/crateFile.cpp +++ b/pxr/usd/lib/usd/crateFile.cpp @@ -26,7 +26,6 @@ #include "pxr/base/arch/demangle.h" #include "pxr/base/arch/errno.h" #include "pxr/base/arch/fileSystem.h" -#include "pxr/base/arch/nap.h" #include "pxr/base/gf/half.h" #include "pxr/base/gf/matrix2d.h" #include "pxr/base/gf/matrix3d.h" @@ -495,7 +494,7 @@ class CrateFile::_BufferedOutput _QueueWrite(std::move(_buffer), _bufferPos); // Get a new _buffer. May have to wait if all are pending writes. while (!_freeBuffers.try_pop(_buffer)) - ArchThreadYield(); + _dispatcher.Wait(); } // Adjust the buffer to start at the write head. _bufferPos = _filePos; From b39539f1a34a0898626ac86d8cf1aff4331d53d6 Mon Sep 17 00:00:00 2001 From: gitamohr Date: Mon, 17 Oct 2016 14:30:10 -0700 Subject: [PATCH 228/380] usd: Add a way to atomically "find or insert" into a UsdStageCache. (Internal change: 1662021) --- pxr/usd/lib/usd/stage.cpp | 166 +++++++++++++++++--------- pxr/usd/lib/usd/stage.h | 5 + pxr/usd/lib/usd/stageCache.cpp | 106 ++++++++++++++++ pxr/usd/lib/usd/stageCache.h | 57 ++++++++- pxr/usd/lib/usd/stageCacheContext.cpp | 19 +++ pxr/usd/lib/usd/stageCacheContext.h | 1 + 6 files changed, 295 insertions(+), 59 deletions(-) diff --git a/pxr/usd/lib/usd/stage.cpp b/pxr/usd/lib/usd/stage.cpp index af53fe2f9d..5ee42fcbfa 100644 --- a/pxr/usd/lib/usd/stage.cpp +++ b/pxr/usd/lib/usd/stage.cpp @@ -716,6 +716,110 @@ UsdStage::Open(const std::string& filePath, return Open(rootLayer, pathResolverContext, load); } +class Usd_StageOpenRequest : public UsdStageCacheRequest +{ +public: + Usd_StageOpenRequest(UsdStage::InitialLoadSet load, + SdfLayerHandle const &rootLayer) + : _rootLayer(rootLayer) + , _initialLoadSet(load) {} + Usd_StageOpenRequest(UsdStage::InitialLoadSet load, + SdfLayerHandle const &rootLayer, + SdfLayerHandle const &sessionLayer) + : _rootLayer(rootLayer) + , _sessionLayer(sessionLayer) + , _initialLoadSet(load) {} + Usd_StageOpenRequest(UsdStage::InitialLoadSet load, + SdfLayerHandle const &rootLayer, + ArResolverContext const &pathResolverContext) + : _rootLayer(rootLayer) + , _pathResolverContext(pathResolverContext) + , _initialLoadSet(load) {} + Usd_StageOpenRequest(UsdStage::InitialLoadSet load, + SdfLayerHandle const &rootLayer, + SdfLayerHandle const &sessionLayer, + ArResolverContext const &pathResolverContext) + : _rootLayer(rootLayer) + , _sessionLayer(sessionLayer) + , _pathResolverContext(pathResolverContext) + , _initialLoadSet(load) {} + + virtual ~Usd_StageOpenRequest() {} + virtual bool IsSatisfiedBy(UsdStageRefPtr const &stage) const { + // Works if other stage's root layer matches and we either don't care + // about the session layer or it matches, and we either don't care about + // the path resolverContext or it matches. + return _rootLayer == stage->GetRootLayer() && + (!_sessionLayer || (*_sessionLayer == stage->GetSessionLayer())) && + (!_pathResolverContext || (*_pathResolverContext == + stage->GetPathResolverContext())); + } + virtual bool IsSatisfiedBy(UsdStageCacheRequest const &other) const { + auto req = dynamic_cast(&other); + if (!req) + return false; + + // Works if other's root layer matches and we either don't care about + // the session layer or it matches, and we either don't care about the + // path resolverContext or it matches. + return _rootLayer == req->_rootLayer && + (!_sessionLayer || (_sessionLayer == req->_sessionLayer)) && + (!_pathResolverContext || (_pathResolverContext == + req->_pathResolverContext)); + } + virtual UsdStageRefPtr Manufacture() { + return UsdStage::_InstantiateStage( + SdfLayerRefPtr(_rootLayer), + _sessionLayer ? SdfLayerRefPtr(*_sessionLayer) : + _CreateAnonymousSessionLayer(_rootLayer), + _pathResolverContext ? *_pathResolverContext : + _CreatePathResolverContext(_rootLayer), + _initialLoadSet); + } + +private: + SdfLayerHandle _rootLayer; + boost::optional _sessionLayer; + boost::optional _pathResolverContext; + UsdStage::InitialLoadSet _initialLoadSet; +}; + +/* static */ +template +UsdStageRefPtr +UsdStage::_OpenImpl(InitialLoadSet load, Args const &... args) +{ + // Try to find a matching stage in read-only caches. + for (const UsdStageCache *cache: + UsdStageCacheContext::_GetReadableCaches()) { + if (UsdStageRefPtr stage = cache->FindOneMatching(args...)) + return stage; + } + + // If none found, request the stage in all the writable caches. If we + // manufacture a stage, we'll publish it to all the writable caches, so + // subsequent requests will get the same stage out. + UsdStageRefPtr stage; + auto writableCaches = UsdStageCacheContext::_GetWritableCaches(); + if (writableCaches.empty()) { + stage = Usd_StageOpenRequest(load, args...).Manufacture(); + } + else { + for (UsdStageCache *cache: writableCaches) { + auto r = cache->RequestStage(Usd_StageOpenRequest(load, args...)); + if (!stage) + stage = r.first; + if (r.second) { + // We manufactured the stage -- we published it to all the other + // caches too, so nothing left to do. + break; + } + } + } + TF_VERIFY(stage); + return stage; +} + /* static */ UsdStageRefPtr UsdStage::Open(const SdfLayerHandle& rootLayer, InitialLoadSet load) @@ -730,19 +834,7 @@ UsdStage::Open(const SdfLayerHandle& rootLayer, InitialLoadSet load) rootLayer->GetIdentifier().c_str(), TfStringify(load).c_str()); - // Try to find a matching stage in any caches. - BOOST_FOREACH(const UsdStageCache *cache, - UsdStageCacheContext::_GetReadableCaches()) { - if (UsdStageRefPtr stage = cache->FindOneMatching(rootLayer)) - return stage; - } - - // No cached stages. Make a new stage, and populate caches with it. - return _InstantiateStage( - rootLayer, - _CreateAnonymousSessionLayer(rootLayer), - _CreatePathResolverContext(rootLayer), - load); + return _OpenImpl(load, rootLayer); } /* static */ @@ -762,21 +854,7 @@ UsdStage::Open(const SdfLayerHandle& rootLayer, sessionLayer ? sessionLayer->GetIdentifier().c_str() : "", TfStringify(load).c_str()); - // Try to find a matching stage in any caches. - BOOST_FOREACH(const UsdStageCache *cache, - UsdStageCacheContext::_GetReadableCaches()) { - if (UsdStageRefPtr stage = - cache->FindOneMatching(rootLayer, sessionLayer)) { - return stage; - } - } - - // No cached stages. Make a new stage, and populate caches with it. - return _InstantiateStage( - rootLayer, - sessionLayer, - _CreatePathResolverContext(rootLayer), - load); + return _OpenImpl(load, rootLayer, sessionLayer); } /* static */ @@ -797,21 +875,7 @@ UsdStage::Open(const SdfLayerHandle& rootLayer, pathResolverContext.GetDebugString().c_str(), TfStringify(load).c_str()); - // Try to find a matching stage in any caches. - BOOST_FOREACH(const UsdStageCache *cache, - UsdStageCacheContext::_GetReadableCaches()) { - if (UsdStageRefPtr stage = - cache->FindOneMatching(rootLayer, pathResolverContext)) { - return stage; - } - } - - // No cached stages. Make a new stage, and populate caches with it. - return _InstantiateStage( - rootLayer, - _CreateAnonymousSessionLayer(rootLayer), - pathResolverContext, - load); + return _OpenImpl(load, rootLayer, pathResolverContext); } /* static */ @@ -834,21 +898,7 @@ UsdStage::Open(const SdfLayerHandle& rootLayer, pathResolverContext.GetDebugString().c_str(), TfStringify(load).c_str()); - // Try to find a matching stage in any caches. - BOOST_FOREACH(const UsdStageCache *cache, - UsdStageCacheContext::_GetReadableCaches()) { - if (UsdStageRefPtr stage = cache->FindOneMatching( - rootLayer, sessionLayer, pathResolverContext)) { - return stage; - } - } - - // No cached stages. Make a new stage, and populate caches with it. - return _InstantiateStage( - rootLayer, - sessionLayer, - pathResolverContext, - load); + return _OpenImpl(load, rootLayer, sessionLayer, pathResolverContext); } SdfPropertySpecHandle diff --git a/pxr/usd/lib/usd/stage.h b/pxr/usd/lib/usd/stage.h index bde7a3cfa9..c2fe836fdd 100644 --- a/pxr/usd/lib/usd/stage.h +++ b/pxr/usd/lib/usd/stage.h @@ -1114,6 +1114,10 @@ class UsdStage : public TfRefBase, public TfWeakBase { const ArResolverContext& pathResolverContext, InitialLoadSet load); + // Helper for Open() overloads -- searches and publishes to bound caches. + template + static UsdStageRefPtr _OpenImpl(InitialLoadSet load, Args const &... args); + // Common ref ptr initialization, called by public, static constructors. // // This method will either return a valid refptr (if the stage is correctly @@ -1673,6 +1677,7 @@ class UsdStage : public TfRefBase, public TfWeakBase { friend class UsdVariantSet; friend class UsdVariantSets; friend class Usd_PrimData; + friend class Usd_StageOpenRequest; }; template diff --git a/pxr/usd/lib/usd/stageCache.cpp b/pxr/usd/lib/usd/stageCache.cpp index 80d00ec8a9..46f047171a 100644 --- a/pxr/usd/lib/usd/stageCache.cpp +++ b/pxr/usd/lib/usd/stageCache.cpp @@ -29,6 +29,8 @@ #include "pxr/usd/ar/resolverContext.h" +#include "pxr/base/arch/nap.h" + #include #include #include @@ -181,9 +183,36 @@ struct DebugHelper } // anonymous ns +struct UsdStageCacheRequest::_Mailbox { + _Mailbox() : state(0) {} + + UsdStageRefPtr Wait() { + while (state == 1) + ArchThreadYield(); + return stage; + } + + bool Subscribed() const { return state > 0; } + + std::atomic_int state; // 0: unsubscribed, 1: subscribed, 2: delivered. + UsdStageRefPtr stage; +}; + +struct UsdStageCacheRequest::_Data +{ + std::vector<_Mailbox *> subscribed; +}; + +void +UsdStageCacheRequest::_DataDeleter::operator()(UsdStageCacheRequest::_Data *d) +{ + delete d; +} + struct Usd_StageCacheImpl { StageContainer stages; + std::vector pendingRequests; string debugName; }; @@ -246,6 +275,71 @@ UsdStageCache::Size() const return _impl->stages.size(); } +std::pair +UsdStageCache::RequestStage(UsdStageCacheRequest &&request) +{ + UsdStageCacheRequest::_Mailbox mailbox; + + { LockGuard lock(_mutex); + // Does the cache currently have a match? If so, done. + StagesByStage &byStage = _impl->stages.get(); + for (auto const &entry: byStage) + if (request.IsSatisfiedBy(entry.stage)) + return std::make_pair(entry.stage, false); + + // Check to see if any pending requests can satisfy. + for (auto *pending: _impl->pendingRequests) { + if (request.IsSatisfiedBy(*pending)) { + // Subscribe to the request so it delivers us a stage. + pending->_Subscribe(&mailbox); + break; + } + } + + // If we didn't subscribe to a pending request, then we will become a + // pending request and load the stage. + if (!mailbox.Subscribed()) + _impl->pendingRequests.push_back(&request); + + // Drop the lock to wait for the pending request or to load the stage. + } + + // If we subscribed to another pending request, just wait for it. + if (mailbox.Subscribed()) + return std::make_pair(mailbox.Wait(), false); + + // We are a pending request -- manufacture a stage. If manufacturing fails, + // issue an error only if the manufacturing process didn't issue its own. + TfErrorMark m; + UsdStageRefPtr stage = request.Manufacture(); + if (!stage && m.IsClean()) { + TF_RUNTIME_ERROR("UsdStageCacheRequest failed to manufacture a valid " + "stage."); + } + + // If we successfully instantiated a stage, insert it into the cache. + if (stage) + Insert(stage); + + // We have to deliver our stage to all the subscribed mailboxes, even if our + // stage is null. + { LockGuard lock(_mutex); + if (request._data) { + for (auto *mbox: request._data->subscribed) { + mbox->stage = stage; + mbox->state = 2; // delivered - this unblocks Wait()ing mboxes. + } + } + // Remove this request as a pending request. + _impl->pendingRequests.erase( + std::remove(_impl->pendingRequests.begin(), + _impl->pendingRequests.end(), &request), + _impl->pendingRequests.end()); + } + + return std::make_pair(stage, true); +} + UsdStageRefPtr UsdStageCache::Find(Id id) const { @@ -567,3 +661,15 @@ UsdDescribe(const UsdStageCache &cache) cache.Size()); } +UsdStageCacheRequest::~UsdStageCacheRequest() +{ +} + +void +UsdStageCacheRequest::_Subscribe(_Mailbox *mailbox) +{ + if (!_data) + _data.reset(new _Data); + _data->subscribed.push_back(mailbox); + mailbox->state = 1; // subscribed. +} diff --git a/pxr/usd/lib/usd/stageCache.h b/pxr/usd/lib/usd/stageCache.h index 2db2eaaabf..3f3570c883 100644 --- a/pxr/usd/lib/usd/stageCache.h +++ b/pxr/usd/lib/usd/stageCache.h @@ -40,6 +40,8 @@ TF_DECLARE_REF_PTRS(UsdStage); class ArResolverContext; +class UsdStageCacheRequest; + /// \class UsdStageCache /// /// A strongly concurrency safe collection of UsdStageRefPtr s, enabling @@ -161,6 +163,32 @@ class UsdStageCache /// Return true if this cache holds no stages, false otherwise. bool IsEmpty() const { return Size() == 0; } + /// Find an existing stage in the cache that satisfies \p request, or invoke + /// request.Manufacture() to create one and insert it into the cache. + /// Return the resulting stage and a bool indicating whether or not this + /// call manufactured the stage. + /// + /// This avoids race conditions in concurrent code that can occur using the + /// other public methods. Consider this racy example: + /// + /// \code + /// if (!cache.FindOneMatching(rootLayer)) { + /// auto stage = UsdStage::Open(rootLayer); + /// cache.Insert(stage); + /// } + /// \endcode + /// + /// This will race with another thread doing the same thing, resulting in + /// two stages with the same root layer inserted in the cache. This is + /// potentially rather inefficient since stage creation can be expensive, + /// depending on how many objects and how many prims & layers the stage + /// contains. RequestStage() avoids this by ensuring that there is no race + /// and the stage is created only once. + /// + /// Note that request should not be retained and must not be reused. + std::pair + RequestStage(UsdStageCacheRequest &&request); + /// Find the stage in this cache corresponding to \p id in this cache. If /// \p id is not valid (see Id::IsValid()) or if this cache does not have a /// stage corresponding to \p id, return null. @@ -177,7 +205,7 @@ class UsdStageCache /// than one matching stage in this cache, return an arbitrary matching one. /// See also FindAllMatching(). UsdStageRefPtr FindOneMatching(const SdfLayerHandle &rootLayer, - const SdfLayerHandle &sessionLayer) const; + const SdfLayerHandle &sessionLayer) const; /// Find a stage in this cache with \p rootLayer and \p pathResolverContext. /// If there is no matching stage in this cache, return null. If there is @@ -302,4 +330,31 @@ class UsdStageCache mutable std::mutex _mutex; }; +class UsdStageCacheRequest +{ +public: + virtual ~UsdStageCacheRequest(); + + // Return true if the stage satisfies this request. + virtual bool IsSatisfiedBy(UsdStageRefPtr const &stage) const = 0; + + // Return true if the pending request will satisfy this request, once + // complete. + virtual bool IsSatisfiedBy(UsdStageCacheRequest const &pending) const = 0; + + // Invoked to manufacture a stage to insert in the cache. Postcondition: + // IsSatisfiedBy() must return true for the resulting stage. + virtual UsdStageRefPtr Manufacture() = 0; + +private: + friend class UsdStageCache; + + struct _Mailbox; + void _Subscribe(_Mailbox *); + + struct _Data; + struct _DataDeleter { void operator()(_Data *); }; + std::unique_ptr<_Data, _DataDeleter> _data; +}; + #endif // USD_STAGECACHE_H diff --git a/pxr/usd/lib/usd/stageCacheContext.cpp b/pxr/usd/lib/usd/stageCacheContext.cpp index 3eb548e27a..3ba3a8bfd0 100644 --- a/pxr/usd/lib/usd/stageCacheContext.cpp +++ b/pxr/usd/lib/usd/stageCacheContext.cpp @@ -39,6 +39,25 @@ TF_REGISTRY_FUNCTION(TfEnum) { TF_ADD_ENUM_NAME(Usd_NoBlock); } +/* static */ +vector +UsdStageCacheContext::_GetReadOnlyCaches() +{ + const Stack &stack = GetStack(); + vector caches; + caches.reserve(stack.size()); + BOOST_REVERSE_FOREACH(const UsdStageCacheContext *ctx, stack) { + if (ctx->_blockType == UsdBlockStageCaches) { + break; + } else if (ctx->_blockType == UsdBlockStageCachePopulation) { + continue; + } else if (ctx->_isReadOnlyCache) { + caches.push_back(ctx->_roCache); + } + } + return caches; +} + /* static */ vector UsdStageCacheContext::_GetReadableCaches() diff --git a/pxr/usd/lib/usd/stageCacheContext.h b/pxr/usd/lib/usd/stageCacheContext.h index f2da9a355a..40255677cf 100644 --- a/pxr/usd/lib/usd/stageCacheContext.h +++ b/pxr/usd/lib/usd/stageCacheContext.h @@ -139,6 +139,7 @@ struct UsdStageCacheContext : public TfStacked private: friend class UsdStage; + static std::vector _GetReadOnlyCaches(); static std::vector _GetReadableCaches(); static std::vector _GetWritableCaches(); From 39600533a454723a91bb584978c4629987732366 Mon Sep 17 00:00:00 2001 From: blevin Date: Mon, 17 Oct 2016 14:30:14 -0700 Subject: [PATCH 229/380] Fix relocates falling off reference arc. Fix an accidental regression in change 1641091: we need to strip variant selections from a path before querying for which relocates affect it. Update the fix (and test case) to cover this. (Internal change: 1662077) --- pxr/usd/lib/pcp/primIndex.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pxr/usd/lib/pcp/primIndex.cpp b/pxr/usd/lib/pcp/primIndex.cpp index beda080387..935aa38759 100644 --- a/pxr/usd/lib/pcp/primIndex.cpp +++ b/pxr/usd/lib/pcp/primIndex.cpp @@ -654,7 +654,7 @@ _CreateMapExpressionForArc(const SdfPath &sourcePath, // Apply relocations that affect namespace at and below this site. if (not inputs.usd) { arcExpr = targetNode.GetLayerStack() - ->GetExpressionForRelocatesAtPath(targetNode.GetPath()) + ->GetExpressionForRelocatesAtPath(targetPath) .Compose(arcExpr); } From ee25b5a7a83000312fea805faf5a4efc9b3e5eb4 Mon Sep 17 00:00:00 2001 From: spiffmon Date: Mon, 17 Oct 2016 14:30:32 -0700 Subject: [PATCH 230/380] Catch the error case in which a stage sublayer fails to be retrieved by identifier, and add a workaround for resolving searchpath-based subLayers. Also enhance tooltip display of subLayers to provide the pre-resolved identifier as well as the "realpath" of each layer. (Internal change: 1662088) --- pxr/usdImaging/lib/usdviewq/common.py | 10 ++++++++++ pxr/usdImaging/lib/usdviewq/mainWindow.py | 4 +++- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/pxr/usdImaging/lib/usdviewq/common.py b/pxr/usdImaging/lib/usdviewq/common.py index 62bb8a4a24..84bb5c97b8 100644 --- a/pxr/usdImaging/lib/usdviewq/common.py +++ b/pxr/usdImaging/lib/usdviewq/common.py @@ -151,12 +151,22 @@ def _AddSubLayers(layer, layerOffset, prefix, parentLayer, layers): for i, l in enumerate(layer.subLayerPaths): offset = offsets[i] if offsets is not None and len(offsets) > i else Sdf.LayerOffset() subLayer = Sdf.Layer.FindRelativeToLayer(layer, l) + # Due to an unfortunate behavior of the Pixar studio resolver, + # FindRelativeToLayer() may fail to resolve certain paths. We will + # remove this extra Find() call as soon as we can retire the behavior; + # in the meantime, the extra call does not hurt (but should not, in + # general, be necessary) + if not subLayer: + subLayer = Sdf.Layer.Find(l) + if subLayer: # This gives a 'tree'-ish presentation, but it looks sad in # a QTableWidget. Just use spaces for now # addedPrefix = "|-- " if parentLayer is None else "| " addedPrefix = " " _AddSubLayers(subLayer, offset, addedPrefix + prefix, layer, layers) + else: + print "Could not find layer " + l def GetRootLayerStackInfo(layer): from pxr import Sdf diff --git a/pxr/usdImaging/lib/usdviewq/mainWindow.py b/pxr/usdImaging/lib/usdviewq/mainWindow.py index 1be4a2c796..702b1c5e78 100644 --- a/pxr/usdImaging/lib/usdviewq/mainWindow.py +++ b/pxr/usdImaging/lib/usdviewq/mainWindow.py @@ -3252,7 +3252,9 @@ def _updateLayerStackView(self, obj=None): for i, layer in enumerate(layers): layerItem = QtGui.QTableWidgetItem(layer.GetHierarchicalDisplayString()) layerItem.layerPath = layer.layer.realPath - layerItem.setToolTip(layer.layer.realPath) + toolTip = "identifier: @%s@
resolved path: %s" % \ + (layer.layer.identifier, layerItem.layerPath) + layerItem.setToolTip(toolTip) tableWidget.setItem(i, 0, layerItem) offsetItem = QtGui.QTableWidgetItem(layer.GetOffsetString()) From 2e5ed5263756db42e81fce08a404e429153b8fdc Mon Sep 17 00:00:00 2001 From: unhyperbolic Date: Mon, 17 Oct 2016 14:31:07 -0700 Subject: [PATCH 231/380] PlugStaticInterface: looking up type by name again since looking up type by std::type_info doesn't work until the plugin is loaded. (Internal change: 1662145) --- pxr/base/lib/plug/staticInterface.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/pxr/base/lib/plug/staticInterface.cpp b/pxr/base/lib/plug/staticInterface.cpp index 6d2ebda6f7..6e9e958b49 100644 --- a/pxr/base/lib/plug/staticInterface.cpp +++ b/pxr/base/lib/plug/staticInterface.cpp @@ -47,7 +47,10 @@ Plug_StaticInterfaceBase::_LoadAndInstantiate(const std::type_info& type) const _initialized = true; // Validate type. - const TfType& tfType = TfType::Find(type); + // We use FindByName because Find requres that std::type_info has been + // regisered, but that won't happen until the plugin is loaded. + const TfType &tfType = + TfType::FindByName(TfType::GetCanonicalTypeName(type)); if (not tfType) { TF_CODING_ERROR("Failed to load plugin interface: " "Can't find type %s", type.name()); From a2121a7c15146c4330d42d8201d8605601eeea2d Mon Sep 17 00:00:00 2001 From: comand Date: Mon, 17 Oct 2016 14:31:22 -0700 Subject: [PATCH 232/380] Wrap basic resolution API useful for debugging, fix default implementation of AnchorRelativePath to properly handle file-relative paths. (Internal change: 1662264) --- pxr/usd/lib/ar/defaultResolver.cpp | 19 +++++++++---------- pxr/usd/lib/ar/wrapResolver.cpp | 3 +++ 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/pxr/usd/lib/ar/defaultResolver.cpp b/pxr/usd/lib/ar/defaultResolver.cpp index 1282d5d62d..b2438ff17b 100644 --- a/pxr/usd/lib/ar/defaultResolver.cpp +++ b/pxr/usd/lib/ar/defaultResolver.cpp @@ -37,7 +37,11 @@ #include -static const char* _FileRelativePathPrefix = "./"; +static bool +_IsFileRelative(const std::string& path) { + return path.find("./") == 0 or path.find("../") == 0; +} + struct Ar_DefaultResolver::_Cache { @@ -85,18 +89,14 @@ Ar_DefaultResolver::AnchorRelativePath( const std::string& anchorPath, const std::string& path) { - if (path.empty() or not IsRelativePath(path)) { - return path; - } - - if (anchorPath.empty() or IsRelativePath(anchorPath)) { + if (anchorPath.empty() or anchorPath[0] != '/' or + path.empty() or path[0] == '/' or not _IsFileRelative(path)) return path; - } // If anchorPath does not end with a '/', we assume it is specifying // a file, strip off the last component, and anchor the path to that // directory. - std::string anchoredPath = TfStringCatPaths( + const std::string anchoredPath = TfStringCatPaths( TfStringGetBeforeSuffix(anchorPath, '/'), path); return TfNormPath(anchoredPath); } @@ -104,8 +104,7 @@ Ar_DefaultResolver::AnchorRelativePath( bool Ar_DefaultResolver::IsSearchPath(const std::string& path) { - return IsRelativePath(path) - and not TfStringStartsWith(path, _FileRelativePathPrefix); + return IsRelativePath(path) and not _IsFileRelative(path); } std::string diff --git a/pxr/usd/lib/ar/wrapResolver.cpp b/pxr/usd/lib/ar/wrapResolver.cpp index cef9ccd929..73aac70c7b 100644 --- a/pxr/usd/lib/ar/wrapResolver.cpp +++ b/pxr/usd/lib/ar/wrapResolver.cpp @@ -44,6 +44,9 @@ wrapResolver() .def("CreateDefaultContext", &This::CreateDefaultContext) .def("CreateDefaultContextForAsset", &This::CreateDefaultContextForAsset) + + .def("AnchorRelativePath", &This::AnchorRelativePath) + .def("Resolve", &This::Resolve) ; def("GetResolver", ArGetResolver, From 3d698f1d60026305db8926270d07007d755f2129 Mon Sep 17 00:00:00 2001 From: MWDD Date: Mon, 17 Oct 2016 14:33:37 -0700 Subject: [PATCH 233/380] Fix for NI-PI USD invalidation. When USD NI instances PI instances, Hydra does not know about the Rprim associated with the PI instancer. Therefore, the rprims were not getting marked as dirty when for example a transform occured in the transform heirarchy. This problem was already being solved for PI cases, by asking the adapter for the dependent set of Rprim's and dirtying those. However, the adapter interface wasn't implemented for NI instances. In addition to implementing the required interface, NI instances use a different path to identify the instancer than PI. Changes: - Implemented GetDependPaths() for UsdImagingInstanceAdapter. - In _MarkSubtreeDirty() now get the depend paths for the NI instancer and mark those subtrees as dirty. (Internal change: 1662332) --- pxr/usdImaging/lib/usdImaging/delegate.cpp | 29 +++++++++++++------ .../lib/usdImaging/instanceAdapter.cpp | 27 +++++++++++++++++ .../lib/usdImaging/instanceAdapter.h | 9 ++++++ 3 files changed, 56 insertions(+), 9 deletions(-) diff --git a/pxr/usdImaging/lib/usdImaging/delegate.cpp b/pxr/usdImaging/lib/usdImaging/delegate.cpp index 2a77678c3f..f229f35e3c 100644 --- a/pxr/usdImaging/lib/usdImaging/delegate.cpp +++ b/pxr/usdImaging/lib/usdImaging/delegate.cpp @@ -2099,6 +2099,17 @@ UsdImagingDelegate::_MarkSubtreeDirty(SdfPath const &subtreeRoot, // redirect to native instancer. _MarkRprimOrInstancerDirty(instancer, instancerDirtyFlag); + + + // also communicate adapter to get the list of instanced proto rprims + // to be marked as dirty. for those are not in the namespace children + // of the instancer (needed for NI-PI cases). + SdfPathVector const &paths = adapter->GetDependPaths(instancer); + TF_FOR_ALL (instIt, paths) { + // recurse + _MarkSubtreeDirty(*instIt, rprimDirtyFlag, instancerDirtyFlag); + } + } else if (_instancerPrimPaths.find(it->first) != _instancerPrimPaths.end()) { // XXX: workaround for per-instance visibility in nested case. // testPxUsdGeomGLPopOut/test_*_5, test_*_6 @@ -2109,19 +2120,19 @@ UsdImagingDelegate::_MarkSubtreeDirty(SdfPath const &subtreeRoot, // instancer itself _MarkRprimOrInstancerDirty(it->first, instancerDirtyFlag); + + // also communicate adapter to get the list of instanced proto rprims + // to be marked as dirty. for those are not in the namespace children + // of the instancer. + SdfPathVector const &paths = adapter->GetDependPaths(it->first); + TF_FOR_ALL (instIt, paths) { + // recurse + _MarkSubtreeDirty(*instIt, rprimDirtyFlag, instancerDirtyFlag); + } } else { // rprim _MarkRprimOrInstancerDirty(it->first, rprimDirtyFlag); } - - // also communicate adapter to get the list of instanced proto rprims - // to be marked as dirty. for those are not in the namespace children - // of the instancer. - SdfPathVector const &paths = adapter->GetDependPaths(it->first); - TF_FOR_ALL (instIt, paths) { - // recurse - _MarkSubtreeDirty(*instIt, rprimDirtyFlag, instancerDirtyFlag); - } } } diff --git a/pxr/usdImaging/lib/usdImaging/instanceAdapter.cpp b/pxr/usdImaging/lib/usdImaging/instanceAdapter.cpp index 5fb76f322a..5602057d6e 100644 --- a/pxr/usdImaging/lib/usdImaging/instanceAdapter.cpp +++ b/pxr/usdImaging/lib/usdImaging/instanceAdapter.cpp @@ -1513,3 +1513,30 @@ UsdImagingInstanceAdapter::PopulateSelection( return found; } + +/*virtual*/ +SdfPathVector +UsdImagingInstanceAdapter::GetDependPaths(SdfPath const &instancerPath) const +{ + _InstancerDataMap::const_iterator it = _instancerData.find(instancerPath); + + SdfPathVector result; + if (it != _instancerData.end()) { + _InstancerData const & instancerData = it->second; + + // if the proto path is property path, that should be in the subtree + // and no need to return. + TF_FOR_ALL (protoIt, instancerData.primMap) { + SdfPath const &protoPath = protoIt->first; + if (protoPath.IsPrimOrPrimVariantSelectionPath()) { + if (not protoPath.HasPrefix(instancerPath)) { + result.push_back(protoPath); + } + } + } + } + // XXX: we may want to cache this result in _instancerData. + return result; +} + + diff --git a/pxr/usdImaging/lib/usdImaging/instanceAdapter.h b/pxr/usdImaging/lib/usdImaging/instanceAdapter.h index 39d06cfbf5..142d25ac6d 100644 --- a/pxr/usdImaging/lib/usdImaging/instanceAdapter.h +++ b/pxr/usdImaging/lib/usdImaging/instanceAdapter.h @@ -117,6 +117,15 @@ class UsdImagingInstanceAdapter : public UsdImagingPrimAdapter VtIntArray const &instanceIndices, HdxSelectionSharedPtr const &result); + // ---------------------------------------------------------------------- // + /// \name Utilities + // ---------------------------------------------------------------------- // + + /// Returns the depending rprim paths which don't exist in descendants. + /// Used for change tracking over subtree boundary (e.g. instancing) + virtual SdfPathVector GetDependPaths(SdfPath const &path) const; + + private: struct _ProtoRprim; From 9abba3bcb0a180d2cd7af0fa74a294ffc1d4d302 Mon Sep 17 00:00:00 2001 From: blevin Date: Mon, 17 Oct 2016 14:34:31 -0700 Subject: [PATCH 234/380] Deadlock with AddTarget() of a relative path. Fixes issue #76. (Internal change: 1662430) --- pxr/usd/lib/usd/instanceCache.cpp | 7 +++++++ pxr/usd/lib/usd/instanceCache.h | 2 +- pxr/usd/lib/usd/relationship.cpp | 13 +++++++++---- 3 files changed, 17 insertions(+), 5 deletions(-) diff --git a/pxr/usd/lib/usd/instanceCache.cpp b/pxr/usd/lib/usd/instanceCache.cpp index 01e593d327..5a5a5cb79b 100644 --- a/pxr/usd/lib/usd/instanceCache.cpp +++ b/pxr/usd/lib/usd/instanceCache.cpp @@ -362,6 +362,13 @@ Usd_InstanceCache::IsPathMasterOrInMaster(const SdfPath& path) if (path.IsEmpty()) { return false; } + if (!path.IsAbsolutePath()) { + // We require an absolute path because there is no way for us + // to walk to the root prim level from a relative path. + TF_CODING_ERROR("IsPathMasterOrInMaster() requires an absolute path " + "but was given <%s>", path.GetText()); + return false; + } SdfPath rootPath = path; while (not rootPath.IsRootPrimPath()) { diff --git a/pxr/usd/lib/usd/instanceCache.h b/pxr/usd/lib/usd/instanceCache.h index fa9f05720c..c1e9f5a631 100644 --- a/pxr/usd/lib/usd/instanceCache.h +++ b/pxr/usd/lib/usd/instanceCache.h @@ -132,7 +132,7 @@ class Usd_InstanceCache : boost::noncopyable void ProcessChanges(Usd_InstanceChanges* changes); /// Returns true if an object at \p path is a master or in a - /// master. + /// master. \p path must be either an absolute path or empty. static bool IsPathMasterOrInMaster(const SdfPath& path); /// Returns the paths of all master prims for instance prim diff --git a/pxr/usd/lib/usd/relationship.cpp b/pxr/usd/lib/usd/relationship.cpp index 349a167a00..69799f4d97 100644 --- a/pxr/usd/lib/usd/relationship.cpp +++ b/pxr/usd/lib/usd/relationship.cpp @@ -56,11 +56,16 @@ SdfPath UsdRelationship::_GetTargetForAuthoring(const SdfPath &target, std::string* whyNot) const { - if (Usd_InstanceCache::IsPathMasterOrInMaster(target)) { - if (whyNot) { - *whyNot = "Cannot target a master or an object within a master."; + if (!target.IsEmpty()) { + SdfPath absTarget = + target.MakeAbsolutePath(GetPath().GetAbsoluteRootOrPrimPath()); + if (Usd_InstanceCache::IsPathMasterOrInMaster(absTarget)) { + if (whyNot) { + *whyNot = "Cannot target a master or an object within a " + "master."; + } + return SdfPath(); } - return SdfPath(); } UsdStage *stage = _GetStage(); From a5c21c169e2deb320fdf557af747ffcc1cb50d33 Mon Sep 17 00:00:00 2001 From: pixar-oss Date: Mon, 17 Oct 2016 14:34:40 -0700 Subject: [PATCH 235/380] Fix for PxrUsdIn crash where the ref ptr to the stage retrieved from the stage cache failed on an attempt to increment. Simply returning the ref ptr instead of a const reference to it fixes the problem. (Internal change: 1662782) --- third_party/katana/lib/usdKatana/cache.cpp | 10 +++---- third_party/katana/lib/usdKatana/cache.h | 32 +++++++++++----------- 2 files changed, 21 insertions(+), 21 deletions(-) diff --git a/third_party/katana/lib/usdKatana/cache.cpp b/third_party/katana/lib/usdKatana/cache.cpp index 1a0801dbea..6df6a19a87 100644 --- a/third_party/katana/lib/usdKatana/cache.cpp +++ b/third_party/katana/lib/usdKatana/cache.cpp @@ -197,7 +197,7 @@ _ResolvePath(const std::string& path) return ArGetResolver().Resolve(path); } -UsdStageRefPtr const& +UsdStageRefPtr UsdKatanaCache::GetStage(std::string const& fileName, std::string const& variantSelections, std::string const& ignoreLayerRegex, @@ -245,7 +245,7 @@ UsdKatanaCache::GetStage(std::string const& fileName, } -UsdStageRefPtr const& +UsdStageRefPtr UsdKatanaCache::GetStage(std::string const& fileName, std::set const& variantSelections, std::string const& ignoreLayerRegex, @@ -256,8 +256,8 @@ UsdKatanaCache::GetStage(std::string const& fileName, } // XXX, largely pasted from equivalent GetStage -// return type differs, doesn't place stageCache/context on stack -UsdStageRefPtr const +// doesn't place stageCache/context on stack +UsdStageRefPtr UsdKatanaCache::GetUncachedStage(std::string const& fileName, std::string const& variantSelections, std::string const& ignoreLayerRegex, @@ -310,7 +310,7 @@ UsdKatanaCache::GetUncachedStage(std::string const& fileName, } -UsdStageRefPtr const +UsdStageRefPtr UsdKatanaCache::GetUncachedStage(std::string const& fileName, std::set const& variantSelections, std::string const& ignoreLayerRegex, diff --git a/third_party/katana/lib/usdKatana/cache.h b/third_party/katana/lib/usdKatana/cache.h index dfa7c8043f..cb501ce66d 100644 --- a/third_party/katana/lib/usdKatana/cache.h +++ b/third_party/katana/lib/usdKatana/cache.h @@ -75,28 +75,28 @@ class UsdKatanaCache : public TfSingleton /// Get (or create) a cached usd stage with a sessionlayer containing the /// specified variant selections - UsdStageRefPtr const& GetStage(std::string const& fileName, - std::string const& variantSelections, - std::string const& ignoreLayerRegex, - bool forcePopulate); + UsdStageRefPtr GetStage(std::string const& fileName, + std::string const& variantSelections, + std::string const& ignoreLayerRegex, + bool forcePopulate); /// Same as above, variant selections as an std::set instead of str - UsdStageRefPtr const& GetStage(std::string const& fileName, - std::set const& variantSelections, - std::string const& ignoreLayerRegex, - bool forcePopulate); + UsdStageRefPtr GetStage(std::string const& fileName, + std::set const& variantSelections, + std::string const& ignoreLayerRegex, + bool forcePopulate); // Equivalent to GetStage above but without caching - UsdStageRefPtr const GetUncachedStage(std::string const& fileName, - std::string const& variantSelections, - std::string const& ignoreLayerRegex, - bool forcePopulate); + UsdStageRefPtr GetUncachedStage(std::string const& fileName, + std::string const& variantSelections, + std::string const& ignoreLayerRegex, + bool forcePopulate); // Equivalent to GetStage above but without caching - UsdStageRefPtr const GetUncachedStage(std::string const& fileName, - std::set const& variantSelections, - std::string const& ignoreLayerRegex, - bool forcePopulate); + UsdStageRefPtr GetUncachedStage(std::string const& fileName, + std::set const& variantSelections, + std::string const& ignoreLayerRegex, + bool forcePopulate); From e768a003f834e7ad46f87bb052041c139f2e8e83 Mon Sep 17 00:00:00 2001 From: gitamohr Date: Mon, 17 Oct 2016 14:34:56 -0700 Subject: [PATCH 236/380] mayapkg: Don't explicitly try to set the thread limit. This code was added way back when we tried to default to single-threaded. We don't do that anymore. (Internal change: 1662827) --- third_party/maya/lib/usdMaya/proxyShape.cpp | 6 ------ 1 file changed, 6 deletions(-) diff --git a/third_party/maya/lib/usdMaya/proxyShape.cpp b/third_party/maya/lib/usdMaya/proxyShape.cpp index c831e9ce33..024dd3c2bf 100644 --- a/third_party/maya/lib/usdMaya/proxyShape.cpp +++ b/third_party/maya/lib/usdMaya/proxyShape.cpp @@ -38,7 +38,6 @@ #include "pxr/usd/usdGeom/tokens.h" #include "pxr/usd/usd/stageCacheContext.h" #include "pxr/usd/usdUtils/stageCache.h" -#include "pxr/base/work/threadLimits.h" #include "pxr/base/gf/bbox3d.h" #include @@ -80,11 +79,6 @@ UsdMayaProxyShape::initialize( { MStatus retValue = MS::kSuccess; - static std::once_flag once; - std::call_once(once, [](){ - WorkSetMaximumConcurrencyLimit(); - }); - // // create attr factories // From 58d0bdc63033979c8c74a986904b8b48c38b24a1 Mon Sep 17 00:00:00 2001 From: blevin Date: Mon, 17 Oct 2016 14:35:32 -0700 Subject: [PATCH 237/380] Pcp: Add another culling pass to Pcp graph optimization that can be more aggressive. Node-culling is a crucial optimization pass in Pcp composition that is a big win against the tendency for scene structure to pile up down namespace. Prime contributors are global inherits (which rarely have opinions below the root level) and sets (which add another reference at each level of grouping). The rules for when we can cull nodes are subtle due to the need to preserve structure required for correct composition, but it turns out we can be more aggressive once we are finalizing the graph, vs. using it an intermediate result. (Internal change: 1662855) --- pxr/usd/lib/pcp/primIndex.cpp | 36 +++++++++++++++++++++++------------ 1 file changed, 24 insertions(+), 12 deletions(-) diff --git a/pxr/usd/lib/pcp/primIndex.cpp b/pxr/usd/lib/pcp/primIndex.cpp index 935aa38759..b81cebb8a4 100644 --- a/pxr/usd/lib/pcp/primIndex.cpp +++ b/pxr/usd/lib/pcp/primIndex.cpp @@ -390,7 +390,8 @@ Pcp_BuildPrimIndex( static bool _NodeCanBeCulled(const PcpNodeRef& node, - const PcpLayerStackSite& rootLayerStack); + const PcpLayerStackSite& rootLayerStack, + bool finalPass); static void _GatherNodesRecursively(const PcpNodeRef& node, @@ -1396,7 +1397,8 @@ _AddArc( // This is because computing the source prim index above will have culled // everything it can *except* for the direct node. if (indexer->inputs.cull) { - if (_NodeCanBeCulled(newNode, indexer->rootSite)) { + if (_NodeCanBeCulled(newNode, indexer->rootSite, + /* finalPass = */ false)) { newNode.SetCulled(true); } else { @@ -3694,7 +3696,8 @@ _ConvertNodeForChild( static bool _NodeCanBeCulled( const PcpNodeRef& node, - const PcpLayerStackSite& rootSite) + const PcpLayerStackSite& rootSite, + bool finalPass) { // Trivial case if this node has already been culled. // This could happen if this node was culled ancestrally. @@ -3734,12 +3737,12 @@ _NodeCanBeCulled( } // We cannot cull any nodes that directly OR ancestrally provide - // variant selections. Variant selections from ancestral sites are - // necessary when evaluating variants in a recursive prim indexing - // call. Otherwise, the recursive call may wind up using a different - // selection than what had been used in the parent index. + // variant selections until the finalPass. The reason is that + // during recursive prim indexing calls, variant selections from + // ancestral sites are necessary to get the correct results + // across arcs like local inerhits. // See TrickyInheritsInVariants2 for an example of this. - if (node.HasVariantSelections()) { + if (!finalPass && node.HasVariantSelections()) { return false; } @@ -3787,7 +3790,8 @@ _NodeCanBeCulled( static void _CullSubtreesWithNoOpinions( PcpNodeRef node, - const PcpLayerStackSite& rootSite) + const PcpLayerStackSite& rootSite, + bool finalPass) { // Recurse and attempt to cull all children first. Order doesn't matter. TF_FOR_ALL(child, Pcp_GetChildrenRange(node)) { @@ -3800,12 +3804,12 @@ _CullSubtreesWithNoOpinions( continue; } - _CullSubtreesWithNoOpinions(*child, rootSite); + _CullSubtreesWithNoOpinions(*child, rootSite, finalPass); } // Now, mark this node as culled if we can. These nodes will be // removed from the prim index at the end of prim indexing. - if (_NodeCanBeCulled(node, rootSite)) { + if (_NodeCanBeCulled(node, rootSite, finalPass)) { node.SetCulled(true); } } @@ -3908,7 +3912,8 @@ _BuildInitialPrimIndexFromAncestor( _ConvertNodeForChild(rootNode, site.path.GetNameToken(), inputs); if (inputs.cull) { - _CullSubtreesWithNoOpinions(rootNode, rootSite); + _CullSubtreesWithNoOpinions(rootNode, rootSite, + /* finalPass = */ false); } // The child inherits the parent's dependencies as ancestral dependencies, @@ -4086,6 +4091,13 @@ PcpComputePrimIndex( _EnforcePermissions(&outputs->primIndex, &outputs->allErrors); } + // Do a final, more aggressive culling pass. + if (inputs.cull) { + PcpNodeRef rootNode = outputs->primIndex.GetRootNode(); + _CullSubtreesWithNoOpinions(rootNode, rootNode.GetSite(), + /* finalPass = */ true); + } + // Determine whether this prim index is instanceable and store that // information in the prim index. This requires composed metadata // values, so we do this here after the prim index is fully composed From 3d8c0419cfc894d64bbfa8fbb1dff60a5f459198 Mon Sep 17 00:00:00 2001 From: blevin Date: Mon, 17 Oct 2016 14:36:53 -0700 Subject: [PATCH 238/380] Rollback commit 58d0bdc6 until the TrickyInheritsInVariants2 failure can be fixed. (Internal change: 1663108) --- pxr/usd/lib/pcp/primIndex.cpp | 36 ++++++++++++----------------------- 1 file changed, 12 insertions(+), 24 deletions(-) diff --git a/pxr/usd/lib/pcp/primIndex.cpp b/pxr/usd/lib/pcp/primIndex.cpp index b81cebb8a4..935aa38759 100644 --- a/pxr/usd/lib/pcp/primIndex.cpp +++ b/pxr/usd/lib/pcp/primIndex.cpp @@ -390,8 +390,7 @@ Pcp_BuildPrimIndex( static bool _NodeCanBeCulled(const PcpNodeRef& node, - const PcpLayerStackSite& rootLayerStack, - bool finalPass); + const PcpLayerStackSite& rootLayerStack); static void _GatherNodesRecursively(const PcpNodeRef& node, @@ -1397,8 +1396,7 @@ _AddArc( // This is because computing the source prim index above will have culled // everything it can *except* for the direct node. if (indexer->inputs.cull) { - if (_NodeCanBeCulled(newNode, indexer->rootSite, - /* finalPass = */ false)) { + if (_NodeCanBeCulled(newNode, indexer->rootSite)) { newNode.SetCulled(true); } else { @@ -3696,8 +3694,7 @@ _ConvertNodeForChild( static bool _NodeCanBeCulled( const PcpNodeRef& node, - const PcpLayerStackSite& rootSite, - bool finalPass) + const PcpLayerStackSite& rootSite) { // Trivial case if this node has already been culled. // This could happen if this node was culled ancestrally. @@ -3737,12 +3734,12 @@ _NodeCanBeCulled( } // We cannot cull any nodes that directly OR ancestrally provide - // variant selections until the finalPass. The reason is that - // during recursive prim indexing calls, variant selections from - // ancestral sites are necessary to get the correct results - // across arcs like local inerhits. + // variant selections. Variant selections from ancestral sites are + // necessary when evaluating variants in a recursive prim indexing + // call. Otherwise, the recursive call may wind up using a different + // selection than what had been used in the parent index. // See TrickyInheritsInVariants2 for an example of this. - if (!finalPass && node.HasVariantSelections()) { + if (node.HasVariantSelections()) { return false; } @@ -3790,8 +3787,7 @@ _NodeCanBeCulled( static void _CullSubtreesWithNoOpinions( PcpNodeRef node, - const PcpLayerStackSite& rootSite, - bool finalPass) + const PcpLayerStackSite& rootSite) { // Recurse and attempt to cull all children first. Order doesn't matter. TF_FOR_ALL(child, Pcp_GetChildrenRange(node)) { @@ -3804,12 +3800,12 @@ _CullSubtreesWithNoOpinions( continue; } - _CullSubtreesWithNoOpinions(*child, rootSite, finalPass); + _CullSubtreesWithNoOpinions(*child, rootSite); } // Now, mark this node as culled if we can. These nodes will be // removed from the prim index at the end of prim indexing. - if (_NodeCanBeCulled(node, rootSite, finalPass)) { + if (_NodeCanBeCulled(node, rootSite)) { node.SetCulled(true); } } @@ -3912,8 +3908,7 @@ _BuildInitialPrimIndexFromAncestor( _ConvertNodeForChild(rootNode, site.path.GetNameToken(), inputs); if (inputs.cull) { - _CullSubtreesWithNoOpinions(rootNode, rootSite, - /* finalPass = */ false); + _CullSubtreesWithNoOpinions(rootNode, rootSite); } // The child inherits the parent's dependencies as ancestral dependencies, @@ -4091,13 +4086,6 @@ PcpComputePrimIndex( _EnforcePermissions(&outputs->primIndex, &outputs->allErrors); } - // Do a final, more aggressive culling pass. - if (inputs.cull) { - PcpNodeRef rootNode = outputs->primIndex.GetRootNode(); - _CullSubtreesWithNoOpinions(rootNode, rootNode.GetSite(), - /* finalPass = */ true); - } - // Determine whether this prim index is instanceable and store that // information in the prim index. This requires composed metadata // values, so we do this here after the prim index is fully composed From a3e50d17e26da3e161a4f87bb983cdeeac0cca24 Mon Sep 17 00:00:00 2001 From: c64kernal Date: Mon, 17 Oct 2016 15:15:22 -0700 Subject: [PATCH 239/380] Refactoring usdImaging a little bit. The goal is to get the usdImaging library to contain only the Hydra delegate and adapters for USD. There was a bunch of other stuff in there also that was used for setup. This has been moved to usdImagingGL for now and will likely be refactored further. (Internal change: 1663196) --- pxr/usdImaging/lib/CMakeLists.txt | 1 + pxr/usdImaging/lib/usdImaging/CMakeLists.txt | 37 ------- .../lib/usdImagingGL/CMakeLists.txt | 87 +++++++++++++++++ .../{usdImaging => usdImagingGL}/__init__.py | 6 +- .../defaultTaskDelegate.cpp | 68 ++++++------- .../defaultTaskDelegate.h | 24 ++--- .../{usdImaging => usdImagingGL}/engine.cpp | 44 ++++----- .../lib/{usdImaging => usdImagingGL}/engine.h | 6 +- .../lib/{usdImaging => usdImagingGL}/gl.cpp | 28 +++--- .../lib/{usdImaging => usdImagingGL}/gl.h | 8 +- .../{usdImaging => usdImagingGL}/hdEngine.cpp | 96 +++++++++---------- .../{usdImaging => usdImagingGL}/hdEngine.h | 42 ++++---- .../{usdImaging => usdImagingGL}/module.cpp | 0 .../moduleDeps.cpp | 5 +- .../refEngine.cpp | 61 ++++++------ .../{usdImaging => usdImagingGL}/refEngine.h | 12 +-- .../taskDelegate.cpp | 10 +- .../taskDelegate.h | 28 +++--- .../testenv/testUsdImagingGLBasicDrawing.cpp} | 39 ++++---- .../unitTestGLDrawing.cpp | 66 ++++++------- .../unitTestGLDrawing.h | 18 ++-- .../{usdImaging => usdImagingGL}/wrapGL.cpp | 4 +- pxr/usdImaging/lib/usdviewq/mainWindow.py | 12 +-- pxr/usdImaging/lib/usdviewq/stageView.py | 42 ++++---- .../katana/lib/usdKatana/CMakeLists.txt | 1 + third_party/katana/lib/usdKatana/cache.cpp | 2 +- .../katana/plugin/vmp_usd/CMakeLists.txt | 1 + third_party/katana/plugin/vmp_usd/usdVMP.cpp | 2 +- third_party/katana/plugin/vmp_usd/usdVMP.h | 2 +- .../maya/lib/pxrUsdMayaGL/CMakeLists.txt | 1 + .../maya/lib/pxrUsdMayaGL/batchRenderer.h | 1 - .../maya/lib/pxrUsdMayaGL/hdRenderer.cpp | 4 +- .../maya/lib/pxrUsdMayaGL/hdRenderer.h | 2 +- .../maya/lib/pxrUsdMayaGL/proxyDrawOverride.h | 1 - 34 files changed, 409 insertions(+), 352 deletions(-) create mode 100644 pxr/usdImaging/lib/usdImagingGL/CMakeLists.txt rename pxr/usdImaging/lib/{usdImaging => usdImagingGL}/__init__.py (92%) rename pxr/usdImaging/lib/{usdImaging => usdImagingGL}/defaultTaskDelegate.cpp (89%) rename pxr/usdImaging/lib/{usdImaging => usdImagingGL}/defaultTaskDelegate.h (85%) rename pxr/usdImaging/lib/{usdImaging => usdImagingGL}/engine.cpp (93%) rename pxr/usdImaging/lib/{usdImaging => usdImagingGL}/engine.h (99%) rename pxr/usdImaging/lib/{usdImaging => usdImagingGL}/gl.cpp (90%) rename pxr/usdImaging/lib/{usdImaging => usdImagingGL}/gl.h (96%) rename pxr/usdImaging/lib/{usdImaging => usdImagingGL}/hdEngine.cpp (87%) rename pxr/usdImaging/lib/{usdImaging => usdImagingGL}/hdEngine.h (82%) rename pxr/usdImaging/lib/{usdImaging => usdImagingGL}/module.cpp (100%) rename pxr/usdImaging/lib/{usdImaging => usdImagingGL}/moduleDeps.cpp (93%) rename pxr/usdImaging/lib/{usdImaging => usdImagingGL}/refEngine.cpp (95%) rename pxr/usdImaging/lib/{usdImaging => usdImagingGL}/refEngine.h (96%) rename pxr/usdImaging/lib/{usdImaging => usdImagingGL}/taskDelegate.cpp (84%) rename pxr/usdImaging/lib/{usdImaging => usdImagingGL}/taskDelegate.h (76%) rename pxr/usdImaging/lib/{usdImaging/testenv/testUsdImagingBasicDrawing.cpp => usdImagingGL/testenv/testUsdImagingGLBasicDrawing.cpp} (90%) rename pxr/usdImaging/lib/{usdImaging => usdImagingGL}/unitTestGLDrawing.cpp (87%) rename pxr/usdImaging/lib/{usdImaging => usdImagingGL}/unitTestGLDrawing.h (87%) rename pxr/usdImaging/lib/{usdImaging => usdImagingGL}/wrapGL.cpp (99%) diff --git a/pxr/usdImaging/lib/CMakeLists.txt b/pxr/usdImaging/lib/CMakeLists.txt index 1f0a65257e..58af152827 100644 --- a/pxr/usdImaging/lib/CMakeLists.txt +++ b/pxr/usdImaging/lib/CMakeLists.txt @@ -1,5 +1,6 @@ set(DIRS usdImaging + usdImagingGL usdviewq ) diff --git a/pxr/usdImaging/lib/usdImaging/CMakeLists.txt b/pxr/usdImaging/lib/usdImaging/CMakeLists.txt index 2bc092d9b4..ef8c26bebf 100644 --- a/pxr/usdImaging/lib/usdImaging/CMakeLists.txt +++ b/pxr/usdImaging/lib/usdImaging/CMakeLists.txt @@ -45,12 +45,8 @@ pxr_shared_library(usdImaging adapterRegistry debugCodes delegate - engine - gl - hdEngine inheritedCache instancerContext - refEngine shaderAdapter tokens valueCache @@ -72,40 +68,7 @@ pxr_shared_library(usdImaging PUBLIC_HEADERS version.h - PRIVATE_CLASSES - defaultTaskDelegate - - PRIVATE_HEADERS - unitTestGLDrawing.h - - CPPFILES - moduleDeps.cpp - - PYMODULE_CPPFILES - module.cpp - wrapGL.cpp - - PYTHON_FILES - __init__.py - RESOURCE_FILES plugInfo.json ) -if (QT4_FOUND) - pxr_build_test(testUsdImagingBasicDrawing - LIBRARIES - hd - glf - glfq - usd - usdUtils - usdImaging - sdf - Qt4::QtCore - Qt4::QtOpenGL - CPPFILES - unitTestGLDrawing.cpp - testenv/testUsdImagingBasicDrawing.cpp - ) -endif() diff --git a/pxr/usdImaging/lib/usdImagingGL/CMakeLists.txt b/pxr/usdImaging/lib/usdImagingGL/CMakeLists.txt new file mode 100644 index 0000000000..2996797426 --- /dev/null +++ b/pxr/usdImaging/lib/usdImagingGL/CMakeLists.txt @@ -0,0 +1,87 @@ +set(PXR_PREFIX pxr/usdImagingGL) +set(PXR_PACKAGE usdImagingGL) + +# Note: both python include directives are included for compatibility. +pxr_shared_library(usdImagingGL + LIBRARIES + gf + tf + plug + tracelite + vt + work + garch + glf + hd + hdx + pxOsd + sdf + usd + usdGeom + usdShade + usdHydra + usdImaging + ar + ${Boost_PYTHON_LIBRARY} + ${PYTHON_LIBRARY} + ${OPENGL_gl_LIBRARY} + ${OPENGL_glu_LIBRARY} + ${GLEW_LIBRARY} + ${TBB_tbb_LIBRARY} + ${TBB_tbbmalloc_LIBRARY} + + INCLUDE_DIRS + ${PYTHON_INCLUDE_PATH} + ${PYTHON_INCLUDE_DIRS} + ${OPENGL_INCLUDE_DIR} + ${GLEW_INCLUDE_DIR} + ${TBB_INCLUDE_DIRS} + + PUBLIC_CLASSES + engine + gl + hdEngine + refEngine + taskDelegate + + PUBLIC_HEADERS + version.h + + PRIVATE_CLASSES + defaultTaskDelegate + + PRIVATE_HEADERS + unitTestGLDrawing.h + + CPPFILES + moduleDeps.cpp + + PYMODULE_CPPFILES + module.cpp + wrapGL.cpp + + PYTHON_FILES + __init__.py + + RESOURCE_FILES + plugInfo.json +) + +if (QT4_FOUND) + pxr_build_test(testUsdImagingGLBasicDrawing + LIBRARIES + hd + glf + glfq + usd + usdUtils + usdImaging + usdImagingGL + sdf + Qt4::QtCore + Qt4::QtOpenGL + CPPFILES + unitTestGLDrawing.cpp + testenv/testUsdImagingBasicDrawing.cpp + ) +endif() diff --git a/pxr/usdImaging/lib/usdImaging/__init__.py b/pxr/usdImaging/lib/usdImagingGL/__init__.py similarity index 92% rename from pxr/usdImaging/lib/usdImaging/__init__.py rename to pxr/usdImaging/lib/usdImagingGL/__init__.py index 606e0e54c4..b832e57e3e 100644 --- a/pxr/usdImaging/lib/usdImaging/__init__.py +++ b/pxr/usdImaging/lib/usdImagingGL/__init__.py @@ -21,10 +21,10 @@ # KIND, either express or implied. See the Apache License for the specific # language governing permissions and limitations under the Apache License. # -from . import _usdImaging +from . import _usdImagingGL from pxr import Tf -Tf.PrepareModule(_usdImaging, locals()) -del _usdImaging, Tf +Tf.PrepareModule(_usdImagingGL, locals()) +del _usdImagingGL, Tf try: from . import __DOC diff --git a/pxr/usdImaging/lib/usdImaging/defaultTaskDelegate.cpp b/pxr/usdImaging/lib/usdImagingGL/defaultTaskDelegate.cpp similarity index 89% rename from pxr/usdImaging/lib/usdImaging/defaultTaskDelegate.cpp rename to pxr/usdImaging/lib/usdImagingGL/defaultTaskDelegate.cpp index 0d3f5b81c0..dd55c33a42 100644 --- a/pxr/usdImaging/lib/usdImaging/defaultTaskDelegate.cpp +++ b/pxr/usdImaging/lib/usdImagingGL/defaultTaskDelegate.cpp @@ -21,7 +21,7 @@ // KIND, either express or implied. See the Apache License for the specific // language governing permissions and limitations under the Apache License. // -#include "pxr/usdImaging/usdImaging/defaultTaskDelegate.h" +#include "pxr/usdImaging/usdImagingGL/defaultTaskDelegate.h" #include "pxr/imaging/hd/version.h" #include "pxr/imaging/hd/tokens.h" @@ -54,21 +54,21 @@ TF_DEFINE_PRIVATE_TOKENS( ); static bool -_ShouldEnableLighting(UsdImagingEngine::RenderParams params) +_ShouldEnableLighting(UsdImagingGLEngine::RenderParams params) { switch(params.drawMode) { - case UsdImagingEngine::DRAW_GEOM_ONLY: - case UsdImagingEngine::DRAW_POINTS: + case UsdImagingGLEngine::DRAW_GEOM_ONLY: + case UsdImagingGLEngine::DRAW_POINTS: return false; default: return params.enableLighting and not params.enableIdRender; } } -UsdImaging_DefaultTaskDelegate::UsdImaging_DefaultTaskDelegate( +UsdImagingGL_DefaultTaskDelegate::UsdImagingGL_DefaultTaskDelegate( HdRenderIndexSharedPtr const& parentIndex, SdfPath const& delegateID) - : UsdImagingTaskDelegate(parentIndex, delegateID) + : UsdImagingGLTaskDelegate(parentIndex, delegateID) , _viewport(0,0,1,1) , _selectionColor(1,1,0,1) { @@ -148,7 +148,7 @@ UsdImaging_DefaultTaskDelegate::UsdImaging_DefaultTaskDelegate( _idRenderTaskId); } -UsdImaging_DefaultTaskDelegate::~UsdImaging_DefaultTaskDelegate() +UsdImagingGL_DefaultTaskDelegate::~UsdImagingGL_DefaultTaskDelegate() { // remove the render graph entities from the renderIndex HdRenderIndex &renderIndex = GetRenderIndex(); @@ -166,13 +166,13 @@ UsdImaging_DefaultTaskDelegate::~UsdImaging_DefaultTaskDelegate() /*virtual*/ HdRprimCollection const& -UsdImaging_DefaultTaskDelegate::GetRprimCollection() const +UsdImagingGL_DefaultTaskDelegate::GetRprimCollection() const { return _rprims; } void -UsdImaging_DefaultTaskDelegate::_InsertRenderTask(SdfPath const &id) +UsdImagingGL_DefaultTaskDelegate::_InsertRenderTask(SdfPath const &id) { GetRenderIndex().InsertTask(this, id); _ValueCache &cache = _valueCacheMap[id]; @@ -188,8 +188,8 @@ UsdImaging_DefaultTaskDelegate::_InsertRenderTask(SdfPath const &id) } HdTaskSharedPtrVector -UsdImaging_DefaultTaskDelegate::GetRenderTasks( - UsdImagingEngine::RenderParams const ¶ms) +UsdImagingGL_DefaultTaskDelegate::GetRenderTasks( + UsdImagingGLEngine::RenderParams const ¶ms) { HdTaskSharedPtrVector tasks; // XXX: we can cache this vector tasks.reserve(3); @@ -215,24 +215,24 @@ UsdImaging_DefaultTaskDelegate::GetRenderTasks( } void -UsdImaging_DefaultTaskDelegate::SetCollectionAndRenderParams( +UsdImagingGL_DefaultTaskDelegate::SetCollectionAndRenderParams( const SdfPathVector &roots, - const UsdImagingEngine::RenderParams ¶ms) + const UsdImagingGLEngine::RenderParams ¶ms) { // choose repr TfToken repr = HdTokens->smoothHull; bool refined = params.complexity > 1.0; - if (params.drawMode == UsdImagingEngine::DRAW_GEOM_FLAT or - params.drawMode == UsdImagingEngine::DRAW_SHADED_FLAT) { + if (params.drawMode == UsdImagingGLEngine::DRAW_GEOM_FLAT or + params.drawMode == UsdImagingGLEngine::DRAW_SHADED_FLAT) { repr = HdTokens->hull; - } else if (params.drawMode == UsdImagingEngine::DRAW_WIREFRAME_ON_SURFACE) { + } else if (params.drawMode == UsdImagingGLEngine::DRAW_WIREFRAME_ON_SURFACE) { if (refined) { repr = HdTokens->refinedWireOnSurf; } else { repr = HdTokens->wireOnSurf; } - } else if (params.drawMode == UsdImagingEngine::DRAW_WIREFRAME) { + } else if (params.drawMode == UsdImagingGLEngine::DRAW_WIREFRAME) { if (refined) { repr = HdTokens->refinedWire; } else { @@ -262,7 +262,7 @@ UsdImaging_DefaultTaskDelegate::SetCollectionAndRenderParams( _renderTaskId, _idRenderTaskId); - UsdImagingEngine::RenderParams &oldParams = params.enableIdRender + UsdImagingGLEngine::RenderParams &oldParams = params.enableIdRender ? _idRenderParams : _renderParams; SdfPath const &taskId = params.enableIdRender @@ -276,7 +276,7 @@ UsdImaging_DefaultTaskDelegate::SetCollectionAndRenderParams( } void -UsdImaging_DefaultTaskDelegate::_UpdateCollection( +UsdImagingGL_DefaultTaskDelegate::_UpdateCollection( HdRprimCollection *rprims, TfToken const &colName, TfToken const &reprName, SdfPathVector const &roots, @@ -326,9 +326,9 @@ UsdImaging_DefaultTaskDelegate::_UpdateCollection( } void -UsdImaging_DefaultTaskDelegate::_UpdateRenderParams( - UsdImagingEngine::RenderParams const &renderParams, - UsdImagingEngine::RenderParams const &oldRenderParams, +UsdImagingGL_DefaultTaskDelegate::_UpdateRenderParams( + UsdImagingGLEngine::RenderParams const &renderParams, + UsdImagingGLEngine::RenderParams const &oldRenderParams, SdfPath const &renderTaskId) { static const HdCullStyle USD_2_HD_CULL_STYLE[] = @@ -340,7 +340,7 @@ UsdImaging_DefaultTaskDelegate::_UpdateRenderParams( }; static_assert(((sizeof(USD_2_HD_CULL_STYLE) / sizeof(USD_2_HD_CULL_STYLE[0])) - == UsdImagingEngine::CULL_STYLE_COUNT),"enum size mismatch"); + == UsdImagingGLEngine::CULL_STYLE_COUNT),"enum size mismatch"); HdxRenderTaskParams params = _GetValue(renderTaskId, HdTokens->params); @@ -403,7 +403,7 @@ UsdImaging_DefaultTaskDelegate::_UpdateRenderParams( } void -UsdImaging_DefaultTaskDelegate::SetLightingState( +UsdImagingGL_DefaultTaskDelegate::SetLightingState( const GlfSimpleLightingContextPtr &src) { if (not TF_VERIFY(src)) return; @@ -467,7 +467,7 @@ UsdImaging_DefaultTaskDelegate::SetLightingState( } void -UsdImaging_DefaultTaskDelegate::SetBypassedLightingState( +UsdImagingGL_DefaultTaskDelegate::SetBypassedLightingState( const GlfSimpleLightingContextPtr &src) { HdxSimpleLightBypassTaskParams params; @@ -484,7 +484,7 @@ UsdImaging_DefaultTaskDelegate::SetBypassedLightingState( } void -UsdImaging_DefaultTaskDelegate::SetCameraState( +UsdImagingGL_DefaultTaskDelegate::SetCameraState( const GfMatrix4d& viewMatrix, const GfMatrix4d& projectionMatrix, const GfVec4d& viewport) @@ -523,7 +523,7 @@ UsdImaging_DefaultTaskDelegate::SetCameraState( } void -UsdImaging_DefaultTaskDelegate::SetSelectionColor(GfVec4f const& color) +UsdImagingGL_DefaultTaskDelegate::SetSelectionColor(GfVec4f const& color) { if (_selectionColor != color) { _selectionColor = color; @@ -540,7 +540,7 @@ UsdImaging_DefaultTaskDelegate::SetSelectionColor(GfVec4f const& color) /* virtual */ VtValue -UsdImaging_DefaultTaskDelegate::Get(SdfPath const& id, TfToken const& key) +UsdImagingGL_DefaultTaskDelegate::Get(SdfPath const& id, TfToken const& key) { _ValueCache *vcache = TfMapLookupPtr(_valueCacheMap, id); VtValue ret; @@ -554,15 +554,15 @@ UsdImaging_DefaultTaskDelegate::Get(SdfPath const& id, TfToken const& key) /* virtual */ bool -UsdImaging_DefaultTaskDelegate::CanRender( - const UsdImagingEngine::RenderParams ¶ms) +UsdImagingGL_DefaultTaskDelegate::CanRender( + const UsdImagingGLEngine::RenderParams ¶ms) { return true; } /* virtual */ bool -UsdImaging_DefaultTaskDelegate::IsConverged() const +UsdImagingGL_DefaultTaskDelegate::IsConverged() const { // default task always converges. return true; @@ -570,10 +570,10 @@ UsdImaging_DefaultTaskDelegate::IsConverged() const /* virtual */ bool -UsdImaging_DefaultTaskDelegate::IsEnabled(TfToken const& option) const +UsdImagingGL_DefaultTaskDelegate::IsEnabled(TfToken const& option) const { if (option == HdxOptionTokens->taskSetAlphaToCoverage) { - // UsdImagingHdEngine enables ALPHA_TO_COVERAGE as needed. + // UsdImagingGLHdEngine enables ALPHA_TO_COVERAGE as needed. return true; } return HdSceneDelegate::IsEnabled(option); @@ -581,7 +581,7 @@ UsdImaging_DefaultTaskDelegate::IsEnabled(TfToken const& option) const /* virtual */ std::vector -UsdImaging_DefaultTaskDelegate::GetClipPlanes(SdfPath const& cameraId) +UsdImagingGL_DefaultTaskDelegate::GetClipPlanes(SdfPath const& cameraId) { return _clipPlanes; } diff --git a/pxr/usdImaging/lib/usdImaging/defaultTaskDelegate.h b/pxr/usdImaging/lib/usdImagingGL/defaultTaskDelegate.h similarity index 85% rename from pxr/usdImaging/lib/usdImaging/defaultTaskDelegate.h rename to pxr/usdImaging/lib/usdImagingGL/defaultTaskDelegate.h index c05cd21db0..ca67b45d15 100644 --- a/pxr/usdImaging/lib/usdImaging/defaultTaskDelegate.h +++ b/pxr/usdImaging/lib/usdImagingGL/defaultTaskDelegate.h @@ -23,8 +23,8 @@ // #pragma once -#include "pxr/usdImaging/usdImaging/engine.h" -#include "pxr/usdImaging/usdImaging/taskDelegate.h" +#include "pxr/usdImaging/usdImagingGL/engine.h" +#include "pxr/usdImaging/usdImagingGL/taskDelegate.h" #include "pxr/imaging/hd/version.h" #include "pxr/imaging/hd/rprimCollection.h" @@ -33,23 +33,23 @@ // --------------------------------------------------------------------------- // Task Delegate for built-in render graph -class UsdImaging_DefaultTaskDelegate : public UsdImagingTaskDelegate { +class UsdImagingGL_DefaultTaskDelegate : public UsdImagingGLTaskDelegate { public: - UsdImaging_DefaultTaskDelegate(HdRenderIndexSharedPtr const&renderIndex, + UsdImagingGL_DefaultTaskDelegate(HdRenderIndexSharedPtr const&renderIndex, SdfPath const& delegateID); - ~UsdImaging_DefaultTaskDelegate(); + ~UsdImagingGL_DefaultTaskDelegate(); // HdSceneDelegate interface virtual VtValue Get(SdfPath const& id, TfToken const& key); // returns tasks in the render graph for the given params virtual HdTaskSharedPtrVector GetRenderTasks( - UsdImagingEngine::RenderParams const ¶ms); + UsdImagingGLEngine::RenderParams const ¶ms); // update roots and RenderParam virtual void SetCollectionAndRenderParams( const SdfPathVector &roots, - const UsdImagingEngine::RenderParams ¶ms); + const UsdImagingGLEngine::RenderParams ¶ms); virtual HdRprimCollection const& GetRprimCollection() const; @@ -70,7 +70,7 @@ class UsdImaging_DefaultTaskDelegate : public UsdImagingTaskDelegate { void SetSelectionColor(GfVec4f const& color); // always returns true for the default task - virtual bool CanRender(const UsdImagingEngine::RenderParams ¶ms); + virtual bool CanRender(const UsdImagingGLEngine::RenderParams ¶ms); // returns true if the image is converged. virtual bool IsConverged() const; @@ -93,8 +93,8 @@ class UsdImaging_DefaultTaskDelegate : public UsdImagingTaskDelegate { SdfPathVector const &roots, SdfPath const &renderTaskId, SdfPath const &idRenderTaskId); - void _UpdateRenderParams(UsdImagingEngine::RenderParams const &renderParams, - UsdImagingEngine::RenderParams const &oldRenderParams, + void _UpdateRenderParams(UsdImagingGLEngine::RenderParams const &renderParams, + UsdImagingGLEngine::RenderParams const &oldRenderParams, SdfPath const &renderTaskId); template @@ -110,8 +110,8 @@ class UsdImaging_DefaultTaskDelegate : public UsdImagingTaskDelegate { private: HdRprimCollection _rprims; - UsdImagingEngine::RenderParams _renderParams; - UsdImagingEngine::RenderParams _idRenderParams; + UsdImagingGLEngine::RenderParams _renderParams; + UsdImagingGLEngine::RenderParams _idRenderParams; GfVec4d _viewport; SdfPath _rootId; diff --git a/pxr/usdImaging/lib/usdImaging/engine.cpp b/pxr/usdImaging/lib/usdImagingGL/engine.cpp similarity index 93% rename from pxr/usdImaging/lib/usdImaging/engine.cpp rename to pxr/usdImaging/lib/usdImagingGL/engine.cpp index c86ab250c4..83b4bc833d 100644 --- a/pxr/usdImaging/lib/usdImaging/engine.cpp +++ b/pxr/usdImaging/lib/usdImagingGL/engine.cpp @@ -22,7 +22,7 @@ // language governing permissions and limitations under the Apache License. // #include "pxr/imaging/glf/glew.h" -#include "pxr/usdImaging/usdImaging/engine.h" +#include "pxr/usdImaging/usdImagingGL/engine.h" #include "pxr/imaging/glf/diagnostic.h" #include "pxr/imaging/glf/glContext.h" @@ -44,11 +44,11 @@ struct _HitData { typedef TfHashMap< int32_t, _HitData > _HitDataById; -UsdImagingEngine::~UsdImagingEngine() { /*nothing*/ } +UsdImagingGLEngine::~UsdImagingGLEngine() { /*nothing*/ } /*virtual*/ void -UsdImagingEngine::SetCameraState(const GfMatrix4d& viewMatrix, +UsdImagingGLEngine::SetCameraState(const GfMatrix4d& viewMatrix, const GfMatrix4d& projectionMatrix, const GfVec4d& viewport) { @@ -56,7 +56,7 @@ UsdImagingEngine::SetCameraState(const GfMatrix4d& viewMatrix, } void -UsdImagingEngine::SetCameraStateFromOpenGL() +UsdImagingGLEngine::SetCameraStateFromOpenGL() { GfMatrix4d viewMatrix, projectionMatrix; GfVec4d viewport; @@ -69,76 +69,76 @@ UsdImagingEngine::SetCameraStateFromOpenGL() /* virtual */ void -UsdImagingEngine::SetLightingStateFromOpenGL() +UsdImagingGLEngine::SetLightingStateFromOpenGL() { // By default, do nothing. } /* virtual */ void -UsdImagingEngine::SetLightingState(GlfSimpleLightingContextPtr const &src) +UsdImagingGLEngine::SetLightingState(GlfSimpleLightingContextPtr const &src) { // By default, do nothing. } /* virtual */ void -UsdImagingEngine::SetRootTransform(GfMatrix4d const& xf) +UsdImagingGLEngine::SetRootTransform(GfMatrix4d const& xf) { // By default, do nothing. } /* virtual */ void -UsdImagingEngine::SetRootVisibility(bool isVisible) +UsdImagingGLEngine::SetRootVisibility(bool isVisible) { // By default, do nothing. } /* virtual */ void -UsdImagingEngine::SetSelected(SdfPathVector const& paths) +UsdImagingGLEngine::SetSelected(SdfPathVector const& paths) { // By default, do nothing. } /* virtual */ void -UsdImagingEngine::ClearSelected() +UsdImagingGLEngine::ClearSelected() { // By default, do nothing. } /* virtual */ void -UsdImagingEngine::AddSelected(SdfPath const &path, int instanceIndex) +UsdImagingGLEngine::AddSelected(SdfPath const &path, int instanceIndex) { // By default, do nothing. } /*virtual*/ void -UsdImagingEngine::SetSelectionColor(GfVec4f const& color) +UsdImagingGLEngine::SetSelectionColor(GfVec4f const& color) { // By default, do nothing. } /* virtual */ void -UsdImagingEngine::PrepareBatch(const UsdPrim& root, RenderParams params) +UsdImagingGLEngine::PrepareBatch(const UsdPrim& root, RenderParams params) { // By default, do nothing. } /* virtual */ void -UsdImagingEngine::RenderBatch(const SdfPathVector& paths, RenderParams params) +UsdImagingGLEngine::RenderBatch(const SdfPathVector& paths, RenderParams params) { // By default, do nothing. } bool -UsdImagingEngine::TestIntersection( +UsdImagingGLEngine::TestIntersection( const GfMatrix4d &viewMatrix, const GfMatrix4d &projectionMatrix, const GfMatrix4d &worldToLocalSpace, @@ -359,7 +359,7 @@ _pow2roundup (uint32_t x) } bool -UsdImagingEngine::TestIntersectionBatch( +UsdImagingGLEngine::TestIntersectionBatch( const GfMatrix4d &viewMatrix, const GfMatrix4d &projectionMatrix, const GfMatrix4d &worldToLocalSpace, @@ -609,7 +609,7 @@ UsdImagingEngine::TestIntersectionBatch( /* virtual */ SdfPath -UsdImagingEngine::GetPrimPathFromPrimIdColor(GfVec4i const &/*primIdColor*/, +UsdImagingGLEngine::GetPrimPathFromPrimIdColor(GfVec4i const &/*primIdColor*/, GfVec4i const &/*instanceIdColor*/, int * /*instanceIndexOut*/) { @@ -618,7 +618,7 @@ UsdImagingEngine::GetPrimPathFromPrimIdColor(GfVec4i const &/*primIdColor*/, /* virtual */ SdfPath -UsdImagingEngine::GetPrimPathFromInstanceIndex( +UsdImagingGLEngine::GetPrimPathFromInstanceIndex( SdfPath const& protoPrimPath, int instanceIndex, int *absoluteInstanceIndex, @@ -629,7 +629,7 @@ UsdImagingEngine::GetPrimPathFromInstanceIndex( /* virtual */ bool -UsdImagingEngine::IsConverged() const +UsdImagingGLEngine::IsConverged() const { // always converges by default. return true; @@ -637,21 +637,21 @@ UsdImagingEngine::IsConverged() const /* virtual */ std::vector -UsdImagingEngine::GetRenderGraphPlugins() +UsdImagingGLEngine::GetRenderGraphPlugins() { return std::vector(); } /* virtual */ bool -UsdImagingEngine::SetRenderGraphPlugin(TfType const &type) +UsdImagingGLEngine::SetRenderGraphPlugin(TfType const &type) { return false; } /* virtual */ VtDictionary -UsdImagingEngine::GetResourceAllocation() const +UsdImagingGLEngine::GetResourceAllocation() const { return VtDictionary(); } diff --git a/pxr/usdImaging/lib/usdImaging/engine.h b/pxr/usdImaging/lib/usdImagingGL/engine.h similarity index 99% rename from pxr/usdImaging/lib/usdImaging/engine.h rename to pxr/usdImaging/lib/usdImagingGL/engine.h index 25964fa30b..59fe50dced 100644 --- a/pxr/usdImaging/lib/usdImaging/engine.h +++ b/pxr/usdImaging/lib/usdImagingGL/engine.h @@ -48,13 +48,13 @@ typedef boost::shared_ptr GlfGLContextSharedPtr; TF_DECLARE_WEAK_AND_REF_PTRS(GlfDrawTarget); TF_DECLARE_WEAK_PTRS(GlfSimpleLightingContext); -/// \class UsdImagingEngine +/// \class UsdImagingGLEngine /// /// Interface class for render engines. /// -class UsdImagingEngine : private boost::noncopyable { +class UsdImagingGLEngine : private boost::noncopyable { public: - virtual ~UsdImagingEngine(); + virtual ~UsdImagingGLEngine(); enum DrawMode { DRAW_POINTS, diff --git a/pxr/usdImaging/lib/usdImaging/gl.cpp b/pxr/usdImaging/lib/usdImagingGL/gl.cpp similarity index 90% rename from pxr/usdImaging/lib/usdImaging/gl.cpp rename to pxr/usdImaging/lib/usdImagingGL/gl.cpp index d2fab606c2..2b1e2fddd0 100644 --- a/pxr/usdImaging/lib/usdImaging/gl.cpp +++ b/pxr/usdImaging/lib/usdImagingGL/gl.cpp @@ -23,9 +23,9 @@ // #include "pxr/imaging/glf/glew.h" -#include "pxr/usdImaging/usdImaging/gl.h" -#include "pxr/usdImaging/usdImaging/hdEngine.h" -#include "pxr/usdImaging/usdImaging/refEngine.h" +#include "pxr/usdImaging/usdImagingGL/gl.h" +#include "pxr/usdImaging/usdImagingGL/hdEngine.h" +#include "pxr/usdImaging/usdImagingGL/refEngine.h" #include "pxr/imaging/hd/renderContextCaps.h" @@ -68,25 +68,25 @@ UsdImagingGL::IsEnabledHydra() } static -UsdImagingEngine* _InitEngine(const SdfPath& rootPath, +UsdImagingGLEngine* _InitEngine(const SdfPath& rootPath, const SdfPathVector& excludedPaths, const SdfPathVector& invisedPaths, const SdfPath& sharedId = SdfPath::AbsoluteRootPath(), - const UsdImagingEngineSharedPtr& sharedEngine = - UsdImagingEngineSharedPtr()) + const UsdImagingGLEngineSharedPtr& sharedEngine = + UsdImagingGLEngineSharedPtr()) { if (UsdImagingGL::IsEnabledHydra()) { - return new UsdImagingHdEngine(rootPath, excludedPaths, invisedPaths, + return new UsdImagingGLHdEngine(rootPath, excludedPaths, invisedPaths, sharedId, - boost::dynamic_pointer_cast(sharedEngine)); + boost::dynamic_pointer_cast(sharedEngine)); } else { // In the refEngine, both excluded paths and invised paths are treated // the same way. SdfPathVector pathsToExclude = excludedPaths; pathsToExclude.insert(pathsToExclude.end(), invisedPaths.begin(), invisedPaths.end()); - return new UsdImagingRefEngine(pathsToExclude); + return new UsdImagingGLRefEngine(pathsToExclude); } } @@ -103,7 +103,7 @@ UsdImagingGL::UsdImagingGL(const SdfPath& rootPath, const UsdImagingGLSharedPtr& sharedImaging) { _engine.reset(_InitEngine(rootPath, excludedPaths, invisedPaths, sharedId, - (sharedImaging ? sharedImaging->_engine : UsdImagingEngineSharedPtr()))); + (sharedImaging ? sharedImaging->_engine : UsdImagingGLEngineSharedPtr()))); } UsdImagingGL::~UsdImagingGL() @@ -139,17 +139,17 @@ UsdImagingGL::PrepareBatch( // Batching is only supported if the Hydra engine is enabled, and if // it is then all of the UsdImagingGL instances we've been given - // must use a UsdImagingHdEngine engine. So we explicitly call the + // must use a UsdImagingGLHdEngine engine. So we explicitly call the // the static method on that class. - UsdImagingHdEngineSharedPtrVector hdEngines; + UsdImagingGLHdEngineSharedPtrVector hdEngines; hdEngines.reserve(renderers.size()); TF_FOR_ALL(it, renderers) { hdEngines.push_back( - boost::dynamic_pointer_cast( + boost::dynamic_pointer_cast( (*it)->_engine)); } - UsdImagingHdEngine::PrepareBatch(hdEngines, rootPrims, times, params); + UsdImagingGLHdEngine::PrepareBatch(hdEngines, rootPrims, times, params); } /*virtual*/ diff --git a/pxr/usdImaging/lib/usdImaging/gl.h b/pxr/usdImaging/lib/usdImagingGL/gl.h similarity index 96% rename from pxr/usdImaging/lib/usdImaging/gl.h rename to pxr/usdImaging/lib/usdImagingGL/gl.h index 214acb852d..779b87dd28 100644 --- a/pxr/usdImaging/lib/usdImaging/gl.h +++ b/pxr/usdImaging/lib/usdImagingGL/gl.h @@ -26,7 +26,7 @@ #pragma once -#include "pxr/usdImaging/usdImaging/engine.h" +#include "pxr/usdImaging/usdImagingGL/engine.h" #include @@ -35,7 +35,7 @@ class SdfPath; typedef std::vector SdfPathVector; typedef std::vector UsdPrimVector; -typedef boost::shared_ptr UsdImagingEngineSharedPtr; +typedef boost::shared_ptr UsdImagingGLEngineSharedPtr; typedef boost::shared_ptr UsdImagingGLSharedPtr; typedef std::vector UsdImagingGLSharedPtrVector; @@ -52,7 +52,7 @@ typedef std::vector UsdImagingGLSharedPtrVector; /// /// So, to disable Hd rendering for testing purposes, set HD_ENABLED to "0" /// -class UsdImagingGL : public UsdImagingEngine { +class UsdImagingGL : public UsdImagingGLEngine { public: /// Returns true if Hydra is enabled for GL drawing. @@ -169,6 +169,6 @@ class UsdImagingGL : public UsdImagingEngine { virtual VtDictionary GetResourceAllocation() const; private: - UsdImagingEngineSharedPtr _engine; + UsdImagingGLEngineSharedPtr _engine; }; diff --git a/pxr/usdImaging/lib/usdImaging/hdEngine.cpp b/pxr/usdImaging/lib/usdImagingGL/hdEngine.cpp similarity index 87% rename from pxr/usdImaging/lib/usdImaging/hdEngine.cpp rename to pxr/usdImaging/lib/usdImagingGL/hdEngine.cpp index da2a059847..e973d1f4c0 100644 --- a/pxr/usdImaging/lib/usdImaging/hdEngine.cpp +++ b/pxr/usdImaging/lib/usdImagingGL/hdEngine.cpp @@ -22,10 +22,10 @@ // language governing permissions and limitations under the Apache License. // #include "pxr/imaging/glf/glew.h" -#include "pxr/usdImaging/usdImaging/hdEngine.h" +#include "pxr/usdImaging/usdImagingGL/hdEngine.h" -#include "pxr/usdImaging/usdImaging/defaultTaskDelegate.h" -#include "pxr/usdImaging/usdImaging/taskDelegate.h" +#include "pxr/usdImaging/usdImagingGL/defaultTaskDelegate.h" +#include "pxr/usdImaging/usdImagingGL/taskDelegate.h" #include "pxr/imaging/hd/version.h" #include "pxr/imaging/hd/tokens.h" @@ -48,19 +48,19 @@ #include "pxr/imaging/glf/info.h" #include "pxr/imaging/glf/simpleLightingContext.h" -UsdImagingHdEngine::UsdImagingHdEngine( +UsdImagingGLHdEngine::UsdImagingGLHdEngine( const SdfPath& rootPath, const SdfPathVector& excludedPrimPaths, const SdfPathVector& invisedPrimPaths, const SdfPath& sharedId, - const UsdImagingHdEngineSharedPtr& sharedEngine) + const UsdImagingGLHdEngineSharedPtr& sharedEngine) : _renderIndex(sharedEngine ? sharedEngine->GetRenderIndex() : HdRenderIndexSharedPtr(new HdRenderIndex())) , _selTracker(new HdxSelectionTracker) , _intersector(new HdxIntersector(_renderIndex)) , _delegate(_renderIndex, sharedId) - , _defaultTaskDelegate(new UsdImaging_DefaultTaskDelegate( + , _defaultTaskDelegate(new UsdImagingGL_DefaultTaskDelegate( _renderIndex, sharedId)) , _pluginDiscovered(false) , _rootPath(rootPath) @@ -70,18 +70,18 @@ UsdImagingHdEngine::UsdImagingHdEngine( { } -UsdImagingHdEngine::~UsdImagingHdEngine() +UsdImagingGLHdEngine::~UsdImagingGLHdEngine() { } HdRenderIndexSharedPtr -UsdImagingHdEngine::GetRenderIndex() const +UsdImagingGLHdEngine::GetRenderIndex() const { return _renderIndex; } void -UsdImagingHdEngine::InvalidateBuffers() +UsdImagingGLHdEngine::InvalidateBuffers() { //_delegate.GetRenderIndex().GetChangeTracker().MarkPrimDirty(path, flag); } @@ -123,7 +123,7 @@ _GetRefineLevel(float c) } bool -UsdImagingHdEngine::_CanPrepareBatch(const UsdPrim& root, +UsdImagingGLHdEngine::_CanPrepareBatch(const UsdPrim& root, const RenderParams& params) { HD_TRACE_FUNCTION(); @@ -143,7 +143,7 @@ UsdImagingHdEngine::_CanPrepareBatch(const UsdPrim& root, } void -UsdImagingHdEngine::_PreSetTime(const UsdPrim& root, const RenderParams& params) +UsdImagingGLHdEngine::_PreSetTime(const UsdPrim& root, const RenderParams& params) { HD_TRACE_FUNCTION(); @@ -153,7 +153,7 @@ UsdImagingHdEngine::_PreSetTime(const UsdPrim& root, const RenderParams& params) } void -UsdImagingHdEngine::_PostSetTime(const UsdPrim& root, const RenderParams& params) +UsdImagingGLHdEngine::_PostSetTime(const UsdPrim& root, const RenderParams& params) { HD_TRACE_FUNCTION(); if (_isPopulated) @@ -165,8 +165,8 @@ UsdImagingHdEngine::_PostSetTime(const UsdPrim& root, const RenderParams& params _delegate.SetRootCompensation(root.GetPath()); } -UsdImagingTaskDelegateSharedPtr -UsdImagingHdEngine::_GetTaskDelegate(const RenderParams ¶ms) const +UsdImagingGLTaskDelegateSharedPtr +UsdImagingGLHdEngine::_GetTaskDelegate(const RenderParams ¶ms) const { // if \p params can be handled by the plugin task, return it if (_currentPluginTaskDelegate) { @@ -182,7 +182,7 @@ UsdImagingHdEngine::_GetTaskDelegate(const RenderParams ¶ms) const /*virtual*/ void -UsdImagingHdEngine::PrepareBatch(const UsdPrim& root, RenderParams params) +UsdImagingGLHdEngine::PrepareBatch(const UsdPrim& root, RenderParams params) { HD_TRACE_FUNCTION(); @@ -203,8 +203,8 @@ UsdImagingHdEngine::PrepareBatch(const UsdPrim& root, RenderParams params) /* static */ void -UsdImagingHdEngine::PrepareBatch( - const UsdImagingHdEngineSharedPtrVector& engines, +UsdImagingGLHdEngine::PrepareBatch( + const UsdImagingGLHdEngineSharedPtrVector& engines, const UsdPrimVector& rootPrims, const std::vector& times, RenderParams params) @@ -230,7 +230,7 @@ UsdImagingHdEngine::PrepareBatch( } else { // Filter out all the engines that fail the error check. - UsdImagingHdEngineSharedPtrVector tmpEngines = engines; + UsdImagingGLHdEngineSharedPtrVector tmpEngines = engines; UsdPrimVector tmpRootPrims = rootPrims; std::vector tmpTimes = times; @@ -246,8 +246,8 @@ UsdImagingHdEngine::PrepareBatch( /* static */ void -UsdImagingHdEngine::_PrepareBatch( - const UsdImagingHdEngineSharedPtrVector& engines, +UsdImagingGLHdEngine::_PrepareBatch( + const UsdImagingGLHdEngineSharedPtrVector& engines, const UsdPrimVector& rootPrims, const std::vector& times, const RenderParams& params) @@ -260,7 +260,7 @@ UsdImagingHdEngine::_PrepareBatch( /*static */ void -UsdImagingHdEngine::_SetTimes(const UsdImagingHdEngineSharedPtrVector& engines, +UsdImagingGLHdEngine::_SetTimes(const UsdImagingGLHdEngineSharedPtrVector& engines, const UsdPrimVector& rootPrims, const std::vector& times, const RenderParams& params) @@ -284,7 +284,7 @@ UsdImagingHdEngine::_SetTimes(const UsdImagingHdEngineSharedPtrVector& engines, /* static */ void -UsdImagingHdEngine::_Populate(const UsdImagingHdEngineSharedPtrVector& engines, +UsdImagingGLHdEngine::_Populate(const UsdImagingGLHdEngineSharedPtrVector& engines, const UsdPrimVector& rootPrims) { HD_TRACE_FUNCTION(); @@ -322,7 +322,7 @@ UsdImagingHdEngine::_Populate(const UsdImagingHdEngineSharedPtrVector& engines, /*virtual*/ void -UsdImagingHdEngine::RenderBatch(const SdfPathVector& paths, RenderParams params) +UsdImagingGLHdEngine::RenderBatch(const SdfPathVector& paths, RenderParams params) { _GetTaskDelegate(params)->SetCollectionAndRenderParams( paths, params); @@ -332,7 +332,7 @@ UsdImagingHdEngine::RenderBatch(const SdfPathVector& paths, RenderParams params) /*virtual*/ void -UsdImagingHdEngine::Render(const UsdPrim& root, RenderParams params) +UsdImagingGLHdEngine::Render(const UsdPrim& root, RenderParams params) { PrepareBatch(root, params); @@ -346,7 +346,7 @@ UsdImagingHdEngine::Render(const UsdPrim& root, RenderParams params) } bool -UsdImagingHdEngine::TestIntersection( +UsdImagingGLHdEngine::TestIntersection( const GfMatrix4d &viewMatrix, const GfMatrix4d &projectionMatrix, const GfMatrix4d &worldToLocalSpace, @@ -405,7 +405,7 @@ UsdImagingHdEngine::TestIntersection( } bool -UsdImagingHdEngine::TestIntersectionBatch( +UsdImagingGLHdEngine::TestIntersectionBatch( const GfMatrix4d &viewMatrix, const GfMatrix4d &projectionMatrix, const GfMatrix4d &worldToLocalSpace, @@ -436,7 +436,7 @@ UsdImagingHdEngine::TestIntersectionBatch( }; static_assert(((sizeof(USD_2_HD_CULL_STYLE) / sizeof(USD_2_HD_CULL_STYLE[0])) - == UsdImagingEngine::CULL_STYLE_COUNT),"enum size mismatch"); + == UsdImagingGLEngine::CULL_STYLE_COUNT),"enum size mismatch"); HdxIntersector::Params qparams; qparams.viewMatrix = worldToLocalSpace * viewMatrix; @@ -475,7 +475,7 @@ UsdImagingHdEngine::TestIntersectionBatch( } void -UsdImagingHdEngine::Render(HdRenderIndex& index, RenderParams params) +UsdImagingGLHdEngine::Render(HdRenderIndex& index, RenderParams params) { // User is responsible for initalizing GL contenxt and glew if (not HdRenderContextCaps::GetInstance().SupportsHydra()) { @@ -551,7 +551,7 @@ UsdImagingHdEngine::Render(HdRenderIndex& index, RenderParams params) /*virtual*/ void -UsdImagingHdEngine::SetCameraState(const GfMatrix4d& viewMatrix, +UsdImagingGLHdEngine::SetCameraState(const GfMatrix4d& viewMatrix, const GfMatrix4d& projectionMatrix, const GfVec4d& viewport) { @@ -567,7 +567,7 @@ UsdImagingHdEngine::SetCameraState(const GfMatrix4d& viewMatrix, /*virtual*/ SdfPath -UsdImagingHdEngine::GetPrimPathFromPrimIdColor(GfVec4i const & primIdColor, +UsdImagingGLHdEngine::GetPrimPathFromPrimIdColor(GfVec4i const & primIdColor, GfVec4i const & instanceIdColor, int * instanceIndexOut) { @@ -577,7 +577,7 @@ UsdImagingHdEngine::GetPrimPathFromPrimIdColor(GfVec4i const & primIdColor, /* virtual */ SdfPath -UsdImagingHdEngine::GetPrimPathFromInstanceIndex(SdfPath const& protoPrimPath, +UsdImagingGLHdEngine::GetPrimPathFromInstanceIndex(SdfPath const& protoPrimPath, int instanceIndex, int *absoluteInstanceIndex, std::vector *instanceContext) @@ -589,7 +589,7 @@ UsdImagingHdEngine::GetPrimPathFromInstanceIndex(SdfPath const& protoPrimPath, /* virtual */ void -UsdImagingHdEngine::SetLightingStateFromOpenGL() +UsdImagingGLHdEngine::SetLightingStateFromOpenGL() { if (not _lightingContextForOpenGLState) { _lightingContextForOpenGLState = GlfSimpleLightingContext::New(); @@ -605,7 +605,7 @@ UsdImagingHdEngine::SetLightingStateFromOpenGL() /* virtual */ void -UsdImagingHdEngine::SetLightingState(GlfSimpleLightingContextPtr const &src) +UsdImagingGLHdEngine::SetLightingState(GlfSimpleLightingContextPtr const &src) { // leave all lighting plumbing work to the incoming lighting context. // XXX: this call will be replaced with SetLightingState() when Phd takes @@ -617,14 +617,14 @@ UsdImagingHdEngine::SetLightingState(GlfSimpleLightingContextPtr const &src) /* virtual */ void -UsdImagingHdEngine::SetRootTransform(GfMatrix4d const& xf) +UsdImagingGLHdEngine::SetRootTransform(GfMatrix4d const& xf) { _delegate.SetRootTransform(xf); } /* virtual */ void -UsdImagingHdEngine::SetRootVisibility(bool isVisible) +UsdImagingGLHdEngine::SetRootVisibility(bool isVisible) { _delegate.SetRootVisibility(isVisible); } @@ -632,7 +632,7 @@ UsdImagingHdEngine::SetRootVisibility(bool isVisible) /*virtual*/ void -UsdImagingHdEngine::SetSelected(SdfPathVector const& paths) +UsdImagingGLHdEngine::SetSelected(SdfPathVector const& paths) { // populate new selection HdxSelectionSharedPtr selection(new HdxSelection(&*_renderIndex)); @@ -648,7 +648,7 @@ UsdImagingHdEngine::SetSelected(SdfPathVector const& paths) /*virtual*/ void -UsdImagingHdEngine::ClearSelected() +UsdImagingGLHdEngine::ClearSelected() { HdxSelectionSharedPtr selection(new HdxSelection(&*_renderIndex)); _selTracker->SetSelection(selection); @@ -656,7 +656,7 @@ UsdImagingHdEngine::ClearSelected() /* virtual */ void -UsdImagingHdEngine::AddSelected(SdfPath const &path, int instanceIndex) +UsdImagingGLHdEngine::AddSelected(SdfPath const &path, int instanceIndex) { HdxSelectionSharedPtr selection = _selTracker->GetSelectionMap(); if (not selection) { @@ -671,14 +671,14 @@ UsdImagingHdEngine::AddSelected(SdfPath const &path, int instanceIndex) /*virtual*/ void -UsdImagingHdEngine::SetSelectionColor(GfVec4f const& color) +UsdImagingGLHdEngine::SetSelectionColor(GfVec4f const& color) { _defaultTaskDelegate->SetSelectionColor(color); } /* virtual */ bool -UsdImagingHdEngine::IsConverged() const +UsdImagingGLHdEngine::IsConverged() const { if (_currentPluginTaskDelegate) return _currentPluginTaskDelegate->IsConverged(); @@ -688,7 +688,7 @@ UsdImagingHdEngine::IsConverged() const /* virtual */ std::vector -UsdImagingHdEngine::GetRenderGraphPlugins() +UsdImagingGLHdEngine::GetRenderGraphPlugins() { // discover plugins if (not _pluginDiscovered) { @@ -696,11 +696,11 @@ UsdImagingHdEngine::GetRenderGraphPlugins() std::set pluginTaskTypes; PlugRegistry::GetAllDerivedTypes( - TfType::Find(), &pluginTaskTypes); + TfType::Find(), &pluginTaskTypes); // create entries (not load plugins yet) TF_FOR_ALL (it, pluginTaskTypes) { - _pluginTaskDelegates[*it] = UsdImagingTaskDelegateSharedPtr(); + _pluginTaskDelegates[*it] = UsdImagingGLTaskDelegateSharedPtr(); } } @@ -715,7 +715,7 @@ UsdImagingHdEngine::GetRenderGraphPlugins() /* virtual */ bool -UsdImagingHdEngine::SetRenderGraphPlugin(TfType const &type) +UsdImagingGLHdEngine::SetRenderGraphPlugin(TfType const &type) { _currentPluginTaskDelegate.reset(); if (not type) { @@ -748,14 +748,14 @@ UsdImagingHdEngine::SetRenderGraphPlugin(TfType const &type) return false; } - UsdImagingTaskDelegateFactoryBase* factory = - type.GetFactory(); + UsdImagingGLTaskDelegateFactoryBase* factory = + type.GetFactory(); if (not factory) { TF_WARN("Plugin type not manufacturable: %s\n", type.GetTypeName().c_str()); return false; } - UsdImagingTaskDelegateSharedPtr taskDelegate = + UsdImagingGLTaskDelegateSharedPtr taskDelegate = factory->New(_renderIndex, _delegate.GetDelegateID()/*=shareId*/); if (not taskDelegate) { TF_WARN("Fail to manufacture plugin %s\n", type.GetTypeName().c_str()); @@ -770,7 +770,7 @@ UsdImagingHdEngine::SetRenderGraphPlugin(TfType const &type) /* virtual */ VtDictionary -UsdImagingHdEngine::GetResourceAllocation() const +UsdImagingGLHdEngine::GetResourceAllocation() const { return HdResourceRegistry::GetInstance().GetResourceAllocation(); } diff --git a/pxr/usdImaging/lib/usdImaging/hdEngine.h b/pxr/usdImaging/lib/usdImagingGL/hdEngine.h similarity index 82% rename from pxr/usdImaging/lib/usdImaging/hdEngine.h rename to pxr/usdImaging/lib/usdImagingGL/hdEngine.h index 2d5b08ab28..61352d70aa 100644 --- a/pxr/usdImaging/lib/usdImaging/hdEngine.h +++ b/pxr/usdImaging/lib/usdImagingGL/hdEngine.h @@ -26,7 +26,7 @@ #pragma once -#include "pxr/usdImaging/usdImaging/engine.h" +#include "pxr/usdImaging/usdImagingGL/engine.h" #include "pxr/usdImaging/usdImaging/delegate.h" #include "pxr/imaging/hd/version.h" #include "pxr/imaging/hd/engine.h" @@ -39,34 +39,34 @@ TF_DECLARE_WEAK_AND_REF_PTRS(GlfSimpleLightingContext); class HdRenderIndex; -typedef boost::shared_ptr - UsdImagingTaskDelegateSharedPtr; -typedef boost::shared_ptr - UsdImaging_DefaultTaskDelegateSharedPtr; -typedef boost::shared_ptr UsdImagingHdEngineSharedPtr; -typedef std::vector - UsdImagingHdEngineSharedPtrVector; +typedef boost::shared_ptr + UsdImagingGLTaskDelegateSharedPtr; +typedef boost::shared_ptr + UsdImagingGL_DefaultTaskDelegateSharedPtr; +typedef boost::shared_ptr UsdImagingGLHdEngineSharedPtr; +typedef std::vector + UsdImagingGLHdEngineSharedPtrVector; typedef std::vector UsdPrimVector; typedef boost::shared_ptr HdxIntersectorSharedPtr; -class UsdImagingHdEngine : public UsdImagingEngine +class UsdImagingGLHdEngine : public UsdImagingGLEngine { public: - UsdImagingHdEngine(const SdfPath& rootPath, + UsdImagingGLHdEngine(const SdfPath& rootPath, const SdfPathVector& excludedPaths, const SdfPathVector& invisedPaths=SdfPathVector(), const SdfPath& sharedId = SdfPath::AbsoluteRootPath(), - const UsdImagingHdEngineSharedPtr& sharedImaging = - UsdImagingHdEngineSharedPtr()); + const UsdImagingGLHdEngineSharedPtr& sharedImaging = + UsdImagingGLHdEngineSharedPtr()); - virtual ~UsdImagingHdEngine(); + virtual ~UsdImagingGLHdEngine(); HdRenderIndexSharedPtr GetRenderIndex() const; virtual void InvalidateBuffers(); static void PrepareBatch( - const UsdImagingHdEngineSharedPtrVector& engines, + const UsdImagingGLHdEngineSharedPtrVector& engines, const UsdPrimVector& rootPrims, const std::vector& times, RenderParams params); @@ -141,14 +141,14 @@ class UsdImagingHdEngine : public UsdImagingEngine private: // Helper functions for preparing multiple engines for // batched drawing. - static void _PrepareBatch(const UsdImagingHdEngineSharedPtrVector& engines, + static void _PrepareBatch(const UsdImagingGLHdEngineSharedPtrVector& engines, const UsdPrimVector& rootPrims, const std::vector& times, const RenderParams& params); - static void _Populate(const UsdImagingHdEngineSharedPtrVector& engines, + static void _Populate(const UsdImagingGLHdEngineSharedPtrVector& engines, const UsdPrimVector& rootPrims); - static void _SetTimes(const UsdImagingHdEngineSharedPtrVector& engines, + static void _SetTimes(const UsdImagingGLHdEngineSharedPtrVector& engines, const UsdPrimVector& rootPrims, const std::vector& times, const RenderParams& params); @@ -161,7 +161,7 @@ class UsdImagingHdEngine : public UsdImagingEngine // returns the active task delegate for \p param. param is used to fallback // to the default task delegate when enableIdRender is true for picking. - UsdImagingTaskDelegateSharedPtr _GetTaskDelegate( + UsdImagingGLTaskDelegateSharedPtr _GetTaskDelegate( const RenderParams ¶ms) const ; HdEngine _engine; @@ -171,14 +171,14 @@ class UsdImagingHdEngine : public UsdImagingEngine UsdImagingDelegate _delegate; // built-in render graph delegate - UsdImaging_DefaultTaskDelegateSharedPtr _defaultTaskDelegate; + UsdImagingGL_DefaultTaskDelegateSharedPtr _defaultTaskDelegate; // plug-in render graphs delegate bool _pluginDiscovered; - typedef std::map + typedef std::map _PluginTaskDelegateMap; _PluginTaskDelegateMap _pluginTaskDelegates; - UsdImagingTaskDelegateSharedPtr _currentPluginTaskDelegate; + UsdImagingGLTaskDelegateSharedPtr _currentPluginTaskDelegate; GlfSimpleLightingContextRefPtr _lightingContextForOpenGLState; diff --git a/pxr/usdImaging/lib/usdImaging/module.cpp b/pxr/usdImaging/lib/usdImagingGL/module.cpp similarity index 100% rename from pxr/usdImaging/lib/usdImaging/module.cpp rename to pxr/usdImaging/lib/usdImagingGL/module.cpp diff --git a/pxr/usdImaging/lib/usdImaging/moduleDeps.cpp b/pxr/usdImaging/lib/usdImagingGL/moduleDeps.cpp similarity index 93% rename from pxr/usdImaging/lib/usdImaging/moduleDeps.cpp rename to pxr/usdImaging/lib/usdImagingGL/moduleDeps.cpp index b4b0124e4e..21f4e6e779 100644 --- a/pxr/usdImaging/lib/usdImaging/moduleDeps.cpp +++ b/pxr/usdImaging/lib/usdImagingGL/moduleDeps.cpp @@ -33,7 +33,7 @@ TF_REGISTRY_FUNCTION(TfScriptModuleLoader) { std::vector reqs; - reqs.reserve(22); + reqs.reserve(23); reqs.push_back(TfToken("ar")); reqs.push_back(TfToken("arch")); reqs.push_back(TfToken("cameraUtil")); @@ -53,10 +53,11 @@ TF_REGISTRY_FUNCTION(TfScriptModuleLoader) { reqs.push_back(TfToken("usd")); reqs.push_back(TfToken("usdGeom")); reqs.push_back(TfToken("usdHydra")); + reqs.push_back(TfToken("usdImaging")); reqs.push_back(TfToken("usdShade")); reqs.push_back(TfToken("vt")); reqs.push_back(TfToken("work")); TfScriptModuleLoader::GetInstance(). - RegisterLibrary(TfToken("usdImaging"), TfToken("pxr.UsdImaging"), reqs); + RegisterLibrary(TfToken("usdImagingGL"), TfToken("pxr.UsdImagingGL"), reqs); } diff --git a/pxr/usdImaging/lib/usdImaging/refEngine.cpp b/pxr/usdImaging/lib/usdImagingGL/refEngine.cpp similarity index 95% rename from pxr/usdImaging/lib/usdImaging/refEngine.cpp rename to pxr/usdImaging/lib/usdImagingGL/refEngine.cpp index a2e2efcc8d..97c4c5a9e9 100644 --- a/pxr/usdImaging/lib/usdImaging/refEngine.cpp +++ b/pxr/usdImaging/lib/usdImagingGL/refEngine.cpp @@ -23,7 +23,8 @@ // #include "pxr/imaging/glf/glew.h" -#include "pxr/usdImaging/usdImaging/refEngine.h" +#include "pxr/usdImaging/usdImagingGL/refEngine.h" + #include "pxr/usdImaging/usdImaging/cubeAdapter.h" #include "pxr/usdImaging/usdImaging/sphereAdapter.h" #include "pxr/usdImaging/usdImaging/coneAdapter.h" @@ -73,7 +74,7 @@ // single draw call, if the hardware supports it. #define _PRIM_RESTART_INDEX 0xffffffff -UsdImagingRefEngine::UsdImagingRefEngine(const SdfPathVector &excludedPrimPaths) : +UsdImagingGLRefEngine::UsdImagingGLRefEngine(const SdfPathVector &excludedPrimPaths) : _ctm(GfMatrix4d(1.0)), _vertCount(0), _lineVertCount(0), @@ -86,21 +87,21 @@ UsdImagingRefEngine::UsdImagingRefEngine(const SdfPathVector &excludedPrimPaths) } } -UsdImagingRefEngine::~UsdImagingRefEngine() +UsdImagingGLRefEngine::~UsdImagingGLRefEngine() { TfNotice::Revoke(_objectsChangedNoticeKey); InvalidateBuffers(); } bool -UsdImagingRefEngine::_SupportsPrimitiveRestartIndex() +UsdImagingGLRefEngine::_SupportsPrimitiveRestartIndex() { static bool supported = GlfHasExtensions("GL_NV_primitive_restart"); return supported; } void -UsdImagingRefEngine::InvalidateBuffers() +UsdImagingGLRefEngine::InvalidateBuffers() { TRACE_FUNCTION(); @@ -139,7 +140,7 @@ _AppendSubData(GLenum target, GLintptr* offset, T const& vec) } void -UsdImagingRefEngine::_PopulateBuffers() +UsdImagingGLRefEngine::_PopulateBuffers() { glGenBuffers(1, &_attribBuffer); glBindBuffer(GL_ARRAY_BUFFER, _attribBuffer); @@ -191,7 +192,7 @@ UsdImagingRefEngine::_PopulateBuffers() /*virtual*/ SdfPath -UsdImagingRefEngine::GetPrimPathFromPrimIdColor( +UsdImagingGLRefEngine::GetPrimPathFromPrimIdColor( GfVec4i const& primIdColor, GfVec4i const& instanceIdColor, int* instanceIndexOut) @@ -204,7 +205,7 @@ UsdImagingRefEngine::GetPrimPathFromPrimIdColor( } void -UsdImagingRefEngine::_DrawPolygons(bool drawID) +UsdImagingGLRefEngine::_DrawPolygons(bool drawID) { if (_points.empty()) { return; @@ -235,7 +236,7 @@ UsdImagingRefEngine::_DrawPolygons(bool drawID) } void -UsdImagingRefEngine::_DrawLines(bool drawID) +UsdImagingGLRefEngine::_DrawLines(bool drawID) { // We are just drawing curves as unrefined line segments, so we turn off // normals. @@ -270,12 +271,12 @@ UsdImagingRefEngine::_DrawLines(bool drawID) } void -UsdImagingRefEngine::Render(const UsdPrim& root, RenderParams params) +UsdImagingGLRefEngine::Render(const UsdPrim& root, RenderParams params) { TRACE_FUNCTION(); // Start listening for change notices from this stage. - UsdImagingRefEnginePtr self = TfCreateWeakPtr(this); + UsdImagingGLRefEnginePtr self = TfCreateWeakPtr(this); // Invalidate existing buffers if we are drawing from a different root or // frame. @@ -460,7 +461,7 @@ UsdImagingRefEngine::Render(const UsdPrim& root, RenderParams params) } void -UsdImagingRefEngine::SetCameraState(const GfMatrix4d& viewMatrix, +UsdImagingGLRefEngine::SetCameraState(const GfMatrix4d& viewMatrix, const GfMatrix4d& projectionMatrix, const GfVec4d& viewport) { @@ -474,14 +475,14 @@ UsdImagingRefEngine::SetCameraState(const GfMatrix4d& viewMatrix, } void -UsdImagingRefEngine::_OnObjectsChanged(UsdNotice::ObjectsChanged const& notice, +UsdImagingGLRefEngine::_OnObjectsChanged(UsdNotice::ObjectsChanged const& notice, UsdStageWeakPtr const& sender) { InvalidateBuffers(); } static void -UsdImagingRefEngine_ComputeSmoothNormals(const VtVec3fArray &points, +UsdImagingGLRefEngine_ComputeSmoothNormals(const VtVec3fArray &points, const VtIntArray &numVerts, const VtIntArray &verts, bool ccw, @@ -563,7 +564,7 @@ _ShouldCullDueToOpacity(const UsdGeomGprim *gprimSchema, const UsdTimeCode &fram } void -UsdImagingRefEngine::_TraverseStage(const UsdPrim& root) +UsdImagingGLRefEngine::_TraverseStage(const UsdPrim& root) { // Instead of using root.begin(), setup a special iterator that does both // pre-order and post-order traversal so we can push and pop state. @@ -656,7 +657,7 @@ UsdImagingRefEngine::_TraverseStage(const UsdPrim& root) } void -UsdImagingRefEngine::_ProcessGprimColor(const UsdGeomGprim *gprimSchema, +UsdImagingGLRefEngine::_ProcessGprimColor(const UsdGeomGprim *gprimSchema, const UsdPrim &prim, bool *doubleSided, VtArray *color, @@ -678,7 +679,7 @@ UsdImagingRefEngine::_ProcessGprimColor(const UsdGeomGprim *gprimSchema, } void -UsdImagingRefEngine::_HandleXform(const UsdPrim &prim) +UsdImagingGLRefEngine::_HandleXform(const UsdPrim &prim) { // Don't apply the root prim's transform. if (prim == _root) @@ -702,7 +703,7 @@ UsdImagingRefEngine::_HandleXform(const UsdPrim &prim) } GfVec4f -UsdImagingRefEngine::_IssueID(SdfPath const& path) +UsdImagingGLRefEngine::_IssueID(SdfPath const& path) { _PrimID::ValueType maxId = (1 << 24) - 1; // Notify the user (failed verify) and return an invalid ID. @@ -716,7 +717,7 @@ UsdImagingRefEngine::_IssueID(SdfPath const& path) } void -UsdImagingRefEngine::_HandleMesh(const UsdPrim &prim) +UsdImagingGLRefEngine::_HandleMesh(const UsdPrim &prim) { TRACE_FUNCTION(); @@ -740,7 +741,7 @@ UsdImagingRefEngine::_HandleMesh(const UsdPrim &prim) } void -UsdImagingRefEngine::_HandleCurves(const UsdPrim& prim) +UsdImagingGLRefEngine::_HandleCurves(const UsdPrim& prim) { TRACE_FUNCTION(); @@ -822,7 +823,7 @@ UsdImagingRefEngine::_HandleCurves(const UsdPrim& prim) } void -UsdImagingRefEngine::_HandleCube(const UsdPrim &prim) +UsdImagingGLRefEngine::_HandleCube(const UsdPrim &prim) { TRACE_FUNCTION(); @@ -850,7 +851,7 @@ UsdImagingRefEngine::_HandleCube(const UsdPrim &prim) } void -UsdImagingRefEngine::_HandleSphere(const UsdPrim &prim) +UsdImagingGLRefEngine::_HandleSphere(const UsdPrim &prim) { TRACE_FUNCTION(); @@ -878,7 +879,7 @@ UsdImagingRefEngine::_HandleSphere(const UsdPrim &prim) } void -UsdImagingRefEngine::_HandleCone(const UsdPrim &prim) +UsdImagingGLRefEngine::_HandleCone(const UsdPrim &prim) { TRACE_FUNCTION(); @@ -902,7 +903,7 @@ UsdImagingRefEngine::_HandleCone(const UsdPrim &prim) } void -UsdImagingRefEngine::_HandleCylinder(const UsdPrim &prim) +UsdImagingGLRefEngine::_HandleCylinder(const UsdPrim &prim) { TRACE_FUNCTION(); @@ -926,7 +927,7 @@ UsdImagingRefEngine::_HandleCylinder(const UsdPrim &prim) } void -UsdImagingRefEngine::_HandleCapsule(const UsdPrim &prim) +UsdImagingGLRefEngine::_HandleCapsule(const UsdPrim &prim) { TRACE_FUNCTION(); @@ -950,13 +951,13 @@ UsdImagingRefEngine::_HandleCapsule(const UsdPrim &prim) } void -UsdImagingRefEngine::_HandlePoints(const UsdPrim &prim) +UsdImagingGLRefEngine::_HandlePoints(const UsdPrim &prim) { TF_WARN("Point primitives are not yet supported."); } void -UsdImagingRefEngine::_HandleNurbsPatch(const UsdPrim &prim) +UsdImagingGLRefEngine::_HandleNurbsPatch(const UsdPrim &prim) { TRACE_FUNCTION(); @@ -979,7 +980,7 @@ UsdImagingRefEngine::_HandleNurbsPatch(const UsdPrim &prim) } void -UsdImagingRefEngine::_RenderPrimitive(const UsdPrim &prim, +UsdImagingGLRefEngine::_RenderPrimitive(const UsdPrim &prim, const UsdGeomGprim *gprimSchema, const VtArray& pts, const VtIntArray& nmvts, @@ -1062,7 +1063,7 @@ UsdImagingRefEngine::_RenderPrimitive(const UsdPrim &prim, // If the user is using FLAT SHADING it will still use interpolated normals // which means that OpenGL will pick one normal (provoking vertex) out of the // normals array. - UsdImagingRefEngine_ComputeSmoothNormals(pts, nmvts, vts, true /*ccw*/, &normals); + UsdImagingGLRefEngine_ComputeSmoothNormals(pts, nmvts, vts, true /*ccw*/, &normals); TF_FOR_ALL(itr, normals) { _normals.push_back((*itr)[0]); @@ -1076,7 +1077,7 @@ UsdImagingRefEngine::_RenderPrimitive(const UsdPrim &prim, // reversed, so that we handle doublesided geometry alongside // backface-culled geometry in the same draw call. - TRACE_SCOPE("UsdImagingRefEngine::HandleMesh (doublesided)"); + TRACE_SCOPE("UsdImagingGLRefEngine::HandleMesh (doublesided)"); index = 0; TF_FOR_ALL(itr, pts) { diff --git a/pxr/usdImaging/lib/usdImaging/refEngine.h b/pxr/usdImaging/lib/usdImagingGL/refEngine.h similarity index 96% rename from pxr/usdImaging/lib/usdImaging/refEngine.h rename to pxr/usdImaging/lib/usdImagingGL/refEngine.h index 1f0a07bad1..063e44be1d 100644 --- a/pxr/usdImaging/lib/usdImaging/refEngine.h +++ b/pxr/usdImaging/lib/usdImagingGL/refEngine.h @@ -26,7 +26,7 @@ #include "pxr/imaging/garch/gl.h" -#include "pxr/usdImaging/usdImaging/engine.h" +#include "pxr/usdImaging/usdImagingGL/engine.h" #include "pxr/usd/usdGeom/gprim.h" #include "pxr/usd/usd/notice.h" @@ -36,15 +36,15 @@ #include "pxr/base/tf/hashmap.h" #include "pxr/base/tf/hashset.h" -TF_DECLARE_WEAK_PTRS(UsdImagingRefEngine); +TF_DECLARE_WEAK_PTRS(UsdImagingGLRefEngine); -class UsdImagingRefEngine : public UsdImagingEngine, public TfWeakBase { - typedef UsdImagingRefEngine This; +class UsdImagingGLRefEngine : public UsdImagingGLEngine, public TfWeakBase { + typedef UsdImagingGLRefEngine This; public: - UsdImagingRefEngine(const SdfPathVector& excludedPaths); + UsdImagingGLRefEngine(const SdfPathVector& excludedPaths); - ~UsdImagingRefEngine(); + ~UsdImagingGLRefEngine(); // Entry point for kicking off a render virtual void Render(const UsdPrim& root, RenderParams params); diff --git a/pxr/usdImaging/lib/usdImaging/taskDelegate.cpp b/pxr/usdImaging/lib/usdImagingGL/taskDelegate.cpp similarity index 84% rename from pxr/usdImaging/lib/usdImaging/taskDelegate.cpp rename to pxr/usdImaging/lib/usdImagingGL/taskDelegate.cpp index e480335ae7..bf2bfe8467 100644 --- a/pxr/usdImaging/lib/usdImaging/taskDelegate.cpp +++ b/pxr/usdImaging/lib/usdImagingGL/taskDelegate.cpp @@ -21,16 +21,16 @@ // KIND, either express or implied. See the Apache License for the specific // language governing permissions and limitations under the Apache License. // -#include "pxr/usdImaging/usdImaging/taskDelegate.h" +#include "pxr/usdImaging/usdImagingGL/taskDelegate.h" #include "pxr/base/tf/type.h" TF_REGISTRY_FUNCTION(TfType) { - TfType::Define(); + TfType::Define(); } -UsdImagingTaskDelegate::UsdImagingTaskDelegate( +UsdImagingGLTaskDelegate::UsdImagingGLTaskDelegate( HdRenderIndexSharedPtr const& parentIndex, SdfPath const& delegateID) : HdSceneDelegate(parentIndex, delegateID) @@ -38,14 +38,14 @@ UsdImagingTaskDelegate::UsdImagingTaskDelegate( /* nothing */ } -UsdImagingTaskDelegate::~UsdImagingTaskDelegate() +UsdImagingGLTaskDelegate::~UsdImagingGLTaskDelegate() { /* nothing */ } /*virtual*/ HdRprimCollection const& -UsdImagingTaskDelegate::GetRprimCollection() const +UsdImagingGLTaskDelegate::GetRprimCollection() const { static HdRprimCollection col; return col; diff --git a/pxr/usdImaging/lib/usdImaging/taskDelegate.h b/pxr/usdImaging/lib/usdImagingGL/taskDelegate.h similarity index 76% rename from pxr/usdImaging/lib/usdImaging/taskDelegate.h rename to pxr/usdImaging/lib/usdImagingGL/taskDelegate.h index dac82350d9..f8e1212c3e 100644 --- a/pxr/usdImaging/lib/usdImaging/taskDelegate.h +++ b/pxr/usdImaging/lib/usdImagingGL/taskDelegate.h @@ -23,7 +23,7 @@ // #pragma once -#include "pxr/usdImaging/usdImaging/engine.h" +#include "pxr/usdImaging/usdImagingGL/engine.h" #include "pxr/imaging/hd/version.h" #include "pxr/imaging/hd/rprimCollection.h" @@ -37,27 +37,27 @@ // Render-graph delegate base // -typedef boost::shared_ptr UsdImagingTaskDelegateSharedPtr; +typedef boost::shared_ptr UsdImagingGLTaskDelegateSharedPtr; -class UsdImagingTaskDelegate : public HdSceneDelegate { +class UsdImagingGLTaskDelegate : public HdSceneDelegate { public: - UsdImagingTaskDelegate(HdRenderIndexSharedPtr const& renderIndex, + UsdImagingGLTaskDelegate(HdRenderIndexSharedPtr const& renderIndex, SdfPath const& delegateID); - ~UsdImagingTaskDelegate(); + ~UsdImagingGLTaskDelegate(); // HdSceneDelegate interface virtual VtValue Get(SdfPath const& id, TfToken const& key) = 0; - // UsdImagingTaskDelegate interface + // UsdImagingGLTaskDelegate interface // returns tasks in the render graph for the given params virtual HdTaskSharedPtrVector GetRenderTasks( - UsdImagingEngine::RenderParams const ¶ms) = 0; + UsdImagingGLEngine::RenderParams const ¶ms) = 0; // update roots and RenderParam virtual void SetCollectionAndRenderParams( const SdfPathVector &roots, - const UsdImagingEngine::RenderParams ¶ms) = 0; + const UsdImagingGLEngine::RenderParams ¶ms) = 0; // Return the current active RprimCollection virtual HdRprimCollection const& GetRprimCollection() const; @@ -75,26 +75,26 @@ class UsdImagingTaskDelegate : public HdSceneDelegate { // returns true if the task delegate can handle \p params. // if it's false, the default task will be used instead. // (for example, a plugin task may not support enableIdRender) - virtual bool CanRender(const UsdImagingEngine::RenderParams ¶ms) = 0; + virtual bool CanRender(const UsdImagingGLEngine::RenderParams ¶ms) = 0; // returns true if the image is converged. virtual bool IsConverged() const = 0; }; -class UsdImagingTaskDelegateFactoryBase : public TfType::FactoryBase { +class UsdImagingGLTaskDelegateFactoryBase : public TfType::FactoryBase { public: - virtual UsdImagingTaskDelegateSharedPtr + virtual UsdImagingGLTaskDelegateSharedPtr New(HdRenderIndexSharedPtr const& renderIndex, SdfPath const& delegateID) const = 0; }; template -class UsdImagingTaskDelegateFactory : public UsdImagingTaskDelegateFactoryBase { +class UsdImagingGLTaskDelegateFactory : public UsdImagingGLTaskDelegateFactoryBase { public: - virtual UsdImagingTaskDelegateSharedPtr + virtual UsdImagingGLTaskDelegateSharedPtr New(HdRenderIndexSharedPtr const& renderIndex, SdfPath const& delegateID) const { - return UsdImagingTaskDelegateSharedPtr(new T(renderIndex, delegateID)); + return UsdImagingGLTaskDelegateSharedPtr(new T(renderIndex, delegateID)); } }; diff --git a/pxr/usdImaging/lib/usdImaging/testenv/testUsdImagingBasicDrawing.cpp b/pxr/usdImaging/lib/usdImagingGL/testenv/testUsdImagingGLBasicDrawing.cpp similarity index 90% rename from pxr/usdImaging/lib/usdImaging/testenv/testUsdImagingBasicDrawing.cpp rename to pxr/usdImaging/lib/usdImagingGL/testenv/testUsdImagingGLBasicDrawing.cpp index ff13c408c5..a67fb28f49 100644 --- a/pxr/usdImaging/lib/usdImaging/testenv/testUsdImagingBasicDrawing.cpp +++ b/pxr/usdImaging/lib/usdImagingGL/testenv/testUsdImagingGLBasicDrawing.cpp @@ -23,7 +23,7 @@ // #include "pxr/imaging/glf/glew.h" -#include "pxr/usdImaging/usdImaging/unitTestGLDrawing.h" +#include "pxr/usdImaging/usdImagingGL/unitTestGLDrawing.h" #include "pxr/base/arch/systemInfo.h" #include "pxr/base/gf/bbox3d.h" @@ -44,20 +44,21 @@ #include "pxr/usd/usdGeom/tokens.h" #include "pxr/usdImaging/usdImaging/unitTestHelper.h" -#include "pxr/usdImaging/usdImaging/gl.h" -#include "pxr/usdImaging/usdImaging/hdEngine.h" -#include "pxr/usdImaging/usdImaging/refEngine.h" #include "pxr/usdImaging/usdImaging/tokens.h" +#include "pxr/usdImaging/usdImagingGL/gl.h" +#include "pxr/usdImaging/usdImagingGL/hdEngine.h" +#include "pxr/usdImaging/usdImagingGL/refEngine.h" + #include #include #include #include -typedef boost::shared_ptr UsdImagingEngineSharedPtr; +typedef boost::shared_ptr UsdImagingGLEngineSharedPtr; -class My_TestGLDrawing : public UsdImaging_UnitTestGLDrawing { +class My_TestGLDrawing : public UsdImagingGL_UnitTestGLDrawing { public: My_TestGLDrawing() { _mousePos[0] = _mousePos[1] = 0; @@ -66,18 +67,18 @@ class My_TestGLDrawing : public UsdImaging_UnitTestGLDrawing { _translate[0] = _translate[1] = _translate[2] = 0; } - // UsdImaging_UnitTestGLDrawing overrides + // UsdImagingGL_UnitTestGLDrawing overrides virtual void InitTest(); virtual void DrawTest(bool offscreen); virtual void ShutdownTest(); - virtual void MousePress(int button, int x, int y); - virtual void MouseRelease(int button, int x, int y); - virtual void MouseMove(int x, int y); + virtual void MousePress(int button, int x, int y, int modKeys); + virtual void MouseRelease(int button, int x, int y, int modKeys); + virtual void MouseMove(int x, int y, int modKeys); private: UsdStageRefPtr _stage; - UsdImagingEngineSharedPtr _engine; + UsdImagingGLEngineSharedPtr _engine; GlfSimpleLightingContextRefPtr _lightingContext; float _rotate[2]; @@ -98,11 +99,11 @@ My_TestGLDrawing::InitTest() bool isEnabledHydra = (TfGetenv("HD_ENABLED", "1") == "1"); if (isEnabledHydra) { std::cout << "Using HD Renderer.\n"; - _engine.reset(new UsdImagingHdEngine( + _engine.reset(new UsdImagingGLHdEngine( _stage->GetPseudoRoot().GetPath(), excludedPaths)); } else{ std::cout << "Using Reference Renderer.\n"; - _engine.reset(new UsdImagingRefEngine(excludedPaths)); + _engine.reset(new UsdImagingGLRefEngine(excludedPaths)); } std::cout << glGetString(GL_VENDOR) << "\n"; @@ -224,15 +225,15 @@ My_TestGLDrawing::DrawTest(bool offscreen) if (*timeIt == -999) { time = UsdTimeCode::Default(); } - UsdImagingEngine::RenderParams params; + UsdImagingGLEngine::RenderParams params; params.drawMode = GetDrawMode(); params.enableLighting = IsEnabledTestLighting(); params.enableIdRender = IsEnabledIdRender(); params.frame = time; params.complexity = _GetComplexity(); params.cullStyle = IsEnabledCullBackfaces() ? - UsdImagingEngine::CULL_STYLE_BACK : - UsdImagingEngine::CULL_STYLE_NOTHING; + UsdImagingGLEngine::CULL_STYLE_BACK : + UsdImagingGLEngine::CULL_STYLE_NOTHING; glViewport(0, 0, width, height); @@ -286,7 +287,7 @@ My_TestGLDrawing::ShutdownTest() } void -My_TestGLDrawing::MousePress(int button, int x, int y) +My_TestGLDrawing::MousePress(int button, int x, int y, int modKeys) { _mouseButton[button] = 1; _mousePos[0] = x; @@ -294,13 +295,13 @@ My_TestGLDrawing::MousePress(int button, int x, int y) } void -My_TestGLDrawing::MouseRelease(int button, int x, int y) +My_TestGLDrawing::MouseRelease(int button, int x, int y, int modKeys) { _mouseButton[button] = 0; } void -My_TestGLDrawing::MouseMove(int x, int y) +My_TestGLDrawing::MouseMove(int x, int y, int modKeys) { int dx = x - _mousePos[0]; int dy = y - _mousePos[1]; diff --git a/pxr/usdImaging/lib/usdImaging/unitTestGLDrawing.cpp b/pxr/usdImaging/lib/usdImagingGL/unitTestGLDrawing.cpp similarity index 87% rename from pxr/usdImaging/lib/usdImaging/unitTestGLDrawing.cpp rename to pxr/usdImaging/lib/usdImagingGL/unitTestGLDrawing.cpp index d6d271135b..cdb2af7b1d 100644 --- a/pxr/usdImaging/lib/usdImaging/unitTestGLDrawing.cpp +++ b/pxr/usdImaging/lib/usdImagingGL/unitTestGLDrawing.cpp @@ -23,7 +23,7 @@ // #include "pxr/imaging/glf/glew.h" -#include "pxr/usdImaging/usdImaging/unitTestGLDrawing.h" +#include "pxr/usdImaging/usdImagingGL/unitTestGLDrawing.h" #include "pxr/imaging/glf/diagnostic.h" #include "pxr/imaging/glf/drawTarget.h" #include "pxr/imaging/glfq/glDebugContext.h" @@ -41,7 +41,7 @@ #include #include -static void UsdImaging_UnitTestHelper_InitPlugins() +static void UsdImagingGL_UnitTestHelper_InitPlugins() { // Unfortunately, in order to properly find plugins in our test setup, we // need to know where the test is running. @@ -68,14 +68,14 @@ _GetGLFormat() return fmt; } -class UsdImaging_UnitTestDrawingQGLWidget : public QGLWidget { +class UsdImagingGL_UnitTestDrawingQGLWidget : public QGLWidget { public: - typedef UsdImaging_UnitTestDrawingQGLWidget This; + typedef UsdImagingGL_UnitTestDrawingQGLWidget This; public: - UsdImaging_UnitTestDrawingQGLWidget(UsdImaging_UnitTestGLDrawing * unitTest, + UsdImagingGL_UnitTestDrawingQGLWidget(UsdImagingGL_UnitTestGLDrawing * unitTest, QWidget * parent = NULL); - virtual ~UsdImaging_UnitTestDrawingQGLWidget(); + virtual ~UsdImagingGL_UnitTestDrawingQGLWidget(); void DrawOffscreen(); @@ -94,25 +94,25 @@ class UsdImaging_UnitTestDrawingQGLWidget : public QGLWidget { virtual void mouseMoveEvent(QMouseEvent * event); private: - UsdImaging_UnitTestGLDrawing *_unitTest; + UsdImagingGL_UnitTestGLDrawing *_unitTest; GlfDrawTargetRefPtr _drawTarget; }; -UsdImaging_UnitTestDrawingQGLWidget::UsdImaging_UnitTestDrawingQGLWidget( - UsdImaging_UnitTestGLDrawing * unitTest, +UsdImagingGL_UnitTestDrawingQGLWidget::UsdImagingGL_UnitTestDrawingQGLWidget( + UsdImagingGL_UnitTestGLDrawing * unitTest, QWidget * parent) : QGLWidget(new GlfQGLDebugContext(_GetGLFormat()), parent), _unitTest(unitTest) { } -UsdImaging_UnitTestDrawingQGLWidget::~UsdImaging_UnitTestDrawingQGLWidget() +UsdImagingGL_UnitTestDrawingQGLWidget::~UsdImagingGL_UnitTestDrawingQGLWidget() { } /* virtual */ void -UsdImaging_UnitTestDrawingQGLWidget::initializeGL() +UsdImagingGL_UnitTestDrawingQGLWidget::initializeGL() { GlfGlewInit(); GlfRegisterDefaultDebugOutputMessageCallback(); @@ -134,7 +134,7 @@ UsdImaging_UnitTestDrawingQGLWidget::initializeGL() /* virtual */ void -UsdImaging_UnitTestDrawingQGLWidget::paintGL() +UsdImagingGL_UnitTestDrawingQGLWidget::paintGL() { // // Update the draw target's size and execute the unit test with @@ -164,7 +164,7 @@ UsdImaging_UnitTestDrawingQGLWidget::paintGL() } void -UsdImaging_UnitTestDrawingQGLWidget::DrawOffscreen() +UsdImagingGL_UnitTestDrawingQGLWidget::DrawOffscreen() { // // Ask Qt to initialize and draw @@ -180,7 +180,7 @@ UsdImaging_UnitTestDrawingQGLWidget::DrawOffscreen() } bool -UsdImaging_UnitTestDrawingQGLWidget::WriteToFile(std::string const & attachment, +UsdImagingGL_UnitTestDrawingQGLWidget::WriteToFile(std::string const & attachment, std::string const & filename) { // We need to unbind the draw target before writing to file to be sure the @@ -198,7 +198,7 @@ UsdImaging_UnitTestDrawingQGLWidget::WriteToFile(std::string const & attachment, /* virtual */ void -UsdImaging_UnitTestDrawingQGLWidget::keyReleaseEvent(QKeyEvent * event) +UsdImagingGL_UnitTestDrawingQGLWidget::keyReleaseEvent(QKeyEvent * event) { switch (event->key()) { case Qt::Key_Escape: @@ -210,7 +210,7 @@ UsdImaging_UnitTestDrawingQGLWidget::keyReleaseEvent(QKeyEvent * event) /* virtual */ void -UsdImaging_UnitTestDrawingQGLWidget::mousePressEvent(QMouseEvent * event) +UsdImagingGL_UnitTestDrawingQGLWidget::mousePressEvent(QMouseEvent * event) { int button = 0; switch(event->button()){ @@ -224,7 +224,7 @@ UsdImaging_UnitTestDrawingQGLWidget::mousePressEvent(QMouseEvent * event) /* virtual */ void -UsdImaging_UnitTestDrawingQGLWidget::mouseReleaseEvent(QMouseEvent * event) +UsdImagingGL_UnitTestDrawingQGLWidget::mouseReleaseEvent(QMouseEvent * event) { int button = 0; switch(event->button()){ @@ -238,7 +238,7 @@ UsdImaging_UnitTestDrawingQGLWidget::mouseReleaseEvent(QMouseEvent * event) /* virtual */ void -UsdImaging_UnitTestDrawingQGLWidget::mouseMoveEvent(QMouseEvent * event) +UsdImagingGL_UnitTestDrawingQGLWidget::mouseMoveEvent(QMouseEvent * event) { _unitTest->MouseMove(event->x(), event->y()); glDraw(); @@ -246,47 +246,47 @@ UsdImaging_UnitTestDrawingQGLWidget::mouseMoveEvent(QMouseEvent * event) //////////////////////////////////////////////////////////// -UsdImaging_UnitTestGLDrawing::UsdImaging_UnitTestGLDrawing() +UsdImagingGL_UnitTestGLDrawing::UsdImagingGL_UnitTestGLDrawing() : _widget(NULL) , _testLighting(false) , _testIdRender(false) , _complexity(1.0f) - , _drawMode(UsdImagingEngine::DRAW_SHADED_SMOOTH) + , _drawMode(UsdImagingGLEngine::DRAW_SHADED_SMOOTH) , _shouldFrameAll(false) , _cullBackfaces(false) { } -UsdImaging_UnitTestGLDrawing::~UsdImaging_UnitTestGLDrawing() +UsdImagingGL_UnitTestGLDrawing::~UsdImagingGL_UnitTestGLDrawing() { } int -UsdImaging_UnitTestGLDrawing::GetWidth() const +UsdImagingGL_UnitTestGLDrawing::GetWidth() const { return _widget->width(); } int -UsdImaging_UnitTestGLDrawing::GetHeight() const +UsdImagingGL_UnitTestGLDrawing::GetHeight() const { return _widget->height(); } bool -UsdImaging_UnitTestGLDrawing::WriteToFile(std::string const & attachment, +UsdImagingGL_UnitTestGLDrawing::WriteToFile(std::string const & attachment, std::string const & filename) const { return _widget->WriteToFile(attachment, filename); } void -UsdImaging_UnitTestGLDrawing::_Redraw() const +UsdImagingGL_UnitTestGLDrawing::_Redraw() const { _widget->update(); } -struct UsdImaging_UnitTestGLDrawing::_Args { +struct UsdImagingGL_UnitTestGLDrawing::_Args { _Args() : offscreen(false) { } std::string unresolvedStageFilePath; @@ -415,7 +415,7 @@ ParseDoubleVector( } void -UsdImaging_UnitTestGLDrawing::_Parse(int argc, char *argv[], _Args* args) +UsdImagingGL_UnitTestGLDrawing::_Parse(int argc, char *argv[], _Args* args) { for (int i = 1; i != argc; ++i) { if (strcmp(argv[i], "-") == 0) { @@ -472,11 +472,11 @@ UsdImaging_UnitTestGLDrawing::_Parse(int argc, char *argv[], _Args* args) } void -UsdImaging_UnitTestGLDrawing::RunTest(int argc, char *argv[]) +UsdImagingGL_UnitTestGLDrawing::RunTest(int argc, char *argv[]) { QApplication app(argc, argv); - UsdImaging_UnitTestHelper_InitPlugins(); + UsdImagingGL_UnitTestHelper_InitPlugins(); _Args args; _Parse(argc, argv, &args); @@ -485,20 +485,20 @@ UsdImaging_UnitTestGLDrawing::RunTest(int argc, char *argv[]) _clipPlanes.push_back(GfVec4d(&args.clipPlaneCoords[i*4])); } - _drawMode = UsdImagingEngine::DRAW_SHADED_SMOOTH; + _drawMode = UsdImagingGLEngine::DRAW_SHADED_SMOOTH; // Only wireOnSurface/flat are supported if (args.shading.compare("wireOnSurface") == 0) { - _drawMode = UsdImagingEngine::DRAW_WIREFRAME_ON_SURFACE; + _drawMode = UsdImagingGLEngine::DRAW_WIREFRAME_ON_SURFACE; } else if (args.shading.compare("flat") == 0 ) { - _drawMode = UsdImagingEngine::DRAW_SHADED_FLAT; + _drawMode = UsdImagingGLEngine::DRAW_SHADED_FLAT; } if (not args.unresolvedStageFilePath.empty()) { _stageFilePath = args.unresolvedStageFilePath; } - _widget = new UsdImaging_UnitTestDrawingQGLWidget(this); + _widget = new UsdImagingGL_UnitTestDrawingQGLWidget(this); _widget->setWindowTitle("Drawing Test"); _widget->resize(640, 480); diff --git a/pxr/usdImaging/lib/usdImaging/unitTestGLDrawing.h b/pxr/usdImaging/lib/usdImagingGL/unitTestGLDrawing.h similarity index 87% rename from pxr/usdImaging/lib/usdImaging/unitTestGLDrawing.h rename to pxr/usdImaging/lib/usdImagingGL/unitTestGLDrawing.h index 1f720ebecd..8095480520 100644 --- a/pxr/usdImaging/lib/usdImaging/unitTestGLDrawing.h +++ b/pxr/usdImaging/lib/usdImagingGL/unitTestGLDrawing.h @@ -28,21 +28,21 @@ #include "pxr/base/tf/declarePtrs.h" -#include "pxr/usdImaging/usdImaging/engine.h" +#include "pxr/usdImaging/usdImagingGL/engine.h" #include #include -class UsdImaging_UnitTestDrawingQGLWidget; +class UsdImagingGL_UnitTestDrawingQGLWidget; -/// \class UsdImaging_UnitTestGLDrawing +/// \class UsdImagingGL_UnitTestGLDrawing /// /// A helper class for unit tests which need to perform GL drawing. /// -class UsdImaging_UnitTestGLDrawing { +class UsdImagingGL_UnitTestGLDrawing { public: - UsdImaging_UnitTestGLDrawing(); - virtual ~UsdImaging_UnitTestGLDrawing(); + UsdImagingGL_UnitTestGLDrawing(); + virtual ~UsdImagingGL_UnitTestGLDrawing(); int GetWidth() const; int GetHeight() const; @@ -51,7 +51,7 @@ class UsdImaging_UnitTestGLDrawing { bool IsEnabledCullBackfaces() const { return _cullBackfaces; } bool IsEnabledIdRender() const { return _testIdRender; } - UsdImagingEngine::DrawMode GetDrawMode() const { return _drawMode; } + UsdImagingGLEngine::DrawMode GetDrawMode() const { return _drawMode; } std::string const & GetStageFilePath() const { return _stageFilePath; } std::string const & GetOutputFilePath() const { return _outputFilePath; } @@ -81,7 +81,7 @@ class UsdImaging_UnitTestGLDrawing { void _Parse(int argc, char *argv[], _Args* args); private: - UsdImaging_UnitTestDrawingQGLWidget *_widget; + UsdImagingGL_UnitTestDrawingQGLWidget *_widget; bool _testLighting; bool _testIdRender; @@ -93,7 +93,7 @@ class UsdImaging_UnitTestGLDrawing { std::vector _clipPlanes; - UsdImagingEngine::DrawMode _drawMode; + UsdImagingGLEngine::DrawMode _drawMode; bool _shouldFrameAll; bool _cullBackfaces; }; diff --git a/pxr/usdImaging/lib/usdImaging/wrapGL.cpp b/pxr/usdImaging/lib/usdImagingGL/wrapGL.cpp similarity index 99% rename from pxr/usdImaging/lib/usdImaging/wrapGL.cpp rename to pxr/usdImaging/lib/usdImagingGL/wrapGL.cpp index 012e83f4ad..7ae5ebf872 100644 --- a/pxr/usdImaging/lib/usdImaging/wrapGL.cpp +++ b/pxr/usdImaging/lib/usdImagingGL/wrapGL.cpp @@ -27,8 +27,10 @@ #include #include -#include "pxr/usdImaging/usdImaging/gl.h" +#include "pxr/usdImaging/usdImagingGL/gl.h" + #include "pxr/usdImaging/usdImaging/delegate.h" + #include "pxr/usd/usd/prim.h" #include "pxr/base/tf/pyEnum.h" #include "pxr/base/tf/pyResultConversions.h" diff --git a/pxr/usdImaging/lib/usdviewq/mainWindow.py b/pxr/usdImaging/lib/usdviewq/mainWindow.py index 702b1c5e78..fc0dc35675 100644 --- a/pxr/usdImaging/lib/usdviewq/mainWindow.py +++ b/pxr/usdImaging/lib/usdviewq/mainWindow.py @@ -31,7 +31,7 @@ from attributeViewContextMenu import AttributeViewContextMenu from customAttributes import _GetCustomAttributes from nodeViewItem import NodeViewItem -from pxr import Usd, UsdGeom, UsdUtils, UsdImaging +from pxr import Usd, UsdGeom, UsdUtils, UsdImagingGL from pxr import Glf from pxr import Sdf from pxr import Tf @@ -2734,7 +2734,7 @@ def _getItemAtPath(self, path, ensureExpanded=False): return self._nodeToItemMap[self._stage.GetPrimAtPath(path)] def resetSelectionToPseudoroot(self): - self.selectNodeByPath("/", UsdImaging.GL.ALL_INSTANCES, "replace") + self.selectNodeByPath("/", UsdImagingGL.GL.ALL_INSTANCES, "replace") def selectNodeByPath(self, path, instanceIndex, updateMode): """Modifies selection by a stage prim based on a prim path, @@ -2765,7 +2765,7 @@ def selectNodeByPath(self, path, instanceIndex, updateMode): # If not in instances picking mode, select all instances. if not self._ui.actionPick_Instances.isChecked(): self._stageView.clearInstanceSelection() - instanceIndex = UsdImaging.GL.ALL_INSTANCES + instanceIndex = UsdImagingGL.GL.ALL_INSTANCES item = self._getItemAtPath(path, ensureExpanded=True) @@ -2777,7 +2777,7 @@ def selectNodeByPath(self, path, instanceIndex, updateMode): self._stageView.setInstanceSelection(path, instanceIndex, True) item.setSelected(True) else: # "toggle" - if instanceIndex != UsdImaging.GL.ALL_INSTANCES: + if instanceIndex != UsdImagingGL.GL.ALL_INSTANCES: self._stageView.setInstanceSelection(path, instanceIndex, not self._stageView.getInstanceSelection(path, instanceIndex)) # if no instances selected, unselect item @@ -2793,7 +2793,7 @@ def selectNodeByPath(self, path, instanceIndex, updateMode): item = self._getItemAtPath(self._stage.GetPseudoRoot().GetPath()) item.setSelected(True) - if instanceIndex != UsdImaging.GL.ALL_INSTANCES: + if instanceIndex != UsdImagingGL.GL.ALL_INSTANCES: self._itemSelectionChanged() return item @@ -2856,7 +2856,7 @@ def _setSelectionFromPrimList(self, primsToSelect): first = True for prim in primsToSelect: if self._primShouldBeShown(prim): - instanceIndex = UsdImaging.GL.ALL_INSTANCES + instanceIndex = UsdImagingGL.GL.ALL_INSTANCES item = self.selectNodeByPath(prim.GetPath(), instanceIndex, "replace" if first else "add") first = False diff --git a/pxr/usdImaging/lib/usdviewq/stageView.py b/pxr/usdImaging/lib/usdviewq/stageView.py index 78b0ffe240..3eafebf91c 100644 --- a/pxr/usdImaging/lib/usdviewq/stageView.py +++ b/pxr/usdImaging/lib/usdviewq/stageView.py @@ -36,7 +36,7 @@ from pxr import Glf from pxr import Glfq from pxr import Sdf, Usd, UsdGeom, UsdUtils -from pxr import UsdImaging +from pxr import UsdImagingGL from pxr import CameraUtil # default includedPurposes for the bbox cache @@ -501,7 +501,7 @@ class StageView(QtOpenGL.QGLWidget): signalBboxUpdateTimeChanged = QtCore.Signal(int) # First arg is primPath, (which could be empty Path) - # Second arg is instanceIndex (or UsdImaging.GL.ALL_INSTANCES for all instances) + # Second arg is instanceIndex (or UsdImagingGL.GL.ALL_INSTANCES for all instances) # Third and Fourth args represent state at time of the pick signalPrimSelected = QtCore.Signal(Sdf.Path, int, QtCore.Qt.MouseButton, QtCore.Qt.KeyboardModifiers) @@ -793,18 +793,18 @@ def __init__(self, parent=None, bboxCache=None, xformCache=None): self._lastY = 0 self._renderer = None - self._renderModeDict={"Wireframe":UsdImaging.GL.DrawMode.DRAW_WIREFRAME, - "WireframeOnSurface":UsdImaging.GL.DrawMode.DRAW_WIREFRAME_ON_SURFACE, - "Smooth Shaded":UsdImaging.GL.DrawMode.DRAW_SHADED_SMOOTH, - "Points":UsdImaging.GL.DrawMode.DRAW_POINTS, - "Flat Shaded":UsdImaging.GL.DrawMode.DRAW_SHADED_FLAT, - "Geom Only":UsdImaging.GL.DrawMode.DRAW_GEOM_ONLY, - "Geom Smooth":UsdImaging.GL.DrawMode.DRAW_GEOM_SMOOTH, - "Geom Flat":UsdImaging.GL.DrawMode.DRAW_GEOM_FLAT, - "Hidden Surface Wireframe":UsdImaging.GL.DrawMode.DRAW_WIREFRAME} + self._renderModeDict={"Wireframe":UsdImagingGL.GL.DrawMode.DRAW_WIREFRAME, + "WireframeOnSurface":UsdImagingGL.GL.DrawMode.DRAW_WIREFRAME_ON_SURFACE, + "Smooth Shaded":UsdImagingGL.GL.DrawMode.DRAW_SHADED_SMOOTH, + "Points":UsdImagingGL.GL.DrawMode.DRAW_POINTS, + "Flat Shaded":UsdImagingGL.GL.DrawMode.DRAW_SHADED_FLAT, + "Geom Only":UsdImagingGL.GL.DrawMode.DRAW_GEOM_ONLY, + "Geom Smooth":UsdImagingGL.GL.DrawMode.DRAW_GEOM_SMOOTH, + "Geom Flat":UsdImagingGL.GL.DrawMode.DRAW_GEOM_FLAT, + "Hidden Surface Wireframe":UsdImagingGL.GL.DrawMode.DRAW_WIREFRAME} self._renderMode = "Smooth Shaded" - self._renderParams = UsdImaging.GL.RenderParams() + self._renderParams = UsdImagingGL.GL.RenderParams() self._defaultFov = 60 self._dist = 50 self._oldDist = self._dist @@ -880,7 +880,7 @@ def InitRenderer(self): disable rendering for this widget, you MUST have already set self.noRender to True prior to calling this function''' if not self._noRender: - self._renderer = UsdImaging.GL() + self._renderer = UsdImagingGL.GL() def GetRenderGraphPlugins(self): if self._renderer: @@ -1092,7 +1092,7 @@ def _updateSelection(self): for instanceIndex in self._selectedInstances[p.GetPath()]: self._renderer.AddSelected(p.GetPath(), instanceIndex) else: - self._renderer.AddSelected(p.GetPath(), UsdImaging.GL.ALL_INSTANCES) + self._renderer.AddSelected(p.GetPath(), UsdImagingGL.GL.ALL_INSTANCES) def _getEmptyBBox(self): return Gf.BBox3d() @@ -1145,9 +1145,9 @@ def renderSinglePass(self, renderMode, renderSelHighlights): self._renderParams.showGuides = self._displayGuides self._renderParams.showRenderGuides = self._displayRenderingGuides self._renderParams.forceRefresh = self._forceRefresh - self._renderParams.cullStyle = (UsdImaging.GL.CullStyle.CULL_STYLE_BACK_UNLESS_DOUBLE_SIDED + self._renderParams.cullStyle = (UsdImagingGL.GL.CullStyle.CULL_STYLE_BACK_UNLESS_DOUBLE_SIDED if self._cullBackfaces - else UsdImaging.GL.CullStyle.CULL_STYLE_NOTHING) + else UsdImagingGL.GL.CullStyle.CULL_STYLE_NOTHING) self._renderParams.gammaCorrectColors = False self._renderParams.enableIdRender = self._displayPrimId self._renderParams.enableSampleAlphaToCoverage = not self._displayPrimId @@ -1548,7 +1548,7 @@ def paintGL(self): # Hydra Enabled toPrint = {"Hydra": - "Enabled" if UsdImaging.GL.IsEnabledHydra() + "Enabled" if UsdImagingGL.GL.IsEnabledHydra() else "Disabled"} self.printDict(self.width()-140, 14, col, toPrint) @@ -1778,9 +1778,9 @@ def pick(self, pickFrustum): self._renderParams.showGuides = self._displayGuides self._renderParams.showRenderGuides = self._displayRenderingGuides self._renderParams.forceRefresh = self._forceRefresh - self._renderParams.cullStyle = (UsdImaging.GL.CullStyle.CULL_STYLE_BACK_UNLESS_DOUBLE_SIDED + self._renderParams.cullStyle = (UsdImagingGL.GL.CullStyle.CULL_STYLE_BACK_UNLESS_DOUBLE_SIDED if self._cullBackfaces - else UsdImaging.GL.CullStyle.CULL_STYLE_NOTHING) + else UsdImagingGL.GL.CullStyle.CULL_STYLE_NOTHING) self._renderParams.gammaCorrectColors = False self._renderParams.enableIdRender = True self._renderParams.enableSampleAlphaToCoverage = False @@ -1834,7 +1834,7 @@ def pickObject(self, x, y, button, modifiers): selectedPrimPath = instancePrimPath selectedInstanceIndex = absInstanceIndex else: - selectedInstanceIndex = UsdImaging.GL.ALL_INSTANCES + selectedInstanceIndex = UsdImagingGL.GL.ALL_INSTANCES selectedPrim = self._stage.GetPrimAtPath(selectedPrimPath) @@ -1850,7 +1850,7 @@ def setInstanceSelection(self, path, instanceIndex, selected): if selected: if not self._selectedInstances.has_key(path): self._selectedInstances[path] = set() - if instanceIndex == UsdImaging.GL.ALL_INSTANCES: + if instanceIndex == UsdImagingGL.GL.ALL_INSTANCES: del self._selectedInstances[path] else: self._selectedInstances[path].add(instanceIndex) diff --git a/third_party/katana/lib/usdKatana/CMakeLists.txt b/third_party/katana/lib/usdKatana/CMakeLists.txt index 61e9ed09a0..a6ccd8fdfc 100644 --- a/third_party/katana/lib/usdKatana/CMakeLists.txt +++ b/third_party/katana/lib/usdKatana/CMakeLists.txt @@ -11,6 +11,7 @@ pxr_shared_library(${PXR_PACKAGE} sdf usd usdImaging + usdImagingGL usdShade usdGeom usdRi diff --git a/third_party/katana/lib/usdKatana/cache.cpp b/third_party/katana/lib/usdKatana/cache.cpp index 6df6a19a87..e2613e8157 100644 --- a/third_party/katana/lib/usdKatana/cache.cpp +++ b/third_party/katana/lib/usdKatana/cache.cpp @@ -27,7 +27,7 @@ #include "pxr/usd/ar/resolver.h" -#include "pxr/usdImaging/usdImaging/gl.h" +#include "pxr/usdImaging/usdImagingGL/gl.h" #include "pxr/usd/usdUtils/stageCache.h" #include "pxr/usd/sdf/layer.h" diff --git a/third_party/katana/plugin/vmp_usd/CMakeLists.txt b/third_party/katana/plugin/vmp_usd/CMakeLists.txt index 1b19c329ac..7777f86adb 100644 --- a/third_party/katana/plugin/vmp_usd/CMakeLists.txt +++ b/third_party/katana/plugin/vmp_usd/CMakeLists.txt @@ -10,6 +10,7 @@ pxr_plugin(${PXR_PACKAGE} usdUtils glf usdImaging + usdImagingGL katanaPluginApi usdKatana diff --git a/third_party/katana/plugin/vmp_usd/usdVMP.cpp b/third_party/katana/plugin/vmp_usd/usdVMP.cpp index 1842b92829..17bdeec433 100644 --- a/third_party/katana/plugin/vmp_usd/usdVMP.cpp +++ b/third_party/katana/plugin/vmp_usd/usdVMP.cpp @@ -146,7 +146,7 @@ USDVMP::setup(FnKat::ViewerModifierInput& input) FnLogWarn(std::string("Cannot compose ") + _prim.GetPath().GetString()); - _params.cullStyle = UsdImagingEngine::CULL_STYLE_BACK_UNLESS_DOUBLE_SIDED; + _params.cullStyle = UsdImagingGLEngine::CULL_STYLE_BACK_UNLESS_DOUBLE_SIDED; _renderer = UsdKatanaCache::GetInstance() .GetRenderer(_stage, _prim, variantString); diff --git a/third_party/katana/plugin/vmp_usd/usdVMP.h b/third_party/katana/plugin/vmp_usd/usdVMP.h index 2df9ead7bf..54edddf2c2 100644 --- a/third_party/katana/plugin/vmp_usd/usdVMP.h +++ b/third_party/katana/plugin/vmp_usd/usdVMP.h @@ -39,7 +39,7 @@ #include "pxr/base/tf/stopwatch.h" #include "pxr/usd/usd/prim.h" #include "pxr/usd/usd/stage.h" -#include "pxr/usdImaging/usdImaging/gl.h" +#include "pxr/usdImaging/usdImagingGL/gl.h" #include "katanaPluginApi/FnViewerModifier.h" #include diff --git a/third_party/maya/lib/pxrUsdMayaGL/CMakeLists.txt b/third_party/maya/lib/pxrUsdMayaGL/CMakeLists.txt index a66c8d6f7e..2c6018f225 100644 --- a/third_party/maya/lib/pxrUsdMayaGL/CMakeLists.txt +++ b/third_party/maya/lib/pxrUsdMayaGL/CMakeLists.txt @@ -13,6 +13,7 @@ pxr_shared_library(${PXR_PACKAGE} sdf usd usdImaging + usdImagingGL usdMaya ${Boost_LIBRARIES} ${GLUT_LIBRARIES} diff --git a/third_party/maya/lib/pxrUsdMayaGL/batchRenderer.h b/third_party/maya/lib/pxrUsdMayaGL/batchRenderer.h index 19e9ac4c8d..3ad480e881 100644 --- a/third_party/maya/lib/pxrUsdMayaGL/batchRenderer.h +++ b/third_party/maya/lib/pxrUsdMayaGL/batchRenderer.h @@ -40,7 +40,6 @@ #include "pxr/imaging/hd/sceneDelegate.h" #include "pxr/imaging/hdx/intersector.h" #include "pxr/usdImaging/usdImaging/delegate.h" -#include "pxr/usdImaging/usdImaging/engine.h" #include "pxr/usdImaging/usdImaging/tokens.h" #include diff --git a/third_party/maya/lib/pxrUsdMayaGL/hdRenderer.cpp b/third_party/maya/lib/pxrUsdMayaGL/hdRenderer.cpp index a4a63ada54..a703e830ef 100644 --- a/third_party/maya/lib/pxrUsdMayaGL/hdRenderer.cpp +++ b/third_party/maya/lib/pxrUsdMayaGL/hdRenderer.cpp @@ -197,7 +197,7 @@ void UsdMayaGLHdRenderer::RenderVp2( params.drawMode = request.drawRequest.token() == UsdMayaGLHdRenderer::DRAW_WIREFRAME ? UsdImagingGL::DRAW_WIREFRAME : UsdImagingGL::DRAW_POINTS; params.enableLighting = false; - params.cullStyle = UsdImagingEngine::CULL_STYLE_NOTHING; + params.cullStyle = UsdImagingGLEngine::CULL_STYLE_NOTHING; params.overrideColor = request.fWireframeColor; @@ -213,7 +213,7 @@ void UsdMayaGLHdRenderer::RenderVp2( params.drawMode = ((request.drawRequest.token() == UsdMayaGLHdRenderer::DRAW_SHADED_FLAT) ? UsdImagingGL::DRAW_GEOM_FLAT : UsdImagingGL::DRAW_GEOM_SMOOTH); params.enableLighting = true; - params.cullStyle = UsdImagingEngine::CULL_STYLE_BACK_UNLESS_DOUBLE_SIDED; + params.cullStyle = UsdImagingGLEngine::CULL_STYLE_BACK_UNLESS_DOUBLE_SIDED; _renderer->Render(_renderedPrim, params); diff --git a/third_party/maya/lib/pxrUsdMayaGL/hdRenderer.h b/third_party/maya/lib/pxrUsdMayaGL/hdRenderer.h index e0ddcdab2f..feb09abae6 100644 --- a/third_party/maya/lib/pxrUsdMayaGL/hdRenderer.h +++ b/third_party/maya/lib/pxrUsdMayaGL/hdRenderer.h @@ -29,7 +29,7 @@ #define PXRUSDMAYAGL_HDRENDERER_H #include "pxr/usd/usd/stage.h" -#include "pxr/usdImaging/usdImaging/gl.h" +#include "pxr/usdImaging/usdImagingGL/gl.h" #include #include #include diff --git a/third_party/maya/lib/pxrUsdMayaGL/proxyDrawOverride.h b/third_party/maya/lib/pxrUsdMayaGL/proxyDrawOverride.h index e29c33e652..fd7f0a5932 100644 --- a/third_party/maya/lib/pxrUsdMayaGL/proxyDrawOverride.h +++ b/third_party/maya/lib/pxrUsdMayaGL/proxyDrawOverride.h @@ -25,7 +25,6 @@ #define PXRUSDMAYAGL_PROXYDRAWOVERRIDE_H #include "pxr/usd/usd/stage.h" -#include "pxr/usdImaging/usdImaging/gl.h" #include "pxrUsdMayaGL/batchRenderer.h" #include "usdMaya/proxyShape.h" From 375c4def9b752527ed71f9ce27e1db4350c8ebfb Mon Sep 17 00:00:00 2001 From: c64kernal Date: Mon, 17 Oct 2016 15:16:04 -0700 Subject: [PATCH 240/380] Fix up CMakeLists.txt for usdImagingGL. (Internal change: 1663198) --- pxr/usdImaging/lib/usdImagingGL/CMakeLists.txt | 3 --- 1 file changed, 3 deletions(-) diff --git a/pxr/usdImaging/lib/usdImagingGL/CMakeLists.txt b/pxr/usdImaging/lib/usdImagingGL/CMakeLists.txt index 2996797426..5df12d9fe6 100644 --- a/pxr/usdImaging/lib/usdImagingGL/CMakeLists.txt +++ b/pxr/usdImaging/lib/usdImagingGL/CMakeLists.txt @@ -62,9 +62,6 @@ pxr_shared_library(usdImagingGL PYTHON_FILES __init__.py - - RESOURCE_FILES - plugInfo.json ) if (QT4_FOUND) From d4d41ba5c3c4e14806dff5218fddc34a314b7ede Mon Sep 17 00:00:00 2001 From: c64kernal Date: Mon, 17 Oct 2016 15:16:10 -0700 Subject: [PATCH 241/380] Fix up CMakeLists.txt for usdImaging. (Internal change: 1663199) --- pxr/usdImaging/lib/usdImaging/CMakeLists.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/pxr/usdImaging/lib/usdImaging/CMakeLists.txt b/pxr/usdImaging/lib/usdImaging/CMakeLists.txt index ef8c26bebf..4f682f3bab 100644 --- a/pxr/usdImaging/lib/usdImaging/CMakeLists.txt +++ b/pxr/usdImaging/lib/usdImaging/CMakeLists.txt @@ -50,7 +50,6 @@ pxr_shared_library(usdImaging shaderAdapter tokens valueCache - taskDelegate basisCurvesAdapter capsuleAdapter coneAdapter From 4c8a41bbf6cc8fc5bfa053ab367b6a9ff71ed554 Mon Sep 17 00:00:00 2001 From: c64kernal Date: Mon, 17 Oct 2016 15:16:18 -0700 Subject: [PATCH 242/380] Missed test update in CMakeLists.txt for usdImagingGL. (Internal change: 1663200) --- pxr/usdImaging/lib/usdImagingGL/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pxr/usdImaging/lib/usdImagingGL/CMakeLists.txt b/pxr/usdImaging/lib/usdImagingGL/CMakeLists.txt index 5df12d9fe6..91f71764b9 100644 --- a/pxr/usdImaging/lib/usdImagingGL/CMakeLists.txt +++ b/pxr/usdImaging/lib/usdImagingGL/CMakeLists.txt @@ -79,6 +79,6 @@ if (QT4_FOUND) Qt4::QtOpenGL CPPFILES unitTestGLDrawing.cpp - testenv/testUsdImagingBasicDrawing.cpp + testenv/testUsdImagingGLBasicDrawing.cpp ) endif() From 06efc02ee0d080850885ee136b75bca5f0b546af Mon Sep 17 00:00:00 2001 From: c64kernal Date: Mon, 17 Oct 2016 15:16:25 -0700 Subject: [PATCH 243/380] More CMakeLists.txt fixes for usdImagingGL. (Internal change: 1663201) --- pxr/usdImaging/lib/usdImagingGL/CMakeLists.txt | 3 --- 1 file changed, 3 deletions(-) diff --git a/pxr/usdImaging/lib/usdImagingGL/CMakeLists.txt b/pxr/usdImaging/lib/usdImagingGL/CMakeLists.txt index 91f71764b9..37510e1c89 100644 --- a/pxr/usdImaging/lib/usdImagingGL/CMakeLists.txt +++ b/pxr/usdImaging/lib/usdImagingGL/CMakeLists.txt @@ -44,9 +44,6 @@ pxr_shared_library(usdImagingGL refEngine taskDelegate - PUBLIC_HEADERS - version.h - PRIVATE_CLASSES defaultTaskDelegate From 586ca85aceb931a92f92f231b42de8a5d2596b5c Mon Sep 17 00:00:00 2001 From: c64kernal Date: Mon, 17 Oct 2016 15:16:30 -0700 Subject: [PATCH 244/380] More CMakeLists.txt fixes for usdImagingGL. (Internal change: 1663209) --- pxr/usdImaging/lib/usdImagingGL/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pxr/usdImaging/lib/usdImagingGL/CMakeLists.txt b/pxr/usdImaging/lib/usdImagingGL/CMakeLists.txt index 37510e1c89..2aaafcedc0 100644 --- a/pxr/usdImaging/lib/usdImagingGL/CMakeLists.txt +++ b/pxr/usdImaging/lib/usdImagingGL/CMakeLists.txt @@ -1,4 +1,4 @@ -set(PXR_PREFIX pxr/usdImagingGL) +set(PXR_PREFIX pxr/usdImaging) set(PXR_PACKAGE usdImagingGL) # Note: both python include directives are included for compatibility. From 22651860a56bf92b8713956e4f44f71270bd488f Mon Sep 17 00:00:00 2001 From: superfunc Date: Mon, 17 Oct 2016 15:24:37 -0700 Subject: [PATCH 245/380] [Pcp] Replace usage of boost with std for static asserts. (Internal change: 1663368) --- pxr/usd/lib/pcp/statistics.cpp | 32 +++++++++++++++++++------------- 1 file changed, 19 insertions(+), 13 deletions(-) diff --git a/pxr/usd/lib/pcp/statistics.cpp b/pxr/usd/lib/pcp/statistics.cpp index 21e09451a1..d89c3813db 100644 --- a/pxr/usd/lib/pcp/statistics.cpp +++ b/pxr/usd/lib/pcp/statistics.cpp @@ -30,8 +30,6 @@ #include "pxr/base/arch/defines.h" -#include - struct Pcp_GraphStats { public: @@ -325,26 +323,34 @@ class Pcp_Statistics } // Assert sizes of structs we want to keep a close eye on. - BOOST_STATIC_ASSERT(sizeof(PcpMapFunction) == 8); - BOOST_STATIC_ASSERT(sizeof(PcpMapExpression) == 8); + static_assert(sizeof(PcpMapFunction) == 8, + "PcpMapFunction must be of size 8"); + static_assert(sizeof(PcpMapExpression) == 8, + "PcpMapExpression must be of size 8"); // This object is 120 bytes when building against libstdc++ // and 96 for libc++ because std::set is 48 bytes in the // former case and 24 bytes in the latter. - BOOST_STATIC_ASSERT(sizeof(PcpMapExpression::_Node) == 120 or - sizeof(PcpMapExpression::_Node) == 96); + static_assert(sizeof(PcpMapExpression::_Node) == 120 || + sizeof(PcpMapExpression::_Node) == 96, + "PcpMapExpression::_Node must be of size 96 or 120"); - BOOST_STATIC_ASSERT(sizeof(PcpLayerStackPtr) == 16); - BOOST_STATIC_ASSERT(sizeof(PcpLayerStackSite) == 24); + static_assert(sizeof(PcpLayerStackPtr) == 16, + "PcpLayerStackPtr must be of size 16"); + static_assert(sizeof(PcpLayerStackSite) == 24, + "PcpLayerStackSite must be of size 24"); // This object is 104 bytes when building against libstdc++ // and 88 for libc++ because std::vector is 40 bytes // in the former case and 24 bytes in the latter. - BOOST_STATIC_ASSERT(sizeof(PcpPrimIndex_Graph) == 104 or - sizeof(PcpPrimIndex_Graph) == 88); - - BOOST_STATIC_ASSERT(sizeof(PcpPrimIndex_Graph::_Node) == 48); - BOOST_STATIC_ASSERT(sizeof(PcpPrimIndex_Graph::_SharedData) == 32); + static_assert(sizeof(PcpPrimIndex_Graph) == 104 || + sizeof(PcpPrimIndex_Graph) == 88, + "PcpPrimIndex_Graph must be of size 88 or 104"); + + static_assert(sizeof(PcpPrimIndex_Graph::_Node) == 48, + "PcpPrimIndex_Graph::_Node must be of size 48"); + static_assert(sizeof(PcpPrimIndex_Graph::_SharedData) == 32, + "PcpPrimIndex_Graph::_SharedData must be of size 32"); } static void PrintPrimIndexStats( From c8db01e2c091517d5a2e3ffe1f1a5f6e07296a26 Mon Sep 17 00:00:00 2001 From: c64kernal Date: Mon, 17 Oct 2016 15:24:48 -0700 Subject: [PATCH 246/380] Simplified getting the composed shaders and fixed compiler warning. (Internal change: 1663496) --- pxr/imaging/lib/hd/drawBatch.h | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/pxr/imaging/lib/hd/drawBatch.h b/pxr/imaging/lib/hd/drawBatch.h index c60ef0abba..63747daf1f 100644 --- a/pxr/imaging/lib/hd/drawBatch.h +++ b/pxr/imaging/lib/hd/drawBatch.h @@ -150,10 +150,7 @@ class Hd_DrawBatch { /// Returns array of composed shaders, this include the shaders passed /// via SetShaders and the shader passed to SetSurfaceShader. HdShaderSharedPtrVector GetComposedShaders() const { - HdShaderSharedPtrVector shaders; - for (int i=0; i<_shaders.size(); i++) { - shaders.push_back(_shaders[i]); - } + HdShaderSharedPtrVector shaders = _shaders; if (_surfaceShader) { shaders.push_back(_surfaceShader); } From fc1ffd8f3c6510a54ae3784061b8ce2d51126928 Mon Sep 17 00:00:00 2001 From: shriramiyer Date: Mon, 17 Oct 2016 15:24:55 -0700 Subject: [PATCH 247/380] Modify GetPathForInstanceIndex to return the instanceContext and the rprimPath separately. Also, the instanceContext is now returned as a vector of paths instead of a vector of UsdPrims, since Hd/SceneDelegate can't know about USD. In the case where the last instance root itself is the rprim, the returned rprimPath will be empty. The last path in instanceContext will contain the rprim path. Updated unit test to exercise the modifications to the API. (Internal change: 1663831) --- pxr/imaging/lib/hd/sceneDelegate.cpp | 4 ++- pxr/imaging/lib/hd/sceneDelegate.h | 4 ++- pxr/usdImaging/lib/usdImaging/delegate.cpp | 14 +++++++--- pxr/usdImaging/lib/usdImaging/delegate.h | 4 +-- .../lib/usdImaging/instanceAdapter.cpp | 28 +++++++++---------- .../lib/usdImaging/instanceAdapter.h | 4 +-- pxr/usdImaging/lib/usdImaging/primAdapter.cpp | 3 +- pxr/usdImaging/lib/usdImaging/primAdapter.h | 3 +- pxr/usdImaging/lib/usdImaging/version.h | 8 ++++-- pxr/usdImaging/lib/usdImagingGL/engine.cpp | 3 +- pxr/usdImaging/lib/usdImagingGL/engine.h | 3 +- pxr/usdImaging/lib/usdImagingGL/gl.cpp | 11 +++++--- pxr/usdImaging/lib/usdImagingGL/gl.h | 3 +- pxr/usdImaging/lib/usdImagingGL/hdEngine.cpp | 12 ++++---- pxr/usdImaging/lib/usdImagingGL/hdEngine.h | 11 ++++---- 15 files changed, 68 insertions(+), 47 deletions(-) diff --git a/pxr/imaging/lib/hd/sceneDelegate.cpp b/pxr/imaging/lib/hd/sceneDelegate.cpp index 029f435a20..394a1bcd01 100644 --- a/pxr/imaging/lib/hd/sceneDelegate.cpp +++ b/pxr/imaging/lib/hd/sceneDelegate.cpp @@ -183,7 +183,9 @@ HdSceneDelegate::GetInstancerTransform(SdfPath const &instancerId, SdfPath HdSceneDelegate::GetPathForInstanceIndex(const SdfPath &protoPrimPath, int instanceIndex, - int *absoluteInstanceIndex) + int *absoluteInstanceIndex, + SdfPath * rprimPath, + SdfPathVector *instanceContext) { return SdfPath(); } diff --git a/pxr/imaging/lib/hd/sceneDelegate.h b/pxr/imaging/lib/hd/sceneDelegate.h index f2c48291c0..334fbd44e7 100644 --- a/pxr/imaging/lib/hd/sceneDelegate.h +++ b/pxr/imaging/lib/hd/sceneDelegate.h @@ -200,7 +200,9 @@ class HdSceneDelegate { /// virtual SdfPath GetPathForInstanceIndex(const SdfPath &protoPrimPath, int instanceIndex, - int *absoluteInstanceIndex); + int *absoluteInstanceIndex, + SdfPath * rprimPath=NULL, + SdfPathVector *instanceContext=NULL); // -----------------------------------------------------------------------// /// \name SurfaceShader Aspects diff --git a/pxr/usdImaging/lib/usdImaging/delegate.cpp b/pxr/usdImaging/lib/usdImaging/delegate.cpp index f229f35e3c..955026ea03 100644 --- a/pxr/usdImaging/lib/usdImaging/delegate.cpp +++ b/pxr/usdImaging/lib/usdImaging/delegate.cpp @@ -2188,7 +2188,8 @@ SdfPath UsdImagingDelegate::GetPathForInstanceIndex(SdfPath const& protoPrimPath, int instanceIndex, int *absoluteInstanceIndex, - std::vector *instanceContext) + SdfPath *rprimPath, + SdfPathVector *instanceContext) { SdfPath usdPath = GetPathForUsd(protoPrimPath); @@ -2200,7 +2201,8 @@ UsdImagingDelegate::GetPathForInstanceIndex(SdfPath const& protoPrimPath, int instanceCount = 0; int protoInstanceIndex = instanceIndex; int absIndex = ALL_INSTANCES; // PointInstancer may overwrite. - std::vector resolvedInstanceContext; + SdfPathVector resolvedInstanceContext; + SdfPath resolvedRprimPath; do { _AdapterSharedPtr const& adapter = _AdapterLookupByPath(usdPath); if (not TF_VERIFY(adapter, "can't find primAdapter for %s", @@ -2210,7 +2212,7 @@ UsdImagingDelegate::GetPathForInstanceIndex(SdfPath const& protoPrimPath, usdPath = adapter->GetPathForInstanceIndex( usdPath, instanceIndex, &instanceCount, &absIndex, - &resolvedInstanceContext); + &resolvedRprimPath, &resolvedInstanceContext); if (usdPath.IsEmpty()) { break; @@ -2231,12 +2233,16 @@ UsdImagingDelegate::GetPathForInstanceIndex(SdfPath const& protoPrimPath, TF_DEBUG(USDIMAGING_SELECTION).Msg("GetPathForInstanceIndex(%s, %d) = " "(%s, %d, %s)\n", protoPrimPath.GetText(), protoInstanceIndex, usdPath.GetText(), absIndex, - resolvedInstanceContext.back().GetPath().GetText()); + resolvedInstanceContext.back().GetText()); if (absoluteInstanceIndex) { *absoluteInstanceIndex = absIndex; } + if (rprimPath) { + *rprimPath = resolvedRprimPath; + } + if (instanceContext) { *instanceContext = resolvedInstanceContext; } diff --git a/pxr/usdImaging/lib/usdImaging/delegate.h b/pxr/usdImaging/lib/usdImaging/delegate.h index 0c1ee40a4b..fb9e741d21 100644 --- a/pxr/usdImaging/lib/usdImaging/delegate.h +++ b/pxr/usdImaging/lib/usdImaging/delegate.h @@ -327,8 +327,8 @@ class UsdImagingDelegate : public HdSceneDelegate, public TfWeakBase { virtual SdfPath GetPathForInstanceIndex(const SdfPath &protoPrimPath, int instanceIndex, int *absoluteInstanceIndex, - std::vector * - instanceContext=NULL); + SdfPath * rprimPath=NULL, + SdfPathVector *instanceContext=NULL); private: typedef TfHashMap _PathToPathMap; diff --git a/pxr/usdImaging/lib/usdImaging/instanceAdapter.cpp b/pxr/usdImaging/lib/usdImaging/instanceAdapter.cpp index 5602057d6e..9652e61d13 100644 --- a/pxr/usdImaging/lib/usdImaging/instanceAdapter.cpp +++ b/pxr/usdImaging/lib/usdImaging/instanceAdapter.cpp @@ -1270,9 +1270,9 @@ struct UsdImagingInstanceAdapter::_GetPathForInstanceIndexFn UsdImagingInstanceAdapter* adapter_, SdfPath const &usdPath_, int instanceIndex_, - std::vector *instanceContextPtr_) + SdfPathVector *instanceContextPaths_) : adapter(adapter_), usdPath(usdPath_), instanceIndex(instanceIndex_), - instanceContextPtr(instanceContextPtr_) + instanceContextPaths(instanceContextPaths_) { } void Initialize(size_t numInstances) @@ -1285,8 +1285,10 @@ struct UsdImagingInstanceAdapter::_GetPathForInstanceIndexFn if (instanceIdx == static_cast(instanceIndex) && instanceContext.size() > 0) { instancePath = instanceContext.back().GetPath(); - if (instanceContextPtr) { - *instanceContextPtr = instanceContext; + if (instanceContextPaths) { + for (const UsdPrim &p: instanceContext) { + instanceContextPaths->push_back(p.GetPath()); + } } return false; @@ -1298,7 +1300,7 @@ struct UsdImagingInstanceAdapter::_GetPathForInstanceIndexFn SdfPath usdPath; SdfPath instancePath; int instanceIndex; - std::vector *instanceContextPtr; + SdfPathVector *instanceContextPaths; }; /*virtual*/ @@ -1306,7 +1308,8 @@ SdfPath UsdImagingInstanceAdapter::GetPathForInstanceIndex( SdfPath const &path, int instanceIndex, int *instanceCount, int *absoluteInstanceIndex, - std::vector *instanceContext) + SdfPath * rprimPath, + SdfPathVector *instanceContext) { UsdPrim const &prim = _GetPrim(path.GetAbsoluteRootOrPrimPath()); if (not prim) { @@ -1336,6 +1339,7 @@ UsdImagingInstanceAdapter::GetPathForInstanceIndex( instanceIndex, instanceCount, absoluteInstanceIndex, + rprimPath, instanceContext); } } @@ -1387,19 +1391,13 @@ UsdImagingInstanceAdapter::GetPathForInstanceIndex( *instanceCount = 0; } - // instanceContext doesn't contain the rprim itself yet. Add it here. - if (instanceContext) { + if (rprimPath) { const auto rprimPathIt = instIt->second.primMap.find(path); if (rprimPathIt != instIt->second.primMap.end()) { - SdfPath rprimPath = rprimPathIt->second.path; + *rprimPath = rprimPathIt->second.path; TF_DEBUG(USDIMAGING_SELECTION).Msg( - "NI: rprimPath %s\n", rprimPath.GetText()); - - instanceContext->push_back(prim.GetStage()->GetPrimAtPath(rprimPath)); - } else { - TF_WARN("Failed to find rprimPath for <%s>, instanceIndex = %d", - path.GetText(), instanceIndex); + "NI: rprimPath %s\n", rprimPath->GetText()); } } diff --git a/pxr/usdImaging/lib/usdImaging/instanceAdapter.h b/pxr/usdImaging/lib/usdImaging/instanceAdapter.h index 142d25ac6d..495e1e38f7 100644 --- a/pxr/usdImaging/lib/usdImaging/instanceAdapter.h +++ b/pxr/usdImaging/lib/usdImaging/instanceAdapter.h @@ -105,8 +105,8 @@ class UsdImagingInstanceAdapter : public UsdImagingPrimAdapter int instanceIndex, int *instanceCount, int *absoluteInstanceIndex, - std::vector * - instanceContext); + SdfPath * rprimPath=NULL, + SdfPathVector *instanceContext=NULL); virtual SdfPath GetInstancer(SdfPath const &cachePath); diff --git a/pxr/usdImaging/lib/usdImaging/primAdapter.cpp b/pxr/usdImaging/lib/usdImaging/primAdapter.cpp index 14a7b92de2..533e1192b7 100644 --- a/pxr/usdImaging/lib/usdImaging/primAdapter.cpp +++ b/pxr/usdImaging/lib/usdImaging/primAdapter.cpp @@ -114,7 +114,8 @@ UsdImagingPrimAdapter::GetPathForInstanceIndex( int instanceIndex, int *instanceCount, int *absoluteInstanceIndex, - std::vector *instanceContext) + SdfPath * rprimPath, + SdfPathVector *instanceContext) { if (absoluteInstanceIndex) { *absoluteInstanceIndex = UsdImagingDelegate::ALL_INSTANCES; diff --git a/pxr/usdImaging/lib/usdImaging/primAdapter.h b/pxr/usdImaging/lib/usdImaging/primAdapter.h index 7b20d8fffe..bb9d5e2572 100644 --- a/pxr/usdImaging/lib/usdImaging/primAdapter.h +++ b/pxr/usdImaging/lib/usdImaging/primAdapter.h @@ -152,7 +152,8 @@ class UsdImagingPrimAdapter virtual SdfPath GetPathForInstanceIndex( SdfPath const &path, int instanceIndex, int *instanceCountForThisLevel, int *absoluteInstanceIndex, - std::vector *instanceContext); + SdfPath * rprimPath=NULL, + SdfPathVector *instanceContext=NULL); /// Returns the instancer path for given \p instancePath. If it's not /// instanced path, returns empty. diff --git a/pxr/usdImaging/lib/usdImaging/version.h b/pxr/usdImaging/lib/usdImaging/version.h index 4be4eb6010..62f857321e 100644 --- a/pxr/usdImaging/lib/usdImaging/version.h +++ b/pxr/usdImaging/lib/usdImaging/version.h @@ -25,11 +25,13 @@ #define USD_IMAGING_VERSION_H // Version 3 -- add support for nested instancers in InsertInstancer. -// Version 4 -- Populate returns SdfPath, HdxSelectionInstanceMap +// Version 4 -- Populate returns SdfPath, HdxSelectionInstanceMap. // Version 5 -- GetPathForInstanceIndex returns absoluteInstanceIndex. -// Version 6 -- PrimAdater::GetDependPaths +// Version 6 -- PrimAdater::GetDependPaths. // Version 7 -- GetPathForInstanceIndex returns instanceContext. +// Version 8 -- GetPathForInstanceIndex returns instanceContext (as +// SdfPathVector) and rprimPath separately. -#define USD_IMAGING_API 7 +#define USD_IMAGING_API 8 #endif // USD_IMAGING_VERSION_H diff --git a/pxr/usdImaging/lib/usdImagingGL/engine.cpp b/pxr/usdImaging/lib/usdImagingGL/engine.cpp index 83b4bc833d..7de94ab422 100644 --- a/pxr/usdImaging/lib/usdImagingGL/engine.cpp +++ b/pxr/usdImaging/lib/usdImagingGL/engine.cpp @@ -622,7 +622,8 @@ UsdImagingGLEngine::GetPrimPathFromInstanceIndex( SdfPath const& protoPrimPath, int instanceIndex, int *absoluteInstanceIndex, - std::vector *instanceContext) + SdfPath *rprimPath, + SdfPathVector *instanceContext) { return SdfPath(); } diff --git a/pxr/usdImaging/lib/usdImagingGL/engine.h b/pxr/usdImaging/lib/usdImagingGL/engine.h index 59fe50dced..155a0b57f8 100644 --- a/pxr/usdImaging/lib/usdImagingGL/engine.h +++ b/pxr/usdImaging/lib/usdImagingGL/engine.h @@ -299,7 +299,8 @@ class UsdImagingGLEngine : private boost::noncopyable { SdfPath const& protoRprimPath, int instanceIndex, int *absoluteInstanceIndex=NULL, - std::vector *instanceContext=NULL); + SdfPath * rprimPath=NULL, + SdfPathVector *instanceContext=NULL); /// Returns true if the resulting image is fully converged. /// (otherwise, caller may need to call Render() again to refine the result) diff --git a/pxr/usdImaging/lib/usdImagingGL/gl.cpp b/pxr/usdImaging/lib/usdImagingGL/gl.cpp index 2b1e2fddd0..930089550e 100644 --- a/pxr/usdImaging/lib/usdImagingGL/gl.cpp +++ b/pxr/usdImaging/lib/usdImagingGL/gl.cpp @@ -204,13 +204,16 @@ UsdImagingGL::GetPrimPathFromPrimIdColor( /* virtual */ SdfPath -UsdImagingGL::GetPrimPathFromInstanceIndex(const SdfPath& protoPrimPath, - int instanceIndex, - int *absoluteInstanceIndex, - std::vector *instanceContext) +UsdImagingGL::GetPrimPathFromInstanceIndex( + const SdfPath& protoPrimPath, + int instanceIndex, + int *absoluteInstanceIndex, + SdfPath * rprimPath, + SdfPathVector *instanceContext) { return _engine->GetPrimPathFromInstanceIndex(protoPrimPath, instanceIndex, absoluteInstanceIndex, + rprimPath, instanceContext); } diff --git a/pxr/usdImaging/lib/usdImagingGL/gl.h b/pxr/usdImaging/lib/usdImagingGL/gl.h index 779b87dd28..5f8527e7bd 100644 --- a/pxr/usdImaging/lib/usdImagingGL/gl.h +++ b/pxr/usdImaging/lib/usdImagingGL/gl.h @@ -137,7 +137,8 @@ class UsdImagingGL : public UsdImagingGLEngine { const SdfPath& protoPrimPath, int instanceIndex, int *absoluteInstanceIndex = NULL, - std::vector *instanceContext=NULL); + SdfPath * rprimPath=NULL, + SdfPathVector *instanceContext=NULL); virtual bool IsConverged() const; diff --git a/pxr/usdImaging/lib/usdImagingGL/hdEngine.cpp b/pxr/usdImaging/lib/usdImagingGL/hdEngine.cpp index e973d1f4c0..5a65ce3b96 100644 --- a/pxr/usdImaging/lib/usdImagingGL/hdEngine.cpp +++ b/pxr/usdImaging/lib/usdImagingGL/hdEngine.cpp @@ -577,13 +577,15 @@ UsdImagingGLHdEngine::GetPrimPathFromPrimIdColor(GfVec4i const & primIdColor, /* virtual */ SdfPath -UsdImagingGLHdEngine::GetPrimPathFromInstanceIndex(SdfPath const& protoPrimPath, - int instanceIndex, - int *absoluteInstanceIndex, - std::vector *instanceContext) +UsdImagingGLHdEngine::GetPrimPathFromInstanceIndex( + SdfPath const& protoPrimPath, + int instanceIndex, + int *absoluteInstanceIndex, + SdfPath * rprimPath, + SdfPathVector *instanceContext) { return _delegate.GetPathForInstanceIndex(protoPrimPath, instanceIndex, - absoluteInstanceIndex, + absoluteInstanceIndex, rprimPath, instanceContext); } diff --git a/pxr/usdImaging/lib/usdImagingGL/hdEngine.h b/pxr/usdImaging/lib/usdImagingGL/hdEngine.h index 61352d70aa..8f46109196 100644 --- a/pxr/usdImaging/lib/usdImagingGL/hdEngine.h +++ b/pxr/usdImaging/lib/usdImagingGL/hdEngine.h @@ -103,11 +103,12 @@ class UsdImagingGLHdEngine : public UsdImagingGLEngine GfVec4i const& instanceIdColor, int* instanceIndexOut = NULL); - virtual SdfPath GetPrimPathFromInstanceIndex(SdfPath const& protoPrimPath, - int instanceIndex, - int *absoluteInstanceIndex=NULL, - std::vector - *instanceContext=NULL); + virtual SdfPath GetPrimPathFromInstanceIndex( + SdfPath const& protoPrimPath, + int instanceIndex, + int *absoluteInstanceIndex=NULL, + SdfPath * rprimPath=NULL, + SdfPathVector *instanceContext=NULL); virtual bool IsConverged() const; From eca6ca8209bdac34d0c78eaa3f3507ba0737cafe Mon Sep 17 00:00:00 2001 From: c64kernal Date: Mon, 17 Oct 2016 15:25:05 -0700 Subject: [PATCH 248/380] Remove build dependencies on GL, GLU and GLEW from usdImaging. (Internal change: 1663896) --- pxr/usdImaging/lib/usdImaging/CMakeLists.txt | 5 ----- pxr/usdImaging/lib/usdImaging/delegate.cpp | 2 -- 2 files changed, 7 deletions(-) diff --git a/pxr/usdImaging/lib/usdImaging/CMakeLists.txt b/pxr/usdImaging/lib/usdImaging/CMakeLists.txt index 4f682f3bab..ec5ee3a5f2 100644 --- a/pxr/usdImaging/lib/usdImaging/CMakeLists.txt +++ b/pxr/usdImaging/lib/usdImaging/CMakeLists.txt @@ -28,17 +28,12 @@ pxr_shared_library(usdImaging ar ${Boost_PYTHON_LIBRARY} ${PYTHON_LIBRARY} - ${OPENGL_gl_LIBRARY} - ${OPENGL_glu_LIBRARY} - ${GLEW_LIBRARY} ${TBB_tbb_LIBRARY} ${TBB_tbbmalloc_LIBRARY} INCLUDE_DIRS ${PYTHON_INCLUDE_PATH} ${PYTHON_INCLUDE_DIRS} - ${OPENGL_INCLUDE_DIR} - ${GLEW_INCLUDE_DIR} ${TBB_INCLUDE_DIRS} PUBLIC_CLASSES diff --git a/pxr/usdImaging/lib/usdImaging/delegate.cpp b/pxr/usdImaging/lib/usdImaging/delegate.cpp index 955026ea03..bf220316c3 100644 --- a/pxr/usdImaging/lib/usdImaging/delegate.cpp +++ b/pxr/usdImaging/lib/usdImaging/delegate.cpp @@ -21,8 +21,6 @@ // KIND, either express or implied. See the Apache License for the specific // language governing permissions and limitations under the Apache License. // -#include "pxr/imaging/glf/glew.h" - #include "pxr/usdImaging/usdImaging/delegate.h" #include "pxr/usdImaging/usdImaging/adapterRegistry.h" From ca51ca226ac59415a686029b13026e916c303a4b Mon Sep 17 00:00:00 2001 From: pixar-oss Date: Mon, 17 Oct 2016 15:25:55 -0700 Subject: [PATCH 249/380] If value is blocked, set null attr to block instead of skipping. (Internal change: 1663953) --- .../katana/lib/usdKatana/readBlindData.cpp | 28 +++++++++++-------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/third_party/katana/lib/usdKatana/readBlindData.cpp b/third_party/katana/lib/usdKatana/readBlindData.cpp index c74bc1455b..6ebcb86072 100644 --- a/third_party/katana/lib/usdKatana/readBlindData.cpp +++ b/third_party/katana/lib/usdKatana/readBlindData.cpp @@ -40,10 +40,6 @@ PxrUsdKatanaReadBlindData( UsdProperty blindProp = *blindPropIter; if (blindProp.Is()) { UsdAttribute blindAttr = blindProp.As(); - VtValue vtValue; - if (not blindAttr.Get(&vtValue)) { - continue; - } std::string attrName = UsdKatanaBlindDataObject::GetKbdAttributeNameSpace(blindProp).GetString(); @@ -63,13 +59,23 @@ PxrUsdKatanaReadBlindData( attrName += UsdKatanaBlindDataObject::GetGroupBuilderKeyForProperty(blindProp); } - // we set asShaderParam=true because we want the attribute to be - // generated "as is", we *do not* want the prmanStatement style - // "type"/"value" declaration to be created. - attrs.set(attrName, - PxrUsdKatanaUtils::ConvertVtValueToKatAttr( - vtValue, - /* asShaderParam */ true)); + VtValue vtValue; + if (blindAttr.Get(&vtValue)) + { + // we set asShaderParam=true because we want the attribute to be + // generated "as is", we *do not* want the prmanStatement style + // "type"/"value" declaration to be created. + attrs.set(attrName, + PxrUsdKatanaUtils::ConvertVtValueToKatAttr( + vtValue, + /* asShaderParam */ true)); + } + else if (blindAttr.HasAuthoredValueOpinion()) + { + // The attr has a block, so set a null attr + // (see bug 136179 for a better detection api) + attrs.set(attrName, FnKat::NullAttribute()); + } } } } From c0d2f8e29a8c50b5437c931f323402a549ea9903 Mon Sep 17 00:00:00 2001 From: poljere Date: Mon, 17 Oct 2016 15:26:10 -0700 Subject: [PATCH 250/380] In my previous commit d84ec65 I changed the order of operation of HdRprim::Sync so it would first try to get the shader from the delegate and then try to use that shader. This change surfaced an issue down in the UsdImaging where it would not know how to resolve the shader when the instance was a transform (for instance). This change fix the instanceAdapter so it will first try to use any shader in the instance and then use what ever was configured in the master. (Internal change: 1664329) --- pxr/usdImaging/lib/usdImaging/instanceAdapter.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/pxr/usdImaging/lib/usdImaging/instanceAdapter.cpp b/pxr/usdImaging/lib/usdImaging/instanceAdapter.cpp index 9652e61d13..b06f9a53f4 100644 --- a/pxr/usdImaging/lib/usdImaging/instanceAdapter.cpp +++ b/pxr/usdImaging/lib/usdImaging/instanceAdapter.cpp @@ -864,7 +864,13 @@ UsdImagingInstanceAdapter::UpdateForTime(UsdPrim const& prim, } if (requestedBits & HdChangeTracker::DirtySurfaceShader) { - valueCache->GetSurfaceShader(cachePath) = GetShaderBinding(prim); + // First try to get the shader binded in the instance, if no shader + // is bound then access the shader bound to the master prim. + SdfPath p = GetShaderBinding(prim); + if (p.IsEmpty()) { + p = GetShaderBinding(_GetPrim(rproto.path)); + } + valueCache->GetSurfaceShader(cachePath) = p; } } else { From 820987b01b82f4b64885dd7762904a7f36ca0ddf Mon Sep 17 00:00:00 2001 From: takahito-tejima Date: Mon, 17 Oct 2016 15:27:16 -0700 Subject: [PATCH 251/380] [Garch] glDebugWindow adding minimal GL window utilitiy for unit tests. (not implemeneted yet on macos) (Internal change: 1664362) --- pxr/imaging/lib/garch/CMakeLists.txt | 6 + pxr/imaging/lib/garch/glDebugWindow.cpp | 121 ++++++++++ pxr/imaging/lib/garch/glDebugWindow.h | 75 ++++++ .../lib/garch/glPlatformDebugWindowDarwin.h | 47 ++++ .../lib/garch/glPlatformDebugWindowDarwin.mm | 70 ++++++ .../lib/garch/glPlatformDebugWindowGLX.cpp | 204 ++++++++++++++++ .../lib/garch/glPlatformDebugWindowGLX.h | 53 +++++ .../garch/glPlatformDebugWindowWindows.cpp | 223 ++++++++++++++++++ .../lib/garch/glPlatformDebugWindowWindows.h | 57 +++++ 9 files changed, 856 insertions(+) create mode 100644 pxr/imaging/lib/garch/glDebugWindow.cpp create mode 100644 pxr/imaging/lib/garch/glDebugWindow.h create mode 100644 pxr/imaging/lib/garch/glPlatformDebugWindowDarwin.h create mode 100644 pxr/imaging/lib/garch/glPlatformDebugWindowDarwin.mm create mode 100644 pxr/imaging/lib/garch/glPlatformDebugWindowGLX.cpp create mode 100644 pxr/imaging/lib/garch/glPlatformDebugWindowGLX.h create mode 100644 pxr/imaging/lib/garch/glPlatformDebugWindowWindows.cpp create mode 100644 pxr/imaging/lib/garch/glPlatformDebugWindowWindows.h diff --git a/pxr/imaging/lib/garch/CMakeLists.txt b/pxr/imaging/lib/garch/CMakeLists.txt index 1bbfd4e605..9b6a7b976b 100644 --- a/pxr/imaging/lib/garch/CMakeLists.txt +++ b/pxr/imaging/lib/garch/CMakeLists.txt @@ -8,6 +8,8 @@ if(APPLE) elseif(X11_FOUND) set(GLPLATFORMCONTEXT_H glPlatformContextGLX.h) set(GLPLATFORMCONTEXT_CPP glPlatformContextGLX.cpp) + set(GLPLATFORMDEBUGWINDOW glPlatformDebugWindowGLX) + set(GLDEBUGWINDOW glDebugWindow) elseif(WIN32) set(GLPLATFORMCONTEXT_H glPlatformContextWindows.h) set(GLPLATFORMCONTEXT_CPP glPlatformContextWindows.cpp) @@ -27,6 +29,7 @@ pxr_shared_library(garch PUBLIC_CLASSES glPlatformContext glPlatformDebugContext + ${GLDEBUGWINDOW} PUBLIC_HEADERS gl.h @@ -35,6 +38,9 @@ pxr_shared_library(garch glut.h ${GLPLATFORMCONTEXT_H} + PRIVATE_CLASSES + ${GLPLATFORMDEBUGWINDOW} + CPPFILES moduleDeps.cpp ${GLPLATFORMCONTEXT_CPP} diff --git a/pxr/imaging/lib/garch/glDebugWindow.cpp b/pxr/imaging/lib/garch/glDebugWindow.cpp new file mode 100644 index 0000000000..5809d942e2 --- /dev/null +++ b/pxr/imaging/lib/garch/glDebugWindow.cpp @@ -0,0 +1,121 @@ +// +// 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. +// + +#include "pxr/imaging/garch/glDebugWindow.h" +#include "pxr/imaging/garch/glPlatformDebugContext.h" +#include "pxr/base/arch/defines.h" + +#if defined ARCH_OS_LINUX +#include "pxr/imaging/garch/glPlatformDebugWindowGLX.h" +#elif defined ARCH_OS_DARWIN +#include "pxr/imaging/garch/glPlatformDebugWindowDarwin.h" +#elif defined ARCH_OS_WINDOWS +#include "pxr/imaging/garch/glPlatformDebugWindowWin.h" +#endif + +GarchGLDebugWindow::GarchGLDebugWindow(const char *title, int width, int height) + : _title(title) + , _width(width) + , _height(height) +{ + _private.reset(new Garch_GLPlatformDebugWindow(this)); +} + +GarchGLDebugWindow::~GarchGLDebugWindow() +{ +} + +void +GarchGLDebugWindow::Init() +{ + _private->Init(_title.c_str(), _width, _height); +} + +void +GarchGLDebugWindow::Run() +{ + _private->Run(); +} + +void +GarchGLDebugWindow::ExitApp() +{ + _private->ExitApp(); +} + +/* virtual */ +void +GarchGLDebugWindow::OnInitializeGL() +{ +} + +/* virtual */ +void +GarchGLDebugWindow::OnUninitializeGL() +{ +} + +/* virtual */ +void +GarchGLDebugWindow::OnResize(int w, int h) +{ + _width = w; + _height = h; +} + +/* virtual */ +void +GarchGLDebugWindow::OnIdle() +{ +} + +/* virtual */ +void +GarchGLDebugWindow::OnPaintGL() +{ +} + +/* virtual */ +void +GarchGLDebugWindow::OnKeyRelease(int key) +{ +} + +/* virtual */ +void +GarchGLDebugWindow::OnMousePress(int button, int x, int y, int modKeys) +{ +} + +/* virtual */ +void +GarchGLDebugWindow::OnMouseRelease(int button, int x, int y, int modKeys) +{ +} + +/* virtual */ +void +GarchGLDebugWindow::OnMouseMove(int x, int y, int modKeys) +{ +} diff --git a/pxr/imaging/lib/garch/glDebugWindow.h b/pxr/imaging/lib/garch/glDebugWindow.h new file mode 100644 index 0000000000..8a5b7dbf58 --- /dev/null +++ b/pxr/imaging/lib/garch/glDebugWindow.h @@ -0,0 +1,75 @@ +// +// 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 GARCH_GLDEBUGWINDOW_H +#define GARCH_GLDEBUGWINDOW_H + +#include + +class Garch_GLPlatformDebugWindow; + +/// \class GarchGLDebugWindow +/// +/// Platform specific minimum GL widget for unit tests. +/// +class GarchGLDebugWindow { +public: + GarchGLDebugWindow(const char *title, int width, int height); + virtual ~GarchGLDebugWindow(); + + void Init(); + void Run(); + void ExitApp(); + + int GetWidth() const { return _width; } + int GetHeight() const { return _height; } + + enum Buttons { + Button1 = 0, + Button2 = 1, + Button3 = 2 + }; + enum ModifierKeys { + None = 0, + Shift = 1, + Alt = 2, + Ctrl = 4 + }; + + virtual void OnInitializeGL(); + virtual void OnUninitializeGL(); + virtual void OnResize(int w, int h); + virtual void OnIdle(); + virtual void OnPaintGL(); + virtual void OnKeyRelease(int key); + virtual void OnMousePress(int button, int x, int y, int modKeys); + virtual void OnMouseRelease(int button, int x, int y, int modKeys); + virtual void OnMouseMove(int x, int y, int modKeys); + +private: + boost::scoped_ptr _private; + std::string _title; + int _width, _height; +}; + +#endif // GARCH_GLDEBUGWINDOW_H diff --git a/pxr/imaging/lib/garch/glPlatformDebugWindowDarwin.h b/pxr/imaging/lib/garch/glPlatformDebugWindowDarwin.h new file mode 100644 index 0000000000..8bdd714ebd --- /dev/null +++ b/pxr/imaging/lib/garch/glPlatformDebugWindowDarwin.h @@ -0,0 +1,47 @@ +// +// 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 GARCH_GLPLATFORM_DEBUG_WINDOW_DARWIN_H +#define GARCH_GLPLATFORM_DEBUG_WINDOW_DARWIN_H + +#include + +class GarchGLDebugWindow; + +/// \class Garch_GLPlatformDebugWindow +/// +class Garch_GLPlatformDebugWindow +{ +public: + Garch_GLPlatformDebugWindow(GarchGLDebugWindow *w); + + void Init(const char *title, int width, int height, int nSamples=1); + void Run(); + void ExitApp(); + +private: + bool _running; + GarchGLDebugWindow *_callback; +}; + +#endif // GARCH_GLPLATFORM_DEBUG_WINDOW_DARWIN_H diff --git a/pxr/imaging/lib/garch/glPlatformDebugWindowDarwin.mm b/pxr/imaging/lib/garch/glPlatformDebugWindowDarwin.mm new file mode 100644 index 0000000000..b3b51375ed --- /dev/null +++ b/pxr/imaging/lib/garch/glPlatformDebugWindowDarwin.mm @@ -0,0 +1,70 @@ +// +// 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. +// + +#include "pxr/imaging/garch/glDebugWindow.h" +#include "pxr/imaging/garch/glPlatformDebugWindowDarwin.h" + +#include "pxr/base/arch/defines.h" +#include "pxr/base/tf/diagnostic.h" + +// --------------------------------------------------------------------------- + +Garch_GLPlatformDebugWindow::Garch_GLPlatformDebugWindow(GarchGLDebugWindow *w) + : _running(false) + , _callback(w) +{ +} + +void +Garch_GLPlatformDebugWindow::Init(const char *title, + int width, int height, int nSamples) +{ + // XXX: todo: implement window and context initialization + + _callback->OnInitializeGL(); +} + +static int +Garch_GetModifierKeys(int state) +{ + int keys = 0; + // if (state & ShiftMask) keys |= GarchGLDebugWindow::Shift; + // if (state & ControlMask) keys |= GarchGLDebugWindow::Ctrl; + // if (state & Mod1Mask) keys |= GarchGLDebugWindow::Alt; + return keys; +} + +void +Garch_GLPlatformDebugWindow::Run() +{ + _running = true; + + // XXX: todo: implement event loop +} + +void +Garch_GLPlatformDebugWindow::ExitApp() +{ + _running = false; +} diff --git a/pxr/imaging/lib/garch/glPlatformDebugWindowGLX.cpp b/pxr/imaging/lib/garch/glPlatformDebugWindowGLX.cpp new file mode 100644 index 0000000000..b2c4909c60 --- /dev/null +++ b/pxr/imaging/lib/garch/glPlatformDebugWindowGLX.cpp @@ -0,0 +1,204 @@ +// +// 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. +// + +#include "pxr/imaging/garch/glDebugWindow.h" +#include "pxr/imaging/garch/glPlatformDebugWindowGLX.h" +#include "pxr/imaging/garch/glPlatformDebugContext.h" + +#include "pxr/base/arch/defines.h" +#include "pxr/base/tf/diagnostic.h" + +typedef GLXContext (*GLXCREATECONTEXTATTRIBSARBPROC)(Display*, GLXFBConfig, GLXContext, Bool, const int*); + +// --------------------------------------------------------------------------- + +Garch_GLPlatformDebugWindow::Garch_GLPlatformDebugWindow(GarchGLDebugWindow *w) + : _running(false) + , _callback(w) + , _display(NULL) +{ +} + +void +Garch_GLPlatformDebugWindow::Init(const char *title, + int width, int height, int nSamples) +{ + int attrib[] = { + GLX_RENDER_TYPE, GLX_RGBA_BIT, + GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT, + GLX_DOUBLEBUFFER, True, + GLX_RED_SIZE, 8, + GLX_GREEN_SIZE, 8, + GLX_BLUE_SIZE, 8, + GLX_DEPTH_SIZE, 24, + GLX_SAMPLE_BUFFERS, (nSamples > 1 ? 1 : 0), + GLX_SAMPLES, nSamples, + None + }; + + _display = XOpenDisplay(NULL); + int screen = DefaultScreen(_display); + Window root = RootWindow(_display, screen); + + // X window + int fbcount; + GLXFBConfig *fbc = glXChooseFBConfig(_display, screen, attrib, &fbcount); + if (not fbc) { + TF_FATAL_ERROR("glXChooseFBConfig failed"); + exit(1); + } + + XVisualInfo *visinfo = glXGetVisualFromFBConfig(_display, fbc[0]); + if (not visinfo) { + TF_FATAL_ERROR("glXGetVisualFromFBConfig failed"); + exit(1); + } + + XSetWindowAttributes attr; + attr.background_pixel = 0; + attr.border_pixel = 0; + attr.colormap = XCreateColormap(_display, root, visinfo->visual, AllocNone); + attr.event_mask = + StructureNotifyMask | ExposureMask | KeyPressMask | KeyReleaseMask | + PointerMotionMask | ButtonPressMask | ButtonReleaseMask; + + _window = XCreateWindow(_display, root, 0, 0, + width, height, 0, + visinfo->depth, + InputOutput, + visinfo->visual, + CWBackPixel|CWBorderPixel|CWColormap|CWEventMask, + &attr); + XStoreName(_display, _window, title); + + // GL context + GLXCREATECONTEXTATTRIBSARBPROC glXCreateContextAttribsARB + = (GLXCREATECONTEXTATTRIBSARBPROC) glXGetProcAddress( + (const GLubyte*)"glXCreateContextAttribsARB"); + + int attribs[] = { 0 }; + GLXContext tmpCtx = glXCreateContextAttribsARB(_display, fbc[0], 0, true, attribs); + glXMakeCurrent(_display, _window, tmpCtx); + + // switch to the debug context + _glContext.reset(new GarchGLPlatformDebugContext(4, 5, true, true)); + _glContext->makeCurrent(); + glXDestroyContext(_display, tmpCtx); + + _callback->OnInitializeGL(); +} + +static int +Garch_GetButton(unsigned int button) +{ + if (button == Button1) return 0; + else if (button == Button2) return 1; + else if (button == Button3) return 2; + return 0; +} + +static int +Garch_GetModifierKeys(int state) +{ + int keys = 0; + if (state & ShiftMask) keys |= GarchGLDebugWindow::Shift; + if (state & ControlMask) keys |= GarchGLDebugWindow::Ctrl; + if (state & Mod1Mask) keys |= GarchGLDebugWindow::Alt; + return keys; +} + +void +Garch_GLPlatformDebugWindow::Run() +{ + if (not _display) return; + + XMapWindow(_display, _window); + + _running = true; + XEvent event; + + while (_running) { + while (XPending(_display)) { + + XNextEvent(_display, &event); + + switch(event.type) { + case Expose: + break; + case ConfigureNotify: + _callback->OnResize(event.xconfigure.width, + event.xconfigure.height); + break; + case ButtonPress: + _callback->OnMousePress( + Garch_GetButton(event.xbutton.button), + event.xbutton.x, + event.xbutton.y, + Garch_GetModifierKeys(event.xbutton.state)); + break; + case ButtonRelease: + _callback->OnMouseRelease( + Garch_GetButton(event.xbutton.button), + event.xbutton.x, + event.xbutton.y, + Garch_GetModifierKeys(event.xbutton.state)); + break; + case MotionNotify: + _callback->OnMouseMove( + event.xmotion.x, event.xmotion.y, + Garch_GetModifierKeys(event.xbutton.state)); + break; + case KeyRelease: + { + char key; + XLookupString(&event.xkey, &key, 1, NULL, NULL); + _callback->OnKeyRelease(key); + break; + } + } + } + _glContext->makeCurrent(); + + // XXX: this should be constant interval + _callback->OnIdle(); + + _callback->OnPaintGL(); + + glFinish(); + glXSwapBuffers(_display, _window); + } + + _callback->OnUninitializeGL(); + + glXMakeCurrent(_display, 0, 0); + _glContext.reset(); + XDestroyWindow(_display, _window); + XCloseDisplay(_display); +} + +void +Garch_GLPlatformDebugWindow::ExitApp() +{ + _running = false; +} diff --git a/pxr/imaging/lib/garch/glPlatformDebugWindowGLX.h b/pxr/imaging/lib/garch/glPlatformDebugWindowGLX.h new file mode 100644 index 0000000000..08370c6fb5 --- /dev/null +++ b/pxr/imaging/lib/garch/glPlatformDebugWindowGLX.h @@ -0,0 +1,53 @@ +// +// 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 GARCH_GLPLATFORM_DEBUG_WINDOW_GLX_H +#define GARCH_GLPLATFORM_DEBUG_WINDOW_GLX_H + +#include +#include +#include + +class GarchGLDebugWindow; +class GarchGLPlatformDebugContext; + +/// \class Garch_GLPlatformDebugWindow +/// +class Garch_GLPlatformDebugWindow +{ +public: + Garch_GLPlatformDebugWindow(GarchGLDebugWindow *w); + + void Init(const char *title, int width, int height, int nSamples=1); + void Run(); + void ExitApp(); + +private: + bool _running; + GarchGLDebugWindow *_callback; + Display *_display; + Window _window; + boost::scoped_ptr _glContext; +}; + +#endif // GARCH_GLPLATFORM_DEBUG_WINDOW_GLX_H diff --git a/pxr/imaging/lib/garch/glPlatformDebugWindowWindows.cpp b/pxr/imaging/lib/garch/glPlatformDebugWindowWindows.cpp new file mode 100644 index 0000000000..869f9307fd --- /dev/null +++ b/pxr/imaging/lib/garch/glPlatformDebugWindowWindows.cpp @@ -0,0 +1,223 @@ +// +// 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. +// + +#include "pxr/imaging/garch/glDebugWindow.h" +#include "pxr/imaging/garch/glPlatformDebugWindowWindows.h" + +#include "pxr/base/arch/defines.h" +#include "pxr/base/tf/diagnostic.h" + +// --------------------------------------------------------------------------- +Garch_GLPlatformDebugWindow::_className = _T("GarchGLDebugWindow"); + +Garch_GLPlatformDebugWindow::Garch_GLPlatformDebugWindow(GarchGLDebugWindow *w) + : _running(false) + , _hWND(NULL) + , _hDC(NULL) + , _hGLRC(NULL) +{ +} + +void +Garch_GLPlatformDebugWindow::Init(const char *title, + int width, int height, int nSamples) +{ + // platform initialize + WNDCLASS wc; + HINSTANCE _hInstnace = GetModuleHandle(NULL); + if (GetClassInfo(_hInstance, _className, &wc) == 0) { + ZeroMemory(&wc, sizeof(WNDCLASS)); + + wc.lpfnWndProc = MsgProc; // XXX: + wc.hInstance = _hInstance; + wc.style = CS_OWNDC | CS_HREDRAW | CS_VREDRAW; + wc.hCursor = LoadCursor(NULL, IDC_ARROW); + wc.lpszClassName = _className; + + if (RegisterClass(&wc) == 0) { + TF_FATAL_ERROR("RegisterClass failed"); + exit(1); + } + } + + // XXX: todo: add support multi sampling + + DWORD flags = WS_CLIPSIBLINGS|WS_CLIPCHILDREN; + DWORD exFlags = 0; + + _hWND = CreateWindowEX(exFlags, _className, + title, flags, 100, 100, width, height, + (HWND)NULL, (HMENU)NULL, _hInstance, + (LPVOID)NULL); + ShowWidnow(_hWND, SW_SHOW); + _windows[_hWND] = this; + _hDC = GetDC(_hWND); + + PIXELFORMATDESCRIPTOR pfd; + ZeroMemory(&pfd, sizeof(PIXELFORMATDESCRIPTOR)); + + pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR); + pfd.nVersion = 1; + pfd.dwFlags = PFD_DRAW_TO_WINDOW|PFD_SUPPORT_OPENGL|PFD_DOUBLEBUFFER; + pfd.iPixelType = PFD_TYPE_RGBA; + pfd.cRedBits = 8; + pfd.cGreenBits = 8; + pfd.cBlueBits = 8; + pfd.cAlphaBits = 8; + pfd.cColorBits = 24; + pfd.cDepthBits = 24; + pfd.cStencilBits = 8; + + int pixelformat = ChoosePixelFormat(_hDC, &pfd); + + if (SetPixelFormat(_hDC, pixelformat, &pfd) == 0) { + TF_FATAL_ERROR("SetPixelFormat failed"); + exit(1); + } + + _hGLRC = wglCreateContext(_hDC); + if (_hGLRC == 0) { + TF_FATAL_ERROR("wglCreateContext failed"); + exit(1); + } + + wglMakeCurrent(_hDC, _hGLRC); + _callback->OnInitializeGL(); +} + +static int +Garch_GetModifierKeys(WPARAM wParam) +{ + int keys = 0; + if (wParam & MK_SHIFT) keys |= GarchGLDebugWindow::Shift; + if (wParam & MK_CONTROL) keys |= GarchGLDebugWindow::Ctrl; + if (HIBYTE(GetKeyState(VK_MENU)) & 0x80) + keys |= GarchGLDebugWindow::Alt; + return keys; +} + +/* static */ +Garch_GLPlatformDebugWindow * +Garch_GLPlatformDebugWindow::_GetWindowByHandle(HWND hWND) +{ + std::map::iterator it = + _windows.find(hWND); + if (it != _windows.end()) { + return it->second; + } + return NULL; +} + +/* static */ +LRESULT WINAPI +Garch_GLPlatformDebugWindow::_MsgProc(HWND hWnd, UINT msg, + WPARAM wParam, LPARAM lParam) +{ + Garch_GLPlatformDebugWindow *window + = Garch_GLPlatformDebugWindow::GetWindowByHandle(hWnd); + if (not TF_VERIFY(window)) { + return 0; + } + + int x = LOWORD(lParam); + int y = HIWORD(lParam); + switch (msg) { + case WM_SIZE: + window->_callback->OnResize( + HIWORD(lParam), LOWORD(lParam)); + break; + case WM_LBUTTONDOWN: + window->_callback->OnMousePressEvent( + /*button=*/0, x, y, Garch_GetModifierKeys(wParam)); + break; + case WM_MBUTTONDOWN: + window->_callback->OnMousePressEvent( + /*button=*/1, x, y, Garch_GetModifierKeys(wParam)); + break; + case WM_RBUTTONDOWN: + window->_callback->OnMousePressEvent( + /*button=*/2, x, y, Garch_GetModifierKeys(wParam)); + break; + case WM_LBUTTONUP: + window->_callback->OnMouseReleaseEvent( + /*button=*/0, x, y, Garch_GetModifierKeys(wParam)); + break; + case WM_MBUTTONUP: + window->_callback->OnMouseReleaseEvent( + /*button=*/1, x, y, Garch_GetModifierKeys(wParam)); + break; + case WM_RBUTTONUP: + window->_callback->OnMouseReleaseEvent( + /*button=*/2, x, y, Garch_GetModifierKeys(wParam)); + break; + case WM_MOUSEMOVE: + window->_callback->OnMouseMoveEvent( + x, y, Garch_GetModifierKeys(wParam)); + break; + case WM_KEYUP: + window->_callback->OnKeyReleaseEvent(key); + break; + } + return DefWindowProc(hWnd, msg, wParam, lParam); +} + +void +Garch_GLPlatformDebugWindow::Run() +{ + if (not _display) return; + + _running = true; + + MSG msg = {0}; + while (_running and message != WM_QUIT) { + if (PeekMessage(&msg, 0, 0, 0, PM_REMOVE)) { + TranslateMessage(&msg); + DispatchMessage(&msg); + } else { + // make current + wglMakeCurrent(_hDC, _hGLRC); + + // XXX: this should be constant interval + _callback->OnIdle(); + _callback->OnPaintGL(); + + glFinish(); + + SwapBuffers(_hDC); + } + } + _callback->OnUninitializeGL(); + + whlMakeCurrent(0, 0); + // release GL + wglDeleteContext(_hGLRC); + + _windows.remove(_hWND); +} + +void +Garch_GLPlatformDebugWindow::ExitApp() +{ + _running = false; +} diff --git a/pxr/imaging/lib/garch/glPlatformDebugWindowWindows.h b/pxr/imaging/lib/garch/glPlatformDebugWindowWindows.h new file mode 100644 index 0000000000..b266202ac1 --- /dev/null +++ b/pxr/imaging/lib/garch/glPlatformDebugWindowWindows.h @@ -0,0 +1,57 @@ +// +// 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 GARCH_GLPLATFORM_DEBUG_WINDOW_WINDOWS_H +#define GARCH_GLPLATFORM_DEBUG_WINDOW_WINDOWS_H + +#include + +class GarchGLDebugWindow; + +/// \class Garch_GLPlatformDebugWindow +/// +class Garch_GLPlatformDebugWindow +{ +public: + Garch_GLPlatformDebugWindow(GarchGLDebugWindow *w); + + void Init(const char *title, int width, int height, int nSamples=1); + void Run(); + void ExitApp(); + +private: + static Garch_GLPlatformDebugWindow *_GetWindowByHandle(HWND); + static LRESULT WINAPI _MsgProc(HWND hWnd, UINT msg, + WPARAM wParam, LPARAM lParam); + static std::map _windows; + + bool _running; + GarchGLDebugWindow *_callback; + HINSTANCE _hInstance; + HWND _hWND; + HDC _hDC; + HGLRC _hGLRC; + const char *_className; +}; + +#endif // GARCH_GLPLATFORM_DEBUG_WINDOW_WINDOWS_H From 6645f2ff5d23440758edcbf7ea9754aa869a3eed Mon Sep 17 00:00:00 2001 From: blevin Date: Mon, 17 Oct 2016 15:27:28 -0700 Subject: [PATCH 252/380] Pcp: Variant node culling attempt #2. Node-culling is a crucial optimization in Pcp composition that is a win against the natural tendency for scene structure to accumulate down namespace. The basic idea is that, as we walk down namespace, we can prune off branches of the composition structure as soon as we know they contribute no further opinions. However, the rules for which nodes we can cull are subtle due to certain features that require preserving empty structure. But it turns out we can be more aggressive with variant culling than we had been. (Internal change: 1664515) --- pxr/usd/lib/pcp/primIndex.cpp | 85 ++++++++++++++++++++++------------- 1 file changed, 55 insertions(+), 30 deletions(-) diff --git a/pxr/usd/lib/pcp/primIndex.cpp b/pxr/usd/lib/pcp/primIndex.cpp index 935aa38759..436174f40f 100644 --- a/pxr/usd/lib/pcp/primIndex.cpp +++ b/pxr/usd/lib/pcp/primIndex.cpp @@ -381,6 +381,7 @@ static void Pcp_BuildPrimIndex( const PcpLayerStackSite & site, const PcpLayerStackSite & rootSite, + int ancestorRecursionDepth, bool evaluateImpliedSpecializes, bool evaluateVariants, bool directNodeShouldContributeSpecs, @@ -697,6 +698,9 @@ struct Pcp_PrimIndexer // The root site for the prim indexing process. PcpLayerStackSite rootSite; + // Total depth of ancestral recursion. + int ancestorRecursionDepth; + // Context for the prim index we are building. PcpPrimIndexInputs inputs; PcpPrimIndexOutputs* outputs; @@ -736,7 +740,8 @@ struct Pcp_PrimIndexer #endif // PCP_DIAGNOSTIC_VALIDATION Pcp_PrimIndexer() - : outputs(0) + : ancestorRecursionDepth(0) + , outputs(0) , previousFrame(0) , handledRelocations(false) , evaluateImpliedSpecializes(true) @@ -1362,6 +1367,7 @@ _AddArc( PcpPrimIndexOutputs childOutputs; Pcp_BuildPrimIndex( site, indexer->rootSite, + indexer->ancestorRecursionDepth, evaluateImpliedSpecializes, evaluateVariants, directNodeShouldContributeSpecs, @@ -2928,33 +2934,34 @@ _ComposeVariantSelectionForNode( return false; } +// Check the tree of nodes rooted at the given node for any node +// representing a prior selection for the given variant set. static bool -_ComposeVariantSelectionForSubtree( +_FindPriorVariantSelection( const PcpNodeRef& node, - const SdfPath& pathInNode, + int ancestorRecursionDepth, const std::string & vset, std::string *vsel, - PcpNodeRef *nodeWithVsel, - PcpPrimIndexOutputs *outputs) + PcpNodeRef *nodeWithVsel) { - // Compose variant selection in strong-to-weak order. - if (_ComposeVariantSelectionForNode( - node, pathInNode, vset, vsel, nodeWithVsel, outputs)) { - return true; + if (node.GetArcType() == PcpArcTypeVariant && + node.GetDepthBelowIntroduction() == ancestorRecursionDepth) { + // If this node represents a variant selection at the same + // effective depth of namespace, check its selection. + const std::pair nodeVsel = + node.GetPathAtIntroduction().GetVariantSelection(); + if (nodeVsel.first == vset) { + *vsel = nodeVsel.second; + *nodeWithVsel = node; + return true; + } } - TF_FOR_ALL(child, Pcp_GetChildrenRange(node)) { - const PcpNodeRef& childNode = *child; - const SdfPath pathInChildNode = - childNode.GetMapToParent().MapTargetToSource(pathInNode); - - if (not pathInChildNode.IsEmpty() and - _ComposeVariantSelectionForSubtree( - *child, pathInChildNode, vset, vsel, nodeWithVsel, outputs)) { + if (_FindPriorVariantSelection( + *child, ancestorRecursionDepth, vset, vsel, nodeWithVsel)) { return true; } } - return false; } @@ -3026,6 +3033,7 @@ _ComposeVariantSelectionAcrossStackFrames( static bool _ComposeVariantSelection( + int ancestorRecursionDepth, PcpPrimIndex_StackFrame *previousFrame, PcpNodeRef node, const SdfPath &pathInNode, @@ -3039,6 +3047,27 @@ _ComposeVariantSelection( TF_VERIFY(not pathInNode.ContainsPrimVariantSelection(), pathInNode.GetText()); + // First check if we have already resolved this variant set. + // Try all nodes in all parent frames; ancestorRecursionDepth + // accounts for any ancestral recursion. + { + PcpNodeRef rootNode = node.GetRootNode(); + PcpPrimIndex_StackFrame *prevFrame = previousFrame; + while (rootNode) { + if (_FindPriorVariantSelection(rootNode, + ancestorRecursionDepth, + vset, vsel, nodeWithVsel)) { + return true; + } + if (prevFrame) { + rootNode = prevFrame->parentNode.GetRootNode(); + prevFrame = prevFrame->previousFrame; + } else { + break; + } + } + } + // We want to look for variant selections in all nodes that have been // added up to this point. Because Pcp follows all other arcs it // encounters (except payloads) before variants, Pcp may pick up variant @@ -3218,7 +3247,8 @@ _EvalNodeVariants( // Determine the variant selection for this set. std::string vsel; PcpNodeRef nodeWithVsel; - _ComposeVariantSelection(indexer->previousFrame, node, + _ComposeVariantSelection(indexer->ancestorRecursionDepth, + indexer->previousFrame, node, node.GetPath().StripAllVariantSelections(), vset, &vsel, &nodeWithVsel, indexer->outputs); @@ -3733,16 +3763,6 @@ _NodeCanBeCulled( return false; } - // We cannot cull any nodes that directly OR ancestrally provide - // variant selections. Variant selections from ancestral sites are - // necessary when evaluating variants in a recursive prim indexing - // call. Otherwise, the recursive call may wind up using a different - // selection than what had been used in the parent index. - // See TrickyInheritsInVariants2 for an example of this. - if (node.HasVariantSelections()) { - return false; - } - // CsdPrim::GetBases wants to return the path of all prims in the // composed scene from which this prim inherits opinions. To ensure // Csd has all the info it needs for this, Pcp has to avoid culling any @@ -3828,6 +3848,7 @@ static void _BuildInitialPrimIndexFromAncestor( const PcpLayerStackSite &site, const PcpLayerStackSite &rootSite, + int ancestorRecursionDepth, PcpPrimIndex_StackFrame *previousFrame, bool evaluateImpliedSpecializes, bool directNodeShouldContributeSpecs, @@ -3870,6 +3891,7 @@ _BuildInitialPrimIndexFromAncestor( site.path.GetParentPath()); Pcp_BuildPrimIndex(parentSite, parentSite, + ancestorRecursionDepth+1, evaluateImpliedSpecializes, /* Always pick up ancestral opinions from variants evaluateVariants = */ true, @@ -3944,6 +3966,7 @@ static void Pcp_BuildPrimIndex( const PcpLayerStackSite & site, const PcpLayerStackSite& rootSite, + int ancestorRecursionDepth, bool evaluateImpliedSpecializes, bool evaluateVariants, bool directNodeShouldContributeSpecs, @@ -3988,7 +4011,7 @@ Pcp_BuildPrimIndex( // other arcs introduced by namespace ancestors that might // contribute opinions to this child. _BuildInitialPrimIndexFromAncestor( - site, rootSite, previousFrame, + site, rootSite, ancestorRecursionDepth, previousFrame, evaluateImpliedSpecializes, directNodeShouldContributeSpecs, inputs, outputs); @@ -3997,6 +4020,7 @@ Pcp_BuildPrimIndex( // Initialize the task list. Pcp_PrimIndexer indexer; indexer.rootSite = rootSite; + indexer.ancestorRecursionDepth = ancestorRecursionDepth; indexer.inputs = inputs; indexer.outputs = outputs; indexer.previousFrame = previousFrame; @@ -4067,6 +4091,7 @@ PcpComputePrimIndex( const PcpLayerStackSite site(layerStack, primPath); Pcp_BuildPrimIndex(site, site, + /* ancestorRecursionDepth = */ 0, /* evaluateImpliedSpecializes = */ true, /* evaluateVariants = */ true, /* directNodeShouldContributeSpecs = */ true, From 5d625916579f7895856cefd34ab019d1a39f9ae1 Mon Sep 17 00:00:00 2001 From: mrawde Date: Mon, 17 Oct 2016 15:29:50 -0700 Subject: [PATCH 253/380] wrap GetWorldPath and SetWorldPath. (Internal change: 1664537) --- pxr/usd/lib/usdGeom/wrapXformCache.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/pxr/usd/lib/usdGeom/wrapXformCache.cpp b/pxr/usd/lib/usdGeom/wrapXformCache.cpp index 732c5c7d1f..2c4439ab96 100644 --- a/pxr/usd/lib/usdGeom/wrapXformCache.cpp +++ b/pxr/usd/lib/usdGeom/wrapXformCache.cpp @@ -40,6 +40,11 @@ void wrapUsdGeomXformCache() .def("Clear", &XformCache::Clear) .def("SetTime", &XformCache::SetTime, arg("time")) .def("GetTime", &XformCache::GetTime) + + .def("SetWorldPath", &XformCache::SetWorldPath, arg("path")) + .def("GetWorldPath", &XformCache::GetWorldPath, + return_value_policy()) + .def("Swap", &XformCache::Swap, arg("other")) ; } From 22c321daf30d61129d8e45456e22722cd299ddd3 Mon Sep 17 00:00:00 2001 From: takahito-tejima Date: Mon, 17 Oct 2016 15:29:58 -0700 Subject: [PATCH 254/380] [Hd, Hdx] remove Qt dependency remove Qt dependency from Hd and Hdx. unit tests use GarchGLDebugWindow instead. (Internal change: 1664580) --- pxr/imaging/lib/hd/CMakeLists.txt | 28 ++-- pxr/imaging/lib/hd/unitTestGLDrawing.cpp | 169 ++++++++------------ pxr/imaging/lib/hd/unitTestGLDrawing.h | 4 +- pxr/imaging/lib/hdx/CMakeLists.txt | 1 + pxr/imaging/lib/hdx/unitTestGLDrawing.cpp | 180 +++++++--------------- pxr/imaging/lib/hdx/unitTestGLDrawing.h | 10 +- 6 files changed, 136 insertions(+), 256 deletions(-) diff --git a/pxr/imaging/lib/hd/CMakeLists.txt b/pxr/imaging/lib/hd/CMakeLists.txt index 7726f82d06..c9eb4a4ae8 100644 --- a/pxr/imaging/lib/hd/CMakeLists.txt +++ b/pxr/imaging/lib/hd/CMakeLists.txt @@ -2,9 +2,6 @@ set(PXR_PREFIX pxr/imaging) set(PXR_PACKAGE hd) set(optionalPublicClasses "") -if (QT4_FOUND) - list(APPEND optionalPrivateClasses unitTestHelper) -endif() if (OPENSUBDIV_HAS_GLSL_TRANSFORM_FEEDBACK) add_definitions(-DOPENSUBDIV_HAS_GLSL_TRANSFORM_FEEDBACK) @@ -121,6 +118,7 @@ pxr_shared_library(hd subdivision subdivision3 unitTestDelegate + unitTestHelper vertexAdjacency ${optionalPrivateClasses} @@ -145,16 +143,16 @@ pxr_shared_library(hd shaders/renderPassShader.glslfx ) -if (QT4_FOUND) - pxr_build_test(testHdBasicDrawing - LIBRARIES - hd - glf - glfq - Qt4::QtCore - Qt4::QtOpenGL - CPPFILES - unitTestGLDrawing.cpp - testenv/testHdBasicDrawing.cpp - ) +if (X11_FOUND AND NOT APPLE) +pxr_build_test(testHdBasicDrawing + LIBRARIES + hd + garch + glf + CPPFILES + unitTestGLDrawing.cpp + testenv/testHdBasicDrawing.cpp +) +endif() + endif() diff --git a/pxr/imaging/lib/hd/unitTestGLDrawing.cpp b/pxr/imaging/lib/hd/unitTestGLDrawing.cpp index 7ddaaa1e49..be4171f952 100644 --- a/pxr/imaging/lib/hd/unitTestGLDrawing.cpp +++ b/pxr/imaging/lib/hd/unitTestGLDrawing.cpp @@ -26,7 +26,7 @@ #include "pxr/imaging/hd/unitTestGLDrawing.h" #include "pxr/imaging/glf/diagnostic.h" #include "pxr/imaging/glf/drawTarget.h" -#include "pxr/imaging/glfq/glDebugContext.h" +#include "pxr/imaging/garch/glDebugWindow.h" #include "pxr/base/gf/frustum.h" #include "pxr/base/gf/matrix4d.h" @@ -34,36 +34,16 @@ #include "pxr/base/gf/vec2i.h" #include "pxr/base/gf/vec4d.h" -#include -#include -#include -#include - #include -//////////////////////////////////////////////////////////// - -static QGLFormat -_GetGLFormat() -{ - QGLFormat fmt; - fmt.setDoubleBuffer(true); - fmt.setDepth(true); - fmt.setAlpha(true); - fmt.setStencil(true); - //fmt.setSampleBuffers(1); - //fmt.setSamples(4); - return fmt; -} - -class Hd_UnitTestDrawingQGLWidget : public QGLWidget { +class Hd_UnitTestWindow : public GarchGLDebugWindow { public: - typedef Hd_UnitTestDrawingQGLWidget This; + typedef Hd_UnitTestWindow This; public: - Hd_UnitTestDrawingQGLWidget(Hd_UnitTestGLDrawing * unitTest, - QWidget * parent = NULL); - virtual ~Hd_UnitTestDrawingQGLWidget(); + Hd_UnitTestWindow(Hd_UnitTestGLDrawing * unitTest, + int width, int height); + virtual ~Hd_UnitTestWindow(); void OffscreenTest(); @@ -72,42 +52,37 @@ class Hd_UnitTestDrawingQGLWidget : public QGLWidget { void StartTimer(); -protected: - // QGLWidget overrides - void initializeGL(); - void paintGL(); - - // QWidget overrides - virtual void keyReleaseEvent(QKeyEvent * event); - virtual void mousePressEvent(QMouseEvent * event); - virtual void mouseReleaseEvent(QMouseEvent * event); - virtual void mouseMoveEvent(QMouseEvent * event); - - bool eventFilter(QObject *object, QEvent *event); + // GarchGLDebugWindow overrides + virtual void OnInitializeGL(); + virtual void OnUninitializeGL(); + virtual void OnIdle(); + virtual void OnPaintGL(); + virtual void OnKeyRelease(int key); + virtual void OnMousePress(int button, int x, int y, int modKeys); + virtual void OnMouseRelease(int button, int x, int y, int modKeys); + virtual void OnMouseMove(int x, int y, int modKeys); private: Hd_UnitTestGLDrawing *_unitTest; GlfDrawTargetRefPtr _drawTarget; - QTimer *_timer; + bool _animate; }; -Hd_UnitTestDrawingQGLWidget::Hd_UnitTestDrawingQGLWidget( - Hd_UnitTestGLDrawing * unitTest, - QWidget * parent) : - QGLWidget(new GlfQGLDebugContext(_GetGLFormat()), parent), - _unitTest(unitTest) +Hd_UnitTestWindow::Hd_UnitTestWindow( + Hd_UnitTestGLDrawing * unitTest, int w, int h) + : GarchGLDebugWindow("Hd Test", w, h) + , _unitTest(unitTest) + , _animate(false) { - _timer = new QTimer(); - _timer->installEventFilter(this); } -Hd_UnitTestDrawingQGLWidget::~Hd_UnitTestDrawingQGLWidget() +Hd_UnitTestWindow::~Hd_UnitTestWindow() { } /* virtual */ void -Hd_UnitTestDrawingQGLWidget::initializeGL() +Hd_UnitTestWindow::OnInitializeGL() { GlfGlewInit(); GlfRegisterDefaultDebugOutputMessageCallback(); @@ -120,7 +95,7 @@ Hd_UnitTestDrawingQGLWidget::initializeGL() // Create an offscreen draw target which is the same size as this // widget and initialize the unit test with the draw target bound. // - _drawTarget = GlfDrawTarget::New(GfVec2i(width(), height())); + _drawTarget = GlfDrawTarget::New(GfVec2i(GetWidth(), GetHeight())); _drawTarget->Bind(); _drawTarget->AddAttachment("color", GL_RGBA, GL_FLOAT, GL_RGBA); _drawTarget->AddAttachment("depth", GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, @@ -132,14 +107,21 @@ Hd_UnitTestDrawingQGLWidget::initializeGL() /* virtual */ void -Hd_UnitTestDrawingQGLWidget::paintGL() +Hd_UnitTestWindow::OnUninitializeGL() +{ + _drawTarget = GlfDrawTargetRefPtr(); +} + +/* virtual */ +void +Hd_UnitTestWindow::OnPaintGL() { // // Update the draw target's size and execute the unit test with // the draw target bound. // _drawTarget->Bind(); - _drawTarget->SetSize(GfVec2i(width(), height())); + _drawTarget->SetSize(GfVec2i(GetWidth(), GetHeight())); _unitTest->DrawTest(); @@ -152,8 +134,8 @@ Hd_UnitTestDrawingQGLWidget::paintGL() glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); glBindFramebuffer(GL_READ_FRAMEBUFFER, _drawTarget->GetFramebufferId()); - glBlitFramebuffer(0, 0, width(), height(), - 0, 0, width(), height(), + glBlitFramebuffer(0, 0, GetWidth(), GetHeight(), + 0, 0, GetWidth(), GetHeight(), GL_COLOR_BUFFER_BIT, GL_NEAREST); @@ -162,16 +144,10 @@ Hd_UnitTestDrawingQGLWidget::paintGL() } void -Hd_UnitTestDrawingQGLWidget::OffscreenTest() +Hd_UnitTestWindow::OffscreenTest() { - // - // Ask Qt to initialize and draw - // - glInit(); - glDraw(); - _drawTarget->Bind(); - _drawTarget->SetSize(GfVec2i(width(), height())); + _drawTarget->SetSize(GfVec2i(GetWidth(), GetHeight())); _unitTest->OffscreenTest(); @@ -179,23 +155,22 @@ Hd_UnitTestDrawingQGLWidget::OffscreenTest() } void -Hd_UnitTestDrawingQGLWidget::StartTimer() +Hd_UnitTestWindow::StartTimer() { - _timer->start(10); + _animate = true; } -bool -Hd_UnitTestDrawingQGLWidget::eventFilter(QObject *object, QEvent *event) +/* virtual */ +void +Hd_UnitTestWindow::OnIdle() { - if (object == _timer) { + if (_animate) { _unitTest->Idle(); - update(); } - return QGLWidget::eventFilter(object, event); } bool -Hd_UnitTestDrawingQGLWidget::WriteToFile(std::string const & attachment, +Hd_UnitTestWindow::WriteToFile(std::string const & attachment, std::string const & filename) { _drawTarget->Unbind(); @@ -206,52 +181,35 @@ Hd_UnitTestDrawingQGLWidget::WriteToFile(std::string const & attachment, /* virtual */ void -Hd_UnitTestDrawingQGLWidget::keyReleaseEvent(QKeyEvent * event) +Hd_UnitTestWindow::OnKeyRelease(int key) { - switch (event->key()) { - case Qt::Key_Escape: - case Qt::Key_Q: - QApplication::instance()->exit(0); + switch (key) { + case 'q': + ExitApp(); return; } - _unitTest->KeyRelease(event->key()); - glDraw(); + _unitTest->KeyRelease(key); } /* virtual */ void -Hd_UnitTestDrawingQGLWidget::mousePressEvent(QMouseEvent * event) +Hd_UnitTestWindow::OnMousePress(int button, int x, int y, int modKeys) { - int button = 0; - switch(event->button()){ - case Qt::LeftButton: button = 0; break; - case Qt::MidButton: button = 1; break; - case Qt::RightButton: button = 2; break; - default: break; - } - _unitTest->MousePress(button, event->x(), event->y()); + _unitTest->MousePress(button, x, y); } /* virtual */ void -Hd_UnitTestDrawingQGLWidget::mouseReleaseEvent(QMouseEvent * event) +Hd_UnitTestWindow::OnMouseRelease(int button, int x, int y, int modKeys) { - int button = 0; - switch(event->button()){ - case Qt::LeftButton: button = 0; break; - case Qt::MidButton: button = 1; break; - case Qt::RightButton: button = 2; break; - default: break; - } - _unitTest->MouseRelease(button, event->x(), event->y()); + _unitTest->MouseRelease(button, x, y); } /* virtual */ void -Hd_UnitTestDrawingQGLWidget::mouseMoveEvent(QMouseEvent * event) +Hd_UnitTestWindow::OnMouseMove(int x, int y, int modKeys) { - _unitTest->MouseMove(event->x(), event->y()); - glDraw(); + _unitTest->MouseMove(x, y); } //////////////////////////////////////////////////////////// @@ -273,13 +231,13 @@ Hd_UnitTestGLDrawing::~Hd_UnitTestGLDrawing() int Hd_UnitTestGLDrawing::GetWidth() const { - return _widget->width(); + return _widget->GetWidth(); } int Hd_UnitTestGLDrawing::GetHeight() const { - return _widget->height(); + return _widget->GetHeight(); } bool @@ -292,8 +250,6 @@ Hd_UnitTestGLDrawing::WriteToFile(std::string const & attachment, void Hd_UnitTestGLDrawing::RunTest(int argc, char *argv[]) { - QApplication app(argc, argv); - bool offscreen = false; bool animate = false; for (int i=0; iParseArgs(argc, argv); - _widget = new Hd_UnitTestDrawingQGLWidget(this); - _widget->setWindowTitle("Hd Test"); - _widget->resize(640, 480); + _widget = new Hd_UnitTestWindow(this, 640, 480); + _widget->Init(); if (offscreen) { // no GUI mode (automated test) - _widget->hide(); - _widget->makeCurrent(); _widget->OffscreenTest(); - _widget->doneCurrent(); } else { // Interactive mode - _widget->show(); if (animate) _widget->StartTimer(); - app.exec(); + _widget->Run(); } } diff --git a/pxr/imaging/lib/hd/unitTestGLDrawing.h b/pxr/imaging/lib/hd/unitTestGLDrawing.h index 717cd65fd9..32d0c0016f 100644 --- a/pxr/imaging/lib/hd/unitTestGLDrawing.h +++ b/pxr/imaging/lib/hd/unitTestGLDrawing.h @@ -30,7 +30,7 @@ #include -class Hd_UnitTestDrawingQGLWidget; +class Hd_UnitTestWindow; /// \class Hd_UnitTestGLDrawing /// @@ -76,7 +76,7 @@ class Hd_UnitTestGLDrawing { GfFrustum GetFrustum() const; private: - Hd_UnitTestDrawingQGLWidget *_widget; + Hd_UnitTestWindow *_widget; float _rotate[2]; GfVec3f _translate; diff --git a/pxr/imaging/lib/hdx/CMakeLists.txt b/pxr/imaging/lib/hdx/CMakeLists.txt index c60c2ac2ff..331f334eab 100644 --- a/pxr/imaging/lib/hdx/CMakeLists.txt +++ b/pxr/imaging/lib/hdx/CMakeLists.txt @@ -8,6 +8,7 @@ pxr_shared_library(hdx vt gf work + garch glf pxOsd hd diff --git a/pxr/imaging/lib/hdx/unitTestGLDrawing.cpp b/pxr/imaging/lib/hdx/unitTestGLDrawing.cpp index 4ce89f3bdb..e1923ff9e6 100644 --- a/pxr/imaging/lib/hdx/unitTestGLDrawing.cpp +++ b/pxr/imaging/lib/hdx/unitTestGLDrawing.cpp @@ -26,7 +26,7 @@ #include "pxr/imaging/hdx/unitTestGLDrawing.h" #include "pxr/imaging/glf/diagnostic.h" #include "pxr/imaging/glf/drawTarget.h" -#include "pxr/imaging/glfq/glDebugContext.h" +#include "pxr/imaging/garch/glDebugWindow.h" #include "pxr/base/gf/frustum.h" #include "pxr/base/gf/matrix4d.h" @@ -34,36 +34,18 @@ #include "pxr/base/gf/vec2i.h" #include "pxr/base/gf/vec4d.h" -#include -#include -#include -#include - #include //////////////////////////////////////////////////////////// -static QGLFormat -_GetGLFormat() -{ - QGLFormat fmt; - fmt.setDoubleBuffer(true); - fmt.setDepth(true); - fmt.setAlpha(true); - fmt.setStencil(true); - //fmt.setSampleBuffers(1); - //fmt.setSamples(4); - return fmt; -} - -class Hdx_UnitTestDrawingQGLWidget : public QGLWidget { +class Hdx_UnitTestWindow : public GarchGLDebugWindow { public: - typedef Hdx_UnitTestDrawingQGLWidget This; + typedef Hdx_UnitTestWindow This; public: - Hdx_UnitTestDrawingQGLWidget(Hdx_UnitTestGLDrawing * unitTest, - QWidget * parent = NULL); - virtual ~Hdx_UnitTestDrawingQGLWidget(); + Hdx_UnitTestWindow(Hdx_UnitTestGLDrawing * unitTest, + int width, int height); + virtual ~Hdx_UnitTestWindow(); void OffscreenTest(); @@ -72,42 +54,34 @@ class Hdx_UnitTestDrawingQGLWidget : public QGLWidget { void StartTimer(); -protected: - // QGLWidget overrides - void initializeGL(); - void paintGL(); - - // QWidget overrides - virtual void keyReleaseEvent(QKeyEvent * event); - virtual void mousePressEvent(QMouseEvent * event); - virtual void mouseReleaseEvent(QMouseEvent * event); - virtual void mouseMoveEvent(QMouseEvent * event); - - bool eventFilter(QObject *object, QEvent *event); + // GarchGLDebugWindow overrides + virtual void OnInitializeGL(); + virtual void OnUninitializeGL(); + virtual void OnPaintGL(); + virtual void OnKeyRelease(int key); + virtual void OnMousePress(int button, int x, int y, int modKeys); + virtual void OnMouseRelease(int button, int x, int y, int modKeys); + virtual void OnMouseMove(int x, int y, int modKeys); private: Hdx_UnitTestGLDrawing *_unitTest; GlfDrawTargetRefPtr _drawTarget; - QTimer *_timer; }; -Hdx_UnitTestDrawingQGLWidget::Hdx_UnitTestDrawingQGLWidget( - Hdx_UnitTestGLDrawing * unitTest, - QWidget * parent) : - QGLWidget(new GlfQGLDebugContext(_GetGLFormat()), parent), - _unitTest(unitTest) +Hdx_UnitTestWindow::Hdx_UnitTestWindow( + Hdx_UnitTestGLDrawing * unitTest, int w, int h) + : GarchGLDebugWindow("Hdx Test", w, h) + , _unitTest(unitTest) { - _timer = new QTimer(); - _timer->installEventFilter(this); } -Hdx_UnitTestDrawingQGLWidget::~Hdx_UnitTestDrawingQGLWidget() +Hdx_UnitTestWindow::~Hdx_UnitTestWindow() { } /* virtual */ void -Hdx_UnitTestDrawingQGLWidget::initializeGL() +Hdx_UnitTestWindow::OnInitializeGL() { GlfGlewInit(); GlfRegisterDefaultDebugOutputMessageCallback(); @@ -120,7 +94,7 @@ Hdx_UnitTestDrawingQGLWidget::initializeGL() // Create an offscreen draw target which is the same size as this // widget and initialize the unit test with the draw target bound. // - _drawTarget = GlfDrawTarget::New(GfVec2i(width(), height())); + _drawTarget = GlfDrawTarget::New(GfVec2i(GetWidth(), GetHeight())); _drawTarget->Bind(); _drawTarget->AddAttachment("color", GL_RGBA, GL_FLOAT, GL_RGBA); _drawTarget->AddAttachment("depth", GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, @@ -132,14 +106,21 @@ Hdx_UnitTestDrawingQGLWidget::initializeGL() /* virtual */ void -Hdx_UnitTestDrawingQGLWidget::paintGL() +Hdx_UnitTestWindow::OnUninitializeGL() +{ + _unitTest->UninitTest(); +} + +/* virtual */ +void +Hdx_UnitTestWindow::OnPaintGL() { // // Update the draw target's size and execute the unit test with // the draw target bound. // _drawTarget->Bind(); - _drawTarget->SetSize(GfVec2i(width(), height())); + _drawTarget->SetSize(GfVec2i(GetWidth(), GetHeight())); _unitTest->DrawTest(); @@ -152,8 +133,8 @@ Hdx_UnitTestDrawingQGLWidget::paintGL() glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); glBindFramebuffer(GL_READ_FRAMEBUFFER, _drawTarget->GetFramebufferId()); - glBlitFramebuffer(0, 0, width(), height(), - 0, 0, width(), height(), + glBlitFramebuffer(0, 0, GetWidth(), GetHeight(), + 0, 0, GetWidth(), GetHeight(), GL_COLOR_BUFFER_BIT, GL_NEAREST); @@ -162,40 +143,18 @@ Hdx_UnitTestDrawingQGLWidget::paintGL() } void -Hdx_UnitTestDrawingQGLWidget::OffscreenTest() +Hdx_UnitTestWindow::OffscreenTest() { - // - // Ask Qt to initialize and draw - // - glInit(); - glDraw(); - _drawTarget->Bind(); - _drawTarget->SetSize(GfVec2i(width(), height())); + _drawTarget->SetSize(GfVec2i(GetWidth(), GetHeight())); _unitTest->OffscreenTest(); _drawTarget->Unbind(); } -void -Hdx_UnitTestDrawingQGLWidget::StartTimer() -{ - _timer->start(10); -} - bool -Hdx_UnitTestDrawingQGLWidget::eventFilter(QObject *object, QEvent *event) -{ - if (object == _timer) { - _unitTest->Idle(); - update(); - } - return QGLWidget::eventFilter(object, event); -} - -bool -Hdx_UnitTestDrawingQGLWidget::WriteToFile(std::string const & attachment, +Hdx_UnitTestWindow::WriteToFile(std::string const & attachment, std::string const & filename) { _drawTarget->Unbind(); @@ -206,55 +165,35 @@ Hdx_UnitTestDrawingQGLWidget::WriteToFile(std::string const & attachment, /* virtual */ void -Hdx_UnitTestDrawingQGLWidget::keyReleaseEvent(QKeyEvent * event) +Hdx_UnitTestWindow::OnKeyRelease(int key) { - switch (event->key()) { - case Qt::Key_Escape: - case Qt::Key_Q: - _unitTest->UninitTest(); - QApplication::instance()->exit(0); + switch (key) { + case 'q': + ExitApp(); return; } - _unitTest->KeyRelease(event->key()); - glDraw(); + _unitTest->KeyRelease(key); } /* virtual */ void -Hdx_UnitTestDrawingQGLWidget::mousePressEvent(QMouseEvent * event) +Hdx_UnitTestWindow::OnMousePress(int button, int x, int y, int modKeys) { - int button = 0; - switch(event->button()){ - case Qt::LeftButton: button = 0; break; - case Qt::MidButton: button = 1; break; - case Qt::RightButton: button = 2; break; - default: break; - } - _unitTest->MousePress(button, event->x(), event->y()); - glDraw(); + _unitTest->MousePress(button, x, y, modKeys); } /* virtual */ void -Hdx_UnitTestDrawingQGLWidget::mouseReleaseEvent(QMouseEvent * event) +Hdx_UnitTestWindow::OnMouseRelease(int button, int x, int y, int modKeys) { - int button = 0; - switch(event->button()){ - case Qt::LeftButton: button = 0; break; - case Qt::MidButton: button = 1; break; - case Qt::RightButton: button = 2; break; - default: break; - } - _unitTest->MouseRelease(button, event->x(), event->y()); - glDraw(); + _unitTest->MouseRelease(button, x, y, modKeys); } /* virtual */ void -Hdx_UnitTestDrawingQGLWidget::mouseMoveEvent(QMouseEvent * event) +Hdx_UnitTestWindow::OnMouseMove(int x, int y, int modKeys) { - _unitTest->MouseMove(event->x(), event->y()); - glDraw(); + _unitTest->MouseMove(x, y, modKeys); } //////////////////////////////////////////////////////////// @@ -276,13 +215,13 @@ Hdx_UnitTestGLDrawing::~Hdx_UnitTestGLDrawing() int Hdx_UnitTestGLDrawing::GetWidth() const { - return _widget->width(); + return _widget->GetWidth(); } int Hdx_UnitTestGLDrawing::GetHeight() const { - return _widget->height(); + return _widget->GetHeight(); } bool @@ -295,8 +234,6 @@ Hdx_UnitTestGLDrawing::WriteToFile(std::string const & attachment, void Hdx_UnitTestGLDrawing::RunTest(int argc, char *argv[]) { - QApplication app(argc, argv); - bool offscreen = false; bool animate = false; for (int i=0; iParseArgs(argc, argv); - _widget = new Hdx_UnitTestDrawingQGLWidget(this); - _widget->setWindowTitle("Hd Test"); - _widget->resize(640, 480); + _widget = new Hdx_UnitTestWindow(this, 640, 480); + _widget->Init(); if (offscreen) { // no GUI mode (automated test) - _widget->hide(); - _widget->makeCurrent(); _widget->OffscreenTest(); - UninitTest(); - _widget->doneCurrent(); } else { // Interactive mode - _widget->show(); - if (animate) _widget->StartTimer(); - app.exec(); + _widget->Run(); } } @@ -343,7 +273,7 @@ Hdx_UnitTestGLDrawing::ParseArgs(int argc, char *argv[]) /* virtual */ void -Hdx_UnitTestGLDrawing::MousePress(int button, int x, int y) +Hdx_UnitTestGLDrawing::MousePress(int button, int x, int y, int modKeys) { _mouseButton[button] = true; _mousePos[0] = x; @@ -352,19 +282,19 @@ Hdx_UnitTestGLDrawing::MousePress(int button, int x, int y) /* virtual */ void -Hdx_UnitTestGLDrawing::MouseRelease(int button, int x, int y) +Hdx_UnitTestGLDrawing::MouseRelease(int button, int x, int y, int modKeys) { _mouseButton[button] = false; } /* virtual */ void -Hdx_UnitTestGLDrawing::MouseMove(int x, int y) +Hdx_UnitTestGLDrawing::MouseMove(int x, int y, int modKeys) { int dx = x - _mousePos[0]; int dy = y - _mousePos[1]; - if (QApplication::keyboardModifiers() & Qt::AltModifier) { + if (modKeys & GarchGLDebugWindow::Alt) { if (_mouseButton[0]) { _rotate[1] += dx; _rotate[0] += dy; diff --git a/pxr/imaging/lib/hdx/unitTestGLDrawing.h b/pxr/imaging/lib/hdx/unitTestGLDrawing.h index d036c92a14..b074989506 100644 --- a/pxr/imaging/lib/hdx/unitTestGLDrawing.h +++ b/pxr/imaging/lib/hdx/unitTestGLDrawing.h @@ -31,7 +31,7 @@ #include -class Hdx_UnitTestDrawingQGLWidget; +class Hdx_UnitTestWindow; /// \class Hdx_UnitTestGLDrawing /// @@ -51,9 +51,9 @@ class Hdx_UnitTestGLDrawing { virtual void DrawTest() = 0; // interactive mode virtual void OffscreenTest() = 0; // offscreen mode (automated test) - virtual void MousePress(int button, int x, int y); - virtual void MouseRelease(int button, int x, int y); - virtual void MouseMove(int x, int y); + virtual void MousePress(int button, int x, int y, int modKeys); + virtual void MouseRelease(int button, int x, int y, int modKeys); + virtual void MouseMove(int x, int y, int modKeys); virtual void KeyRelease(int key); virtual void Idle(); @@ -80,7 +80,7 @@ class Hdx_UnitTestGLDrawing { GfVec2i GetMousePos() const { return GfVec2i(_mousePos[0], _mousePos[1]); } private: - Hdx_UnitTestDrawingQGLWidget *_widget; + Hdx_UnitTestWindow *_widget; float _rotate[2]; GfVec3f _translate; From 030fc77b18585ad1c7e78c92a721d88463f5e5fa Mon Sep 17 00:00:00 2001 From: superfunc Date: Mon, 17 Oct 2016 15:30:09 -0700 Subject: [PATCH 255/380] [Usd] Clip code refactor. Replace TF_FOR_ALL's with C++11 range-for (limited to clips specific files, stage and few others need this treatment, but its outside the scope of this change, methinks.) Change the TimeMapping obj from a std::pair<..> typedef to a struct with named members, update all usage points. Condense some time mapping code in clip.cpp. Put large debug notice into function instead of rewriting it in 5 or so places. Lastly, this adds two sentinel values, Usd_ClipTimesBegin/End which are aliases for std::numeric_limits::max()(-/+) which are authored silently at the end of the clipTimes range. (Internal change: 1664596) --- pxr/usd/lib/usd/clip.cpp | 262 +++++++++++++++------------------- pxr/usd/lib/usd/clip.h | 32 +++-- pxr/usd/lib/usd/clipCache.cpp | 44 +++--- pxr/usd/lib/usd/stage.cpp | 14 +- 4 files changed, 162 insertions(+), 190 deletions(-) diff --git a/pxr/usd/lib/usd/clip.cpp b/pxr/usd/lib/usd/clip.cpp index f6c4a986cf..a395d9443b 100644 --- a/pxr/usd/lib/usd/clip.cpp +++ b/pxr/usd/lib/usd/clip.cpp @@ -59,13 +59,19 @@ UsdIsClipRelatedField(const TfToken& fieldName) struct Usd_SortByExternalTime { - bool operator()( - const Usd_Clip::TimeMapping& x, Usd_Clip::ExternalTime y) const - { return x.first < y; } + bool + operator()(const Usd_Clip::TimeMapping& x, + const Usd_Clip::ExternalTime y) const + { + return x.externalTime < y; + } - bool operator()( - const Usd_Clip::TimeMapping& x, const Usd_Clip::TimeMapping& y) const - { return x.first < y.first; } + bool + operator()(const Usd_Clip::TimeMapping& x, + const Usd_Clip::TimeMapping& y) const + { + return x.externalTime < y.externalTime; + } }; std::ostream& @@ -75,11 +81,9 @@ operator<<(std::ostream& out, const Usd_ClipRefPtr& clip) "%s<%s> (start: %s end: %s)", TfStringify(clip->assetPath).c_str(), clip->primPath.GetString().c_str(), - - (clip->startTime == -std::numeric_limits::max() ? + (clip->startTime == Usd_ClipTimesEarliest ? "-inf" : TfStringPrintf("%.3f", clip->startTime).c_str()), - - (clip->endTime == std::numeric_limits::max() ? + (clip->endTime == Usd_ClipTimesLatest ? "inf" : TfStringPrintf("%.3f", clip->endTime).c_str())); return out; } @@ -133,11 +137,26 @@ _ApplyLayerOffsetToExternalTimes( } const SdfLayerOffset inverse = layerOffset.GetInverse(); - TF_FOR_ALL(it, *array) { - (*it)[0] = inverse * (*it)[0]; + for (auto& time : *array) { + time[0] = inverse * time[0]; } } +static void +_ClipDebugMsg(const PcpNodeRef& node, + const SdfLayerRefPtr& layer, + const TfToken& metadataName) +{ + TF_DEBUG(USD_CLIPS).Msg( + "%s for prim <%s> found in LayerStack %s " + "at spec @%s@<%s>\n", + metadataName.GetText(), + node.GetRootNode().GetPath().GetString().c_str(), + TfStringify(node.GetLayerStack()).c_str(), + layer->GetIdentifier().c_str(), + node.GetPath().GetString().c_str()); +} + void Usd_ResolveClipInfo( const PcpNodeRef& node, @@ -150,17 +169,9 @@ Usd_ResolveClipInfo( for (size_t i = 0, j = layers.size(); i != j; ++i) { const SdfLayerRefPtr& layer = layers[i]; VtArray clipAssetPaths; - if (layer->HasField( - primPath, UsdTokens->clipAssetPaths, &clipAssetPaths)){ - - TF_DEBUG(USD_CLIPS).Msg( - "clipAssetPaths for prim <%s> found in LayerStack %s " - "at spec @%s@<%s>\n", - node.GetRootNode().GetPath().GetString().c_str(), - TfStringify(layerStack).c_str(), - layer->GetIdentifier().c_str(), - primPath.GetString().c_str()); - + if (layer->HasField(primPath, UsdTokens->clipAssetPaths, + &clipAssetPaths)){ + _ClipDebugMsg(node, layer, UsdTokens->clipAssetPaths); clipInfo->indexOfLayerWhereAssetPathsFound = i; clipInfo->clipAssetPaths = boost::in_place(); clipInfo->clipAssetPaths->swap(clipAssetPaths); @@ -181,36 +192,18 @@ Usd_ResolveClipInfo( if (not clipInfo->clipManifestAssetPath) { SdfAssetPath clipManifestAssetPath; - if (layer->HasField( - primPath, UsdTokens->clipManifestAssetPath, - &clipManifestAssetPath)) { - - TF_DEBUG(USD_CLIPS).Msg( - "clipManifestAssetPath for prim <%s> found in LayerStack " - "%s at spec @%s@<%s>\n", - node.GetRootNode().GetPath().GetString().c_str(), - TfStringify(layerStack).c_str(), - layer->GetIdentifier().c_str(), - primPath.GetString().c_str()); - + if (layer->HasField(primPath, UsdTokens->clipManifestAssetPath, + &clipManifestAssetPath)) { + _ClipDebugMsg(node, layer, UsdTokens->clipManifestAssetPath); clipInfo->clipManifestAssetPath = clipManifestAssetPath; } } - if (not clipInfo->clipPrimPath) { std::string clipPrimPath; - if (layer->HasField( - primPath, UsdTokens->clipPrimPath, &clipPrimPath)) { - - TF_DEBUG(USD_CLIPS).Msg( - "clipPrimPath for prim <%s> found in LayerStack %s " - "at spec @%s@<%s>\n", - node.GetRootNode().GetPath().GetString().c_str(), - TfStringify(layerStack).c_str(), - layer->GetIdentifier().c_str(), - primPath.GetString().c_str()); - + if (layer->HasField(primPath, UsdTokens->clipPrimPath, + &clipPrimPath)) { + _ClipDebugMsg(node, layer, UsdTokens->clipPrimPath); clipInfo->clipPrimPath = boost::in_place(); clipInfo->clipPrimPath->swap(clipPrimPath); } @@ -218,20 +211,10 @@ Usd_ResolveClipInfo( if (not clipInfo->clipActive) { VtVec2dArray clipActive; - if (layer->HasField( - primPath, UsdTokens->clipActive, &clipActive)) { - - TF_DEBUG(USD_CLIPS).Msg( - "clipActive for prim <%s> found in LayerStack %s " - "at spec @%s@<%s>\n", - node.GetRootNode().GetPath().GetString().c_str(), - TfStringify(layerStack).c_str(), - layer->GetIdentifier().c_str(), - primPath.GetString().c_str()); - + if (layer->HasField(primPath, UsdTokens->clipActive, &clipActive)) { + _ClipDebugMsg(node, layer, UsdTokens->clipActive); _ApplyLayerOffsetToExternalTimes( _GetLayerOffsetToRoot(node, layer), &clipActive); - clipInfo->clipActive = boost::in_place(); clipInfo->clipActive->swap(clipActive); } @@ -239,20 +222,10 @@ Usd_ResolveClipInfo( if (not clipInfo->clipTimes) { VtVec2dArray clipTimes; - if (layer->HasField( - primPath, UsdTokens->clipTimes, &clipTimes)) { - - TF_DEBUG(USD_CLIPS).Msg( - "clipTimes for prim <%s> found in LayerStack %s " - "at spec @%s@<%s>\n", - node.GetRootNode().GetPath().GetString().c_str(), - TfStringify(layerStack).c_str(), - layer->GetIdentifier().c_str(), - primPath.GetString().c_str()); - + if (layer->HasField(primPath, UsdTokens->clipTimes, &clipTimes)) { + _ClipDebugMsg(node, layer, UsdTokens->clipTimes); _ApplyLayerOffsetToExternalTimes( _GetLayerOffsetToRoot(node, layer), &clipTimes); - clipInfo->clipTimes = boost::in_place(); clipInfo->clipTimes->swap(clipTimes); } @@ -327,11 +300,11 @@ _GetBracketingTimeSegment( // This relies on the Usd_Clip c'tor inserting sentinel values at the // beginning and end of the TimeMappings object. Consumers rely on this // function never returning m1 == m2. - if (time <= times.front().first) { + if (time <= times.front().externalTime) { *m1 = 0; *m2 = 1; } - else if (time >= times.back().first) { + else if (time >= times.back().externalTime) { *m1 = times.size() - 2; *m2 = times.size() - 1; } @@ -425,56 +398,45 @@ Usd_Clip::GetBracketingTimeSamplesForPath( } boost::optional translatedLower, translatedUpper; - - for (int i1 = m1, i2 = m2; i1 >= 0 and i2 >= 0; --i1, --i2) { - const TimeMapping& map1 = times[i1]; - const TimeMapping& map2 = times[i2]; - - const double lower = std::min(map1.second, map2.second); - const double upper = std::max(map1.second, map2.second); - - if (lower <= lowerInClip and lowerInClip <= upper) { - if (map1.second != map2.second) { - translatedLower.reset( - _TranslateTimeToExternal(lowerInClip, map1, map2)); + auto _CanTranslate = [&time, &upperInClip, &lowerInClip, this, + &translatedLower, &translatedUpper]( + const TimeMapping& map1, + const TimeMapping& map2, + const bool translatingLower) { + const double timeInClip = translatingLower ? lowerInClip : upperInClip; + auto& translated = translatingLower ? translatedLower : translatedUpper; + + const double lower = std::min(map1.internalTime, map2.internalTime); + const double upper = std::max(map1.internalTime, map2.internalTime); + + if (lower <= timeInClip and timeInClip <= upper) { + if (map1.internalTime != map2.internalTime) { + translated.reset( + this->_TranslateTimeToExternal(timeInClip, map1, map2)); } else { const bool lowerUpperMatch = (lowerInClip == upperInClip); - if (lowerUpperMatch && time == map1.first) { - translatedLower.reset(map1.first); - } else if (lowerUpperMatch && time == map2.first) { - translatedLower.reset(map2.first); + if (lowerUpperMatch && time == map1.externalTime) { + translated.reset(map1.externalTime); + } else if (lowerUpperMatch && time == map2.externalTime) { + translated.reset(map2.externalTime); } else { - translatedLower.reset(map1.first); + if (translatingLower) { + translated.reset(map1.externalTime); + } else { + translated.reset(map2.externalTime); + } } } - break; } + return static_cast(translated); + }; + + for (int i1 = m1, i2 = m2; i1 >= 0 and i2 >= 0; --i1, --i2) { + if (_CanTranslate(times[i1], times[i2], /*lower=*/true)) { break; } } - for (size_t i1 = m1, i2 = m2; - i1 < times.size() and i2 < times.size(); ++i1, ++i2) { - const TimeMapping& map1 = times[i1]; - const TimeMapping& map2 = times[i2]; - - const double lower = std::min(map1.second, map2.second); - const double upper = std::max(map1.second, map2.second); - - if (lower <= upperInClip and upperInClip <= upper) { - if (map1.second != map2.second) { - translatedUpper.reset( - _TranslateTimeToExternal(upperInClip, map1, map2)); - } else { - const bool lowerUpperMatch = (lowerInClip == upperInClip); - if (lowerUpperMatch && time == map1.first) { - translatedUpper.reset(map1.first); - } else if (lowerUpperMatch && time == map2.first) { - translatedUpper.reset(map2.first); - } else { - translatedUpper.reset(map2.first); - } - } - break; - } + for (size_t i1 = m1, i2 = m2, sz = times.size(); i1 < sz and i2 < sz; ++i1, ++i2) { + if (_CanTranslate(times[i1], times[i2], /*lower=*/false)) { break; } } if (translatedLower and not translatedUpper) { @@ -495,18 +457,18 @@ Usd_Clip::GetBracketingTimeSamplesForPath( // // The 'timingOutsideClip' test case in testUsdModelClips exercises // this behavior. - if (lowerInClip < times.front().second) { - translatedLower.reset(times.front().first); + if (lowerInClip < times.front().internalTime) { + translatedLower.reset(times.front().externalTime); } - else if (lowerInClip > times.back().second) { - translatedLower.reset(times.back().first); + else if (lowerInClip > times.back().internalTime) { + translatedLower.reset(times.back().externalTime); } - if (upperInClip < times.front().second) { - translatedUpper.reset(times.front().first); + if (upperInClip < times.front().internalTime) { + translatedUpper.reset(times.front().externalTime); } - else if (upperInClip > times.back().second) { - translatedUpper.reset(times.back().first); + else if (upperInClip > times.back().internalTime) { + translatedUpper.reset(times.back().externalTime); } } @@ -545,10 +507,10 @@ Usd_Clip::ListTimeSamplesForPath(const SdfAbstractDataSpecId& id) const const TimeMapping& m1 = times[i]; const TimeMapping& m2 = times[i+1]; - if (m1.second <= t and t <= m2.second) { - if (m1.second == m2.second) { - timeSamples.insert(m1.first); - timeSamples.insert(m2.first); + if (m1.internalTime <= t and t <= m2.internalTime) { + if (m1.internalTime == m2.internalTime) { + timeSamples.insert(m1.externalTime); + timeSamples.insert(m2.externalTime); } else { timeSamples.insert(_TranslateTimeToExternal(t, m1, m2)); @@ -563,11 +525,11 @@ Usd_Clip::ListTimeSamplesForPath(const SdfAbstractDataSpecId& id) const // maintain consistency. if (timeSamples.empty()) { for (InternalTime t: timeSamplesInClip) { - if (t < times.front().second) { - timeSamples.insert(times.front().first); + if (t < times.front().internalTime) { + timeSamples.insert(times.front().externalTime); } - else if (t > times.back().second) { - timeSamples.insert(times.back().first); + else if (t > times.back().internalTime) { + timeSamples.insert(times.back().externalTime); } } } @@ -602,19 +564,20 @@ Usd_Clip::_TranslateTimeToInternal(ExternalTime extTime) const // Early out in some special cases to avoid unnecessary // math operations that could introduce precision issues. - if (m1.first == m2.first) { - return m1.second; + if (m1.externalTime == m2.externalTime) { + return m1.internalTime; } - else if (extTime == m1.first) { - return m1.second; + else if (extTime == m1.externalTime) { + return m1.internalTime; } - else if (extTime == m2.first) { - return m2.second; + else if (extTime == m2.externalTime) { + return m2.internalTime; } - return (m2.second - m1.second) / (m2.first - m1.first) - * (extTime - m1.first) - + m1.second; + return (m2.internalTime - m1.internalTime) / + (m2.externalTime - m1.externalTime) + * (extTime - m1.externalTime) + + m1.internalTime; } Usd_Clip::ExternalTime @@ -623,19 +586,20 @@ Usd_Clip::_TranslateTimeToExternal( { // Early out in some special cases to avoid unnecessary // math operations that could introduce precision issues. - if (m1.second == m2.second) { - return m1.first; + if (m1.internalTime == m2.internalTime) { + return m1.externalTime; } - else if (intTime == m1.second) { - return m1.first; + else if (intTime == m1.internalTime) { + return m1.externalTime; } - else if (intTime == m2.second) { - return m2.first; + else if (intTime == m2.internalTime) { + return m2.externalTime; } - return (m2.first - m1.first) / (m2.second - m1.second) - * (intTime - m1.second) - + m1.first; + return (m2.externalTime - m1.externalTime) / + (m2.internalTime - m1.internalTime) + * (intTime - m1.internalTime) + + m1.externalTime; } SdfPropertySpecHandle diff --git a/pxr/usd/lib/usd/clip.h b/pxr/usd/lib/usd/clip.h index b5386d63b1..c109b560a4 100644 --- a/pxr/usd/lib/usd/clip.h +++ b/pxr/usd/lib/usd/clip.h @@ -77,8 +77,8 @@ struct Usd_ResolvedClipInfo { size_t hash = indexOfLayerWhereAssetPathsFound; if (clipAssetPaths) { - TF_FOR_ALL(it, *clipAssetPaths) { - boost::hash_combine(hash, it->GetHash()); + for (const auto& assetPath : *clipAssetPaths) { + boost::hash_combine(hash, assetPath.GetHash()); } } if (clipManifestAssetPath) { @@ -88,15 +88,15 @@ struct Usd_ResolvedClipInfo boost::hash_combine(hash, *clipPrimPath); } if (clipActive) { - TF_FOR_ALL(it, *clipActive) { - boost::hash_combine(hash, (*it)[0]); - boost::hash_combine(hash, (*it)[1]); + for (const auto& active : *clipActive) { + boost::hash_combine(hash, active[0]); + boost::hash_combine(hash, active[1]); } } if (clipTimes) { - TF_FOR_ALL(it, *clipTimes) { - boost::hash_combine(hash, (*it)[0]); - boost::hash_combine(hash, (*it)[1]); + for (const auto& time : *clipTimes) { + boost::hash_combine(hash, time[0]); + boost::hash_combine(hash, time[1]); } } @@ -117,6 +117,10 @@ Usd_ResolveClipInfo( const PcpNodeRef& node, Usd_ResolvedClipInfo* clipInfo); +/// Sentinel values authored on the edges of a clipTimes range. +constexpr double Usd_ClipTimesEarliest = -std::numeric_limits::max(); +constexpr double Usd_ClipTimesLatest = std::numeric_limits::max(); + /// \class Usd_Clip /// /// Represents a clip from which time samples may be read during @@ -149,7 +153,17 @@ struct Usd_Clip : public boost::noncopyable /// offsetting or scaling the animation. typedef double ExternalTime; typedef double InternalTime; - typedef std::pair TimeMapping; + struct TimeMapping { + ExternalTime externalTime; + InternalTime internalTime; + + TimeMapping() {} + TimeMapping(const ExternalTime e, const InternalTime i) + : externalTime(e), + internalTime(i) + {} + }; + typedef std::vector TimeMappings; Usd_Clip(); diff --git a/pxr/usd/lib/usd/clipCache.cpp b/pxr/usd/lib/usd/clipCache.cpp index 0396551341..ac993077b5 100644 --- a/pxr/usd/lib/usd/clipCache.cpp +++ b/pxr/usd/lib/usd/clipCache.cpp @@ -74,12 +74,10 @@ _ValidateClipFields( const size_t numClips = clipAssetPaths.size(); // Each entry in the 'clipAssetPaths' array is the asset path to a clip. - TF_FOR_ALL(it, clipAssetPaths) { - const std::string& assetPath = it->GetAssetPath(); - if (assetPath.empty()) { - *errMsg = TfStringPrintf( - "Empty clip asset path in metadata '%s'", - UsdTokens->clipAssetPaths.GetText()); + for (const auto& clipAssetPath : clipAssetPaths) { + if (clipAssetPath.GetAssetPath().empty()) { + *errMsg = TfStringPrintf("Empty clip asset path in metadata '%s'", + UsdTokens->clipAssetPaths.GetText()); return false; } } @@ -101,8 +99,7 @@ _ValidateClipFields( // Each Vec2d in the 'clipActive' array is a (start frame, clip index) // tuple. Ensure the clip index points to a valid clip. - TF_FOR_ALL(it, clipActive) { - const GfVec2d& startFrameAndClipIndex = *it; + for (const auto& startFrameAndClipIndex : clipActive) { if (startFrameAndClipIndex[1] < 0 or startFrameAndClipIndex[1] >= numClips) { @@ -118,8 +115,7 @@ _ValidateClipFields( // active at the same time. typedef std::map _ActiveClipMap; _ActiveClipMap activeClipMap; - TF_FOR_ALL(it, clipActive) { - const GfVec2d& startFrameAndClipIndex = *it; + for (const auto& startFrameAndClipIndex : clipActive) { std::pair<_ActiveClipMap::iterator, bool> status = activeClipMap.insert(std::make_pair( startFrameAndClipIndex[0], startFrameAndClipIndex[1])); @@ -186,14 +182,14 @@ _AddClipsFromNode( // If a clip manifest has been specified, create a clip for it. if (clipInfo.clipManifestAssetPath) { const Usd_ClipRefPtr clip(new Usd_Clip( - /* clipSourceNode = */ node, + /* clipSourceNode = */ node, /* clipSourceLayerIndex = */ clipInfo.indexOfLayerWhereAssetPathsFound, - /* clipAssetPath = */ *clipInfo.clipManifestAssetPath, - /* clipPrimPath = */ SdfPath(*clipInfo.clipPrimPath), - /* clipStartTime = */ -std::numeric_limits::max(), - /* clipEndTime = */ std::numeric_limits::max(), - /* clipTimes = */ Usd_Clip::TimeMappings())); + /* clipAssetPath = */ *clipInfo.clipManifestAssetPath, + /* clipPrimPath = */ SdfPath(*clipInfo.clipPrimPath), + /* clipStartTime = */ Usd_ClipTimesEarliest, + /* clipEndTime = */ Usd_ClipTimesLatest, + /* clipTimes = */ Usd_Clip::TimeMappings())); clips->manifestClip = clip; } @@ -202,9 +198,9 @@ _AddClipsFromNode( typedef std::map _TimeToClipMap; _TimeToClipMap startTimeToClip; - TF_FOR_ALL(it, *clipInfo.clipActive) { - const double startFrame = (*it)[0]; - const int clipIndex = (int)((*it)[1]); + for (const auto& startFrameAndClipIndex : *clipInfo.clipActive) { + const double startFrame = startFrameAndClipIndex[0]; + const int clipIndex = (int)(startFrameAndClipIndex[1]); const SdfAssetPath& assetPath = (*clipInfo.clipAssetPaths)[clipIndex]; Usd_ClipEntry entry; @@ -227,17 +223,17 @@ _AddClipsFromNode( const Usd_ClipEntry clipEntry = it->second; const Usd_Clip::ExternalTime clipStartTime = - (it == itBegin ? -std::numeric_limits::max() : it->first); + (it == itBegin ? Usd_ClipTimesEarliest : it->first); ++it; const Usd_Clip::ExternalTime clipEndTime = - (it == itEnd ? std::numeric_limits::max() : it->first); + (it == itEnd ? Usd_ClipTimesLatest : it->first); // Generate the clip time mapping that applies to this clip. Usd_Clip::TimeMappings timeMapping; if (clipInfo.clipTimes) { - TF_FOR_ALL(it, *clipInfo.clipTimes) { - const Usd_Clip::ExternalTime extTime = (*it)[0]; - const Usd_Clip::InternalTime intTime = (*it)[1]; + for (const auto& clipTime : *clipInfo.clipTimes) { + const Usd_Clip::ExternalTime extTime = clipTime[0]; + const Usd_Clip::InternalTime intTime = clipTime[1]; if (clipStartTime <= extTime and extTime < clipEndTime) { timeMapping.push_back( diff --git a/pxr/usd/lib/usd/stage.cpp b/pxr/usd/lib/usd/stage.cpp index 5ee42fcbfa..2cc60ee7e1 100644 --- a/pxr/usd/lib/usd/stage.cpp +++ b/pxr/usd/lib/usd/stage.cpp @@ -5564,14 +5564,12 @@ UsdStage::_GetTimeSamplesInIntervalFromResolveInfo( // See _GetBracketingTimeSamplesFromResolveInfo for more // details. if (interval.Contains(clipInterval.GetMin()) - and clipInterval.GetMin() - != -std::numeric_limits::max()) { + and clipInterval.GetMin() != Usd_ClipTimesEarliest) { timesFromAllClips.push_back(clip->startTime); } if (interval.Contains(clipInterval.GetMax()) - and clipInterval.GetMax() - != std::numeric_limits::max()){ + and clipInterval.GetMax() != Usd_ClipTimesLatest){ timesFromAllClips.push_back(clip->endTime); } } @@ -5778,13 +5776,13 @@ UsdStage::_GetBracketingTimeSamplesFromResolveInfo(const Usd_ResolveInfo &info, } if (not foundLower and - clip->startTime != -std::numeric_limits::max()) { + clip->startTime != Usd_ClipTimesEarliest) { *lower = clip->startTime; foundLower = true; } if (not foundUpper and - clip->endTime != std::numeric_limits::max()) { + clip->endTime != Usd_ClipTimesLatest) { *upper = clip->endTime; foundUpper = true; } @@ -5836,8 +5834,8 @@ _ValueFromClipsMightBeTimeVarying(const Usd_ClipRefPtr &firstClipWithSamples, // clip that affects this attribute) and it has more than one time // sample, then it might be time varying. If it only has one sample, // its value must be constant over all time. - if (firstClipWithSamples->startTime == -std::numeric_limits::max() - and firstClipWithSamples->endTime == std::numeric_limits::max()) { + if (firstClipWithSamples->startTime == Usd_ClipTimesEarliest + and firstClipWithSamples->endTime == Usd_ClipTimesLatest) { return firstClipWithSamples->GetNumTimeSamplesForPath(attrSpecId) > 1; } From c5cf5f51422d9750a87729ab5c57484f5ce2ac25 Mon Sep 17 00:00:00 2001 From: takahito-tejima Date: Mon, 17 Oct 2016 15:30:25 -0700 Subject: [PATCH 256/380] [hd] fix CMakeLists.txt remove a stray endif(), inadvertently added at the previous change (Internal change: 1664655) --- pxr/imaging/lib/hd/CMakeLists.txt | 2 -- 1 file changed, 2 deletions(-) diff --git a/pxr/imaging/lib/hd/CMakeLists.txt b/pxr/imaging/lib/hd/CMakeLists.txt index c9eb4a4ae8..a89a5abac4 100644 --- a/pxr/imaging/lib/hd/CMakeLists.txt +++ b/pxr/imaging/lib/hd/CMakeLists.txt @@ -154,5 +154,3 @@ pxr_build_test(testHdBasicDrawing testenv/testHdBasicDrawing.cpp ) endif() - -endif() From 76dea7d04622bbc5c0aa1ced08bd6a4cf2472ab6 Mon Sep 17 00:00:00 2001 From: MWDD Date: Mon, 17 Oct 2016 15:30:34 -0700 Subject: [PATCH 257/380] Fix for crash in copy computation The Hydra mesh Rprim sets up a copy computation to combine vertex buffers that have different formats. When were running the computation, we discovered that the source of the copy didn't have a GPU resource allocated to it. The reason why their was no GPU resource is because the points array was empty, so because of that the packed smooth normals was producing no output and the memory manager was determing the size was 0, so didn't provide a resource for it. This all happens in a deferred way, so we don't know at the time of adding the computation that the result is going to be empty, therefore the copy computation is seeing these empty unallocated buffers at execution time. Changes: - Reordered the copy computation execution function, so that the empty check comes before the is resource allocated check. (Internal change: 1664714) --- pxr/imaging/lib/hd/copyComputation.cpp | 44 +++++++++++++++++++------- 1 file changed, 33 insertions(+), 11 deletions(-) diff --git a/pxr/imaging/lib/hd/copyComputation.cpp b/pxr/imaging/lib/hd/copyComputation.cpp index a74b9bc71a..45039844f1 100644 --- a/pxr/imaging/lib/hd/copyComputation.cpp +++ b/pxr/imaging/lib/hd/copyComputation.cpp @@ -40,34 +40,56 @@ HdCopyComputationGPU::Execute(HdBufferArrayRangeSharedPtr const &range) HD_TRACE_FUNCTION(); HD_MALLOC_TAG_FUNCTION(); - if (not glBufferSubData) return; + if (not glBufferSubData) { + return; + } HdBufferResourceSharedPtr src = _src->GetResource(_name); HdBufferResourceSharedPtr dst = range->GetResource(_name); - if (not TF_VERIFY(src)) return; - if (not TF_VERIFY(dst)) return; - - GLint srcId = src->GetId(); - GLint dstId = dst->GetId(); - - if (not TF_VERIFY(srcId)) return; - if (not TF_VERIFY(dstId)) return; + if (not TF_VERIFY(src)) { + return; + } + if (not TF_VERIFY(dst)) { + return; + } int srcBytesPerElement = src->GetNumComponents() * src->GetComponentSize(); int dstBytesPerElement = dst->GetNumComponents() * dst->GetComponentSize(); - if (not TF_VERIFY(srcBytesPerElement == dstBytesPerElement)) return; + if (not TF_VERIFY(srcBytesPerElement == dstBytesPerElement)) { + return; + } GLintptr readOffset = _src->GetOffset() * srcBytesPerElement; GLintptr writeOffset = range->GetOffset() * dstBytesPerElement; GLsizeiptr copySize = _src->GetNumElements() * srcBytesPerElement; - if (not TF_VERIFY(_src->GetNumElements() <= range->GetNumElements())) return; + if (not TF_VERIFY(_src->GetNumElements() <= range->GetNumElements())) { + return; + } HdRenderContextCaps const &caps = HdRenderContextCaps::GetInstance(); + // Unfortunately at the time the copy computation is added, we don't + // know if the source buffer has 0 length. So we can get here with + // a zero sized copy. if (copySize > 0) { + + // If the buffer's have 0 size, resources for them would not have + // be allocated, so the check for resource allocation has been moved + // until after the copy size check. + + GLint srcId = src->GetId(); + GLint dstId = dst->GetId(); + + if (not TF_VERIFY(srcId)) { + return; + } + if (not TF_VERIFY(dstId)) { + return; + } + HD_PERF_COUNTER_INCR(HdPerfTokens->glCopyBufferSubData); if (caps.directStateAccessEnabled) { From 1429a0868bdac271b0b58da7b01bab208c30a696 Mon Sep 17 00:00:00 2001 From: takahito-tejima Date: Mon, 17 Oct 2016 15:31:15 -0700 Subject: [PATCH 258/380] [garch] osx GL debug window implements GarchGLDebugWindow on osx (still quite minimal) (Internal change: 1664718) --- pxr/imaging/lib/garch/CMakeLists.txt | 11 +- pxr/imaging/lib/garch/glDebugWindow.cpp | 3 +- pxr/imaging/lib/garch/glDebugWindow.h | 4 +- .../lib/garch/glPlatformDebugWindowDarwin.h | 3 - .../lib/garch/glPlatformDebugWindowDarwin.mm | 195 ++++++++++++++++-- pxr/imaging/lib/hd/CMakeLists.txt | 2 +- 6 files changed, 189 insertions(+), 29 deletions(-) diff --git a/pxr/imaging/lib/garch/CMakeLists.txt b/pxr/imaging/lib/garch/CMakeLists.txt index 9b6a7b976b..8d7b7628ca 100644 --- a/pxr/imaging/lib/garch/CMakeLists.txt +++ b/pxr/imaging/lib/garch/CMakeLists.txt @@ -4,11 +4,15 @@ set(PXR_PACKAGE garch) if(APPLE) set(GLPLATFORMCONTEXT_H glPlatformContextDarwin.h) set(GLPLATFORMCONTEXT_CPP glPlatformContextDarwin.mm) + set(GLPLATFORMDEBUGWINDOW_H glPlatformDebugWindowDarwin.h) + set(GLPLATFORMDEBUGWINDOW_CPP glPlatformDebugWindowDarwin.mm) + set(GLDEBUGWINDOW glDebugWindow) FIND_LIBRARY(APPKIT_LIBRARY AppKit) elseif(X11_FOUND) set(GLPLATFORMCONTEXT_H glPlatformContextGLX.h) set(GLPLATFORMCONTEXT_CPP glPlatformContextGLX.cpp) - set(GLPLATFORMDEBUGWINDOW glPlatformDebugWindowGLX) + set(GLPLATFORMDEBUGWINDOW_H glPlatformDebugWindowGLX.h) + set(GLPLATFORMDEBUGWINDOW_CPP glPlatformDebugWindowGLX.cpp) set(GLDEBUGWINDOW glDebugWindow) elseif(WIN32) set(GLPLATFORMCONTEXT_H glPlatformContextWindows.h) @@ -38,12 +42,13 @@ pxr_shared_library(garch glut.h ${GLPLATFORMCONTEXT_H} - PRIVATE_CLASSES - ${GLPLATFORMDEBUGWINDOW} + PRIVATE_HEADERS + ${GLPLATFORMDEBUGWINDOW_H} CPPFILES moduleDeps.cpp ${GLPLATFORMCONTEXT_CPP} + ${GLPLATFORMDEBUGWINDOW_CPP} PYMODULE_CPPFILES module.cpp diff --git a/pxr/imaging/lib/garch/glDebugWindow.cpp b/pxr/imaging/lib/garch/glDebugWindow.cpp index 5809d942e2..b415aa24fa 100644 --- a/pxr/imaging/lib/garch/glDebugWindow.cpp +++ b/pxr/imaging/lib/garch/glDebugWindow.cpp @@ -39,11 +39,12 @@ GarchGLDebugWindow::GarchGLDebugWindow(const char *title, int width, int height) , _width(width) , _height(height) { - _private.reset(new Garch_GLPlatformDebugWindow(this)); + _private = new Garch_GLPlatformDebugWindow(this); } GarchGLDebugWindow::~GarchGLDebugWindow() { + delete _private; } void diff --git a/pxr/imaging/lib/garch/glDebugWindow.h b/pxr/imaging/lib/garch/glDebugWindow.h index 8a5b7dbf58..96dcad7ff9 100644 --- a/pxr/imaging/lib/garch/glDebugWindow.h +++ b/pxr/imaging/lib/garch/glDebugWindow.h @@ -24,7 +24,7 @@ #ifndef GARCH_GLDEBUGWINDOW_H #define GARCH_GLDEBUGWINDOW_H -#include +#include class Garch_GLPlatformDebugWindow; @@ -67,7 +67,7 @@ class GarchGLDebugWindow { virtual void OnMouseMove(int x, int y, int modKeys); private: - boost::scoped_ptr _private; + Garch_GLPlatformDebugWindow *_private; std::string _title; int _width, _height; }; diff --git a/pxr/imaging/lib/garch/glPlatformDebugWindowDarwin.h b/pxr/imaging/lib/garch/glPlatformDebugWindowDarwin.h index 8bdd714ebd..ea8d85a39c 100644 --- a/pxr/imaging/lib/garch/glPlatformDebugWindowDarwin.h +++ b/pxr/imaging/lib/garch/glPlatformDebugWindowDarwin.h @@ -24,8 +24,6 @@ #ifndef GARCH_GLPLATFORM_DEBUG_WINDOW_DARWIN_H #define GARCH_GLPLATFORM_DEBUG_WINDOW_DARWIN_H -#include - class GarchGLDebugWindow; /// \class Garch_GLPlatformDebugWindow @@ -40,7 +38,6 @@ class Garch_GLPlatformDebugWindow void ExitApp(); private: - bool _running; GarchGLDebugWindow *_callback; }; diff --git a/pxr/imaging/lib/garch/glPlatformDebugWindowDarwin.mm b/pxr/imaging/lib/garch/glPlatformDebugWindowDarwin.mm index b3b51375ed..9ab2febf28 100644 --- a/pxr/imaging/lib/garch/glPlatformDebugWindowDarwin.mm +++ b/pxr/imaging/lib/garch/glPlatformDebugWindowDarwin.mm @@ -25,14 +25,161 @@ #include "pxr/imaging/garch/glDebugWindow.h" #include "pxr/imaging/garch/glPlatformDebugWindowDarwin.h" -#include "pxr/base/arch/defines.h" -#include "pxr/base/tf/diagnostic.h" +#import +#import +#import + +static int +Garch_GetModifierKeys(NSUInteger flags) +{ + int keys = 0; + + if (flags & NSEventModifierFlagShift) keys |= GarchGLDebugWindow::Shift; + if (flags & NSEventModifierFlagControl) keys |= GarchGLDebugWindow::Ctrl; + if (flags & NSEventModifierFlagOption) keys |= GarchGLDebugWindow::Alt; + if (flags & NSEventModifierFlagCommand) keys |= GarchGLDebugWindow::Alt; + + return keys; +} + +@class View; + +@interface View : NSOpenGLView +{ + GarchGLDebugWindow *_callback; + NSOpenGLContext *_ctx; +} + +@end + +@implementation View + +-(id)initGL:(NSRect)frame callback:(GarchGLDebugWindow*)cb +{ + _callback = cb; + + int attribs[] = { + NSOpenGLPFAAccelerated, + NSOpenGLPFADoubleBuffer, + NSOpenGLPFADepthSize, 24, + NSOpenGLPFAAlphaSize, 8, + NSOpenGLPFAColorSize, 32, + NSOpenGLPFANoRecovery, + NSOpenGLPFAOpenGLProfile, NSOpenGLProfileVersion3_2Core, + 0 + }; + + NSOpenGLPixelFormat *pf + = [[NSOpenGLPixelFormat alloc] + initWithAttributes:(NSOpenGLPixelFormatAttribute*)attribs]; + self = [self initWithFrame:frame pixelFormat:pf]; + + _ctx = [[NSOpenGLContext alloc] initWithFormat:pf shareContext:nil]; + + [self setOpenGLContext:_ctx]; + + [_ctx makeCurrentContext]; + + _callback->OnInitializeGL(); + + [pf release]; + + return self; +} + +-(bool)acceptsFirstResponder +{ + return YES; +} + +-(void)drawRect:(NSRect)theRect +{ + [_ctx makeCurrentContext]; + + _callback->OnPaintGL(); + + [[self openGLContext] flushBuffer]; +} + +-(void)windowWillClose:(NSNotification*)notification +{ + [[NSApplication sharedApplication] terminate:self]; +} + +-(void)windowDidResize:(NSNotification *)notification +{ + NSRect r = [self frame]; + _callback->OnResize(r.size.width, r.size.height); +} + +-(void)mouseDown:(NSEvent*)event +{ + NSPoint p = [event locationInWindow]; + NSRect r = [self frame]; + NSUInteger modflags = [event modifierFlags]; + _callback->OnMousePress(GarchGLDebugWindow::Button1, + p.x, r.size.height - 1 - p.y, + Garch_GetModifierKeys(modflags)); + + [self setNeedsDisplay:YES]; +} + +-(void)mouseUp:(NSEvent*)event +{ + NSPoint p = [event locationInWindow]; + NSRect r = [self frame]; + NSUInteger modflags = [event modifierFlags]; + _callback->OnMouseRelease(GarchGLDebugWindow::Button1, + p.x, r.size.height - 1 - p.y, + Garch_GetModifierKeys(modflags)); + + [self setNeedsDisplay:YES]; +} + +-(void)mouseDragged:(NSEvent*)event +{ + NSPoint p = [event locationInWindow]; + NSRect r = [self frame]; + NSUInteger modflags = [event modifierFlags]; + _callback->OnMouseMove(p.x, r.size.height - 1 - p.y, + Garch_GetModifierKeys(modflags)); + + [self setNeedsDisplay:YES]; +} + +- (void)keyDown:(NSEvent *)event +{ + int keyCode = [event keyCode]; + int key = 0; + + // XXX shoud call UCKeyTranslate() for non-us keyboard + const int keyMap[] = { 0x00, 'a', 0x0b, 'b', 0x08, 'c', 0x02, 'd', + 0x0e, 'e', 0x03, 'f', 0x05, 'g', 0x04, 'h', + 0x22, 'i', 0x26, 'j', 0x28, 'k', 0x25, 'l', + 0x2e, 'm', 0x2d, 'n', 0x1f, 'o', 0x23, 'p', + 0x0c, 'q', 0x0f, 'r', 0x01, 's', 0x11, 't', + 0x20, 'u', 0x09, 'v', 0x0d, 'w', 0x07, 'x', + 0x10, 'y', 0x06, 'z', 0x31, ' ', -1, -1}; + + for (int i = 0; keyMap[i] >=0; i += 2) { + if (keyMap[i] == keyCode) { + key = keyMap[i+1]; + break; + } + } + if (key) { + _callback->OnKeyRelease(key); + } + + [self setNeedsDisplay:YES]; +} + +@end // --------------------------------------------------------------------------- Garch_GLPlatformDebugWindow::Garch_GLPlatformDebugWindow(GarchGLDebugWindow *w) - : _running(false) - , _callback(w) + : _callback(w) { } @@ -40,31 +187,41 @@ Garch_GLPlatformDebugWindow::Init(const char *title, int width, int height, int nSamples) { - // XXX: todo: implement window and context initialization + [NSApplication sharedApplication]; + [NSApp setActivationPolicy:NSApplicationActivationPolicyRegular]; + id applicationName = [[NSProcessInfo processInfo] processName]; - _callback->OnInitializeGL(); -} + NSRect frame = NSMakeRect(0, 0, width, height); + NSRect viewBounds = NSMakeRect(0, 0, width, height); -static int -Garch_GetModifierKeys(int state) -{ - int keys = 0; - // if (state & ShiftMask) keys |= GarchGLDebugWindow::Shift; - // if (state & ControlMask) keys |= GarchGLDebugWindow::Ctrl; - // if (state & Mod1Mask) keys |= GarchGLDebugWindow::Alt; - return keys; + View *view = [[View alloc] initGL:viewBounds callback:_callback]; + + NSWindow *window = [[NSWindow alloc] + initWithContentRect:frame + styleMask:NSTitledWindowMask + |NSClosableWindowMask + |NSMiniaturizableWindowMask + |NSResizableWindowMask + backing:NSBackingStoreBuffered + defer:NO]; + [window cascadeTopLeftFromPoint:NSMakePoint(20,20)]; + [window setTitle: applicationName]; + [window makeKeyAndOrderFront:nil]; + + [NSApp activateIgnoringOtherApps:YES]; + + [window setContentView:view]; + [window setDelegate:view]; } void Garch_GLPlatformDebugWindow::Run() { - _running = true; - - // XXX: todo: implement event loop + [NSApp run]; } void Garch_GLPlatformDebugWindow::ExitApp() { - _running = false; + [NSApp stop:nil]; } diff --git a/pxr/imaging/lib/hd/CMakeLists.txt b/pxr/imaging/lib/hd/CMakeLists.txt index a89a5abac4..e2b726807f 100644 --- a/pxr/imaging/lib/hd/CMakeLists.txt +++ b/pxr/imaging/lib/hd/CMakeLists.txt @@ -143,7 +143,7 @@ pxr_shared_library(hd shaders/renderPassShader.glslfx ) -if (X11_FOUND AND NOT APPLE) +if (X11_FOUND OR APPLE) pxr_build_test(testHdBasicDrawing LIBRARIES hd From 4e499f5a3bac4bd0e2912fd98f7f08f50addded1 Mon Sep 17 00:00:00 2001 From: poljere Date: Mon, 17 Oct 2016 15:31:22 -0700 Subject: [PATCH 259/380] Makes sure that if we reset the geometric shaders we set them up again. (Internal change: 1664738) --- pxr/imaging/lib/hd/mesh.cpp | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/pxr/imaging/lib/hd/mesh.cpp b/pxr/imaging/lib/hd/mesh.cpp index 9a33c2aa87..3993ebe10f 100644 --- a/pxr/imaging/lib/hd/mesh.cpp +++ b/pxr/imaging/lib/hd/mesh.cpp @@ -1113,12 +1113,17 @@ HdMesh::_GetRepr(TfToken const &reprName, HdChangeTracker::DumpDirtyBits(*dirtyBits); } - // for the bits geometric shader depends on, reset all geometric shaders. + bool needsSetGeometricShader = false; + // For the bits geometric shader depends on, reset all geometric shaders. // they are populated again at the end of _GetRepr. + // Since the dirty bits are cleaned by UpdateDrawItem (because certain + // reprs have multiple draw items) we need to remember if we need to set + // the geometric shader again if (*dirtyBits & (HdChangeTracker::DirtyRefineLevel| HdChangeTracker::DirtyCullStyle| HdChangeTracker::DirtyDoubleSided)) { _ResetGeometricShaders(); + needsSetGeometricShader = true; } // iterate through all reprs to figure out if any requires smoothnormals @@ -1148,9 +1153,7 @@ HdMesh::_GetRepr(TfToken const &reprName, // if we need to rebuild geometric shader, make sure all reprs to have // their geometric shader up-to-date. - if (*dirtyBits & (HdChangeTracker::DirtyRefineLevel| - HdChangeTracker::DirtyCullStyle| - HdChangeTracker::DirtyDoubleSided)) { + if (needsSetGeometricShader) { _SetGeometricShaders(); } From bd780ea9342fd3090b49283abedc59fbddb4d34c Mon Sep 17 00:00:00 2001 From: takahito-tejima Date: Mon, 17 Oct 2016 15:33:33 -0700 Subject: [PATCH 260/380] [usdviewq] use SetCameraState instead of SetCameraStateFromOpenGL. one step forward to remove GL fixed pipeline functions. (for OSX port) (Internal change: 1664742) --- pxr/usdImaging/lib/usdviewq/stageView.py | 32 ++++++++---------------- 1 file changed, 10 insertions(+), 22 deletions(-) diff --git a/pxr/usdImaging/lib/usdviewq/stageView.py b/pxr/usdImaging/lib/usdviewq/stageView.py index 3eafebf91c..459fa3b230 100644 --- a/pxr/usdImaging/lib/usdviewq/stageView.py +++ b/pxr/usdImaging/lib/usdviewq/stageView.py @@ -1234,27 +1234,6 @@ def restoreViewState(self, viewState): self._freeCamera = self._freeCamera.clone() self.update() - - def setupOpenGLViewMatricesForFrustum(self, frustum): - from OpenGL import GL - import ctypes - GLMtx = ctypes.c_double * 16 - MakeGLMtx = lambda m: GLMtx.from_buffer_copy(m) - - GL.glMatrixMode(GL.GL_PROJECTION) - GL.glLoadIdentity() - GL.glMultMatrixd(MakeGLMtx(frustum.ComputeProjectionMatrix())) - - GL.glMatrixMode(GL.GL_MODELVIEW) - GL.glLoadIdentity() - GL.glMultMatrixd(MakeGLMtx(frustum.ComputeViewMatrix())) - - GL.glViewport(0, 0, self.size().width(), self.size().height()) - - GL.glClear(GL.GL_COLOR_BUFFER_BIT|GL.GL_DEPTH_BUFFER_BIT) - - self._renderer.SetCameraStateFromOpenGL() - def drawWireframeCube(self, size): from OpenGL import GL @@ -1313,7 +1292,16 @@ def paintGL(self): cam_up = frustum.ComputeUpVector() cam_right = Gf.Cross(frustum.ComputeViewDirection(), cam_up) - self.setupOpenGLViewMatricesForFrustum(frustum) + self._renderer.SetCameraState( + frustum.ComputeViewMatrix(), + frustum.ComputeProjectionMatrix(), + Gf.Vec4d(0, 0, self.size().width(), self.size().height())) + + # XXX: this is redundant for refEngine, but currently hdEngine + # doesn't call glViewport. + GL.glViewport(0, 0, self.size().width(), self.size().height()) + + GL.glClear(GL.GL_COLOR_BUFFER_BIT|GL.GL_DEPTH_BUFFER_BIT) # Set the clipping planes. self._renderParams.clipPlanes = [Gf.Vec4d(i) for i in From eee1970a488d0914e10b63f74672d79971c2f98c Mon Sep 17 00:00:00 2001 From: MWDD Date: Mon, 17 Oct 2016 15:33:42 -0700 Subject: [PATCH 261/380] Fix for Edge Only meshes being drawn in the wrong color. Changes: - Added blendWireframeColor to HdMeshReprDesc. - This flag, then passed to the Mesh Shader Key which uses it to choose the appropriate shader fragment. - Modified the fullback value for GetWireframeColor to 0,0,0,0. - Renamed shader fragment MeshWire.Fragment.EdgeOnly to MeshWire.Fragment.EdgeOnlyBlendColor. - Added new shader fragment MeshWire.Fragment.EdgeOnlyNoBlend, which removes the lerp. - Updated testHdCodeGen and testHdDrawBatching to support new shader key parameters. - Added new subtests to testHdCodeGen for edgeonly fragments. - Updated baselines for testHdCodeGen for new default Wireframe color. (Internal change: 1664785) --- pxr/imaging/lib/hd/mesh.cpp | 3 + pxr/imaging/lib/hd/mesh.h | 5 +- pxr/imaging/lib/hd/meshShaderKey.cpp | 63 +++++++++++--------- pxr/imaging/lib/hd/meshShaderKey.h | 1 + pxr/imaging/lib/hd/renderIndex.cpp | 21 ++++--- pxr/imaging/lib/hd/shaders/meshWire.glslfx | 23 ++++++- pxr/imaging/lib/hd/shaders/renderPass.glslfx | 2 +- 7 files changed, 80 insertions(+), 38 deletions(-) diff --git a/pxr/imaging/lib/hd/mesh.cpp b/pxr/imaging/lib/hd/mesh.cpp index 3993ebe10f..1a21ee90e1 100644 --- a/pxr/imaging/lib/hd/mesh.cpp +++ b/pxr/imaging/lib/hd/mesh.cpp @@ -1009,12 +1009,15 @@ HdMesh::_UpdateDrawItemGeometricShader(HdDrawItem *drawItem, HdMeshReprDesc desc cullStyle = desc.cullStyle; } + bool blendWireframeColor = desc.blendWireframeColor; + // create a shaderKey and set to the geometric shader. Hd_MeshShaderKey shaderKey(primType, desc.lit, smoothNormals, _doubleSided, hasFaceVaryingPrimVars, + blendWireframeColor, cullStyle, geomStyle); diff --git a/pxr/imaging/lib/hd/mesh.h b/pxr/imaging/lib/hd/mesh.h index 0ab6f88c11..6cc738cc99 100644 --- a/pxr/imaging/lib/hd/mesh.h +++ b/pxr/imaging/lib/hd/mesh.h @@ -50,17 +50,20 @@ struct HdMeshReprDesc { HdMeshReprDesc(HdMeshGeomStyle geomStyle = HdMeshGeomStyleInvalid, HdCullStyle cullStyle = HdCullStyleDontCare, bool lit = false, - bool smoothNormals = false) + bool smoothNormals = false, + bool blendWireframeColor = true) : geomStyle(geomStyle) , cullStyle(cullStyle) , lit(lit) , smoothNormals(smoothNormals) + , blendWireframeColor(blendWireframeColor) {} HdMeshGeomStyle geomStyle:3; HdCullStyle cullStyle:3; bool lit:1; bool smoothNormals:1; + bool blendWireframeColor:1; }; /// A subdivision surface or poly-mesh object. diff --git a/pxr/imaging/lib/hd/meshShaderKey.cpp b/pxr/imaging/lib/hd/meshShaderKey.cpp index 47c30c0861..883d5c5166 100644 --- a/pxr/imaging/lib/hd/meshShaderKey.cpp +++ b/pxr/imaging/lib/hd/meshShaderKey.cpp @@ -28,29 +28,30 @@ TF_DEFINE_PRIVATE_TOKENS( _tokens, - ((baseGLSLFX, "mesh.glslfx")) - ((smooth, "MeshNormal.Smooth")) - ((flat, "MeshNormal.Flat")) - ((limit, "MeshNormal.Limit")) - ((doubleSidedFS, "MeshNormal.Fragment.DoubleSided")) - ((singleSidedFS, "MeshNormal.Fragment.SingleSided")) - ((edgeNoneGS, "MeshWire.Geometry.NoEdge")) - ((edgeNoneFS, "MeshWire.Fragment.NoEdge")) - ((edgeOnlyGS, "MeshWire.Geometry.Edge")) - ((edgeOnlyFS, "MeshWire.Fragment.EdgeOnly")) - ((edgeOnSurfGS, "MeshWire.Geometry.Edge")) - ((edgeOnSurfFS, "MeshWire.Fragment.EdgeOnSurface")) - ((patchEdgeOnlyFS, "MeshPatchWire.Fragment.EdgeOnly")) - ((patchEdgeOnSurfFS,"MeshPatchWire.Fragment.EdgeOnSurface")) - ((mainVS, "Mesh.Vertex")) - ((mainBSplineTCS, "Mesh.TessControl.BSpline")) - ((mainBezierTES, "Mesh.TessEval.Bezier")) - ((mainTriangleGS, "Mesh.Geometry.Triangle")) - ((mainQuadGS, "Mesh.Geometry.Quad")) - ((litFS, "Mesh.Fragment.Lit")) - ((unlitFS, "Mesh.Fragment.Unlit")) - ((mainFS, "Mesh.Fragment")) - ((instancing, "Instancing.Transform")) + ((baseGLSLFX, "mesh.glslfx")) + ((smooth, "MeshNormal.Smooth")) + ((flat, "MeshNormal.Flat")) + ((limit, "MeshNormal.Limit")) + ((doubleSidedFS, "MeshNormal.Fragment.DoubleSided")) + ((singleSidedFS, "MeshNormal.Fragment.SingleSided")) + ((edgeNoneGS, "MeshWire.Geometry.NoEdge")) + ((edgeNoneFS, "MeshWire.Fragment.NoEdge")) + ((edgeOnlyGS, "MeshWire.Geometry.Edge")) + ((edgeOnlyBlendFS, "MeshWire.Fragment.EdgeOnlyBlendColor")) + ((edgeOnlyNoBlendFS, "MeshWire.Fragment.EdgeOnlyNoBlend")) + ((edgeOnSurfGS, "MeshWire.Geometry.Edge")) + ((edgeOnSurfFS, "MeshWire.Fragment.EdgeOnSurface")) + ((patchEdgeOnlyFS, "MeshPatchWire.Fragment.EdgeOnly")) + ((patchEdgeOnSurfFS, "MeshPatchWire.Fragment.EdgeOnSurface")) + ((mainVS, "Mesh.Vertex")) + ((mainBSplineTCS, "Mesh.TessControl.BSpline")) + ((mainBezierTES, "Mesh.TessEval.Bezier")) + ((mainTriangleGS, "Mesh.Geometry.Triangle")) + ((mainQuadGS, "Mesh.Geometry.Quad")) + ((litFS, "Mesh.Fragment.Lit")) + ((unlitFS, "Mesh.Fragment.Unlit")) + ((mainFS, "Mesh.Fragment")) + ((instancing, "Instancing.Transform")) ); Hd_MeshShaderKey::Hd_MeshShaderKey( @@ -59,6 +60,7 @@ Hd_MeshShaderKey::Hd_MeshShaderKey( bool smoothNormals, bool doubleSided, bool faceVarying, + bool blendWireframeColor, HdCullStyle cullStyle, HdMeshGeomStyle geomStyle) : primitiveMode(primType) @@ -140,11 +142,16 @@ Hd_MeshShaderKey::Hd_MeshShaderKey( geomStyle == HdMeshGeomStyleHullEdgeOnSurf) ? _tokens->patchEdgeOnSurfFS : _tokens->edgeNoneFS)); } else { - FS[3] = ((geomStyle == HdMeshGeomStyleEdgeOnly or - geomStyle == HdMeshGeomStyleHullEdgeOnly) ? _tokens->edgeOnlyFS - : ((geomStyle == HdMeshGeomStyleEdgeOnSurf or - geomStyle == HdMeshGeomStyleHullEdgeOnSurf) ? _tokens->edgeOnSurfFS - : _tokens->edgeNoneFS)); + if (geomStyle == HdMeshGeomStyleEdgeOnly or + geomStyle == HdMeshGeomStyleHullEdgeOnly) { + FS[3] = blendWireframeColor ? _tokens->edgeOnlyBlendFS + : _tokens->edgeOnlyNoBlendFS; + } else if (geomStyle == HdMeshGeomStyleEdgeOnSurf or + geomStyle == HdMeshGeomStyleHullEdgeOnSurf) { + FS[3] = _tokens->edgeOnSurfFS; + } else { + FS[3] = _tokens->edgeNoneFS; + } } FS[4] = lit ? _tokens->litFS : _tokens->unlitFS; FS[5] = _tokens->mainFS; diff --git a/pxr/imaging/lib/hd/meshShaderKey.h b/pxr/imaging/lib/hd/meshShaderKey.h index f20f3f3c01..4d03e3111e 100644 --- a/pxr/imaging/lib/hd/meshShaderKey.h +++ b/pxr/imaging/lib/hd/meshShaderKey.h @@ -36,6 +36,7 @@ struct Hd_MeshShaderKey bool smoothNormals, bool doubleSided, bool faceVarying, + bool blendWireframeColor, HdCullStyle cullStyle, HdMeshGeomStyle geomStyle); diff --git a/pxr/imaging/lib/hd/renderIndex.cpp b/pxr/imaging/lib/hd/renderIndex.cpp index 9cb58ed9bf..fda1dc16c2 100644 --- a/pxr/imaging/lib/hd/renderIndex.cpp +++ b/pxr/imaging/lib/hd/renderIndex.cpp @@ -78,38 +78,45 @@ HdRenderIndex::HdRenderIndex() HdMeshReprDesc(HdMeshGeomStyleHull, HdCullStyleDontCare, /*lit=*/true, - /*smoothNormals=*/false)); + /*smoothNormals=*/false, + /*blendWireframeColor=*/false)); HdMesh::ConfigureRepr(HdTokens->smoothHull, HdMeshReprDesc(HdMeshGeomStyleHull, HdCullStyleDontCare, /*lit=*/true, - /*smoothNormals=*/true)); + /*smoothNormals=*/true, + /*blendWireframeColor=*/false)); HdMesh::ConfigureRepr(HdTokens->wire, HdMeshReprDesc(HdMeshGeomStyleHullEdgeOnly, HdCullStyleDontCare, /*lit=*/true, - /*smoothNormals=*/true)); + /*smoothNormals=*/true, + /*blendWireframeColor=*/true)); HdMesh::ConfigureRepr(HdTokens->wireOnSurf, HdMeshReprDesc(HdMeshGeomStyleHullEdgeOnSurf, HdCullStyleDontCare, /*lit=*/true, - /*smoothNormals=*/true)); + /*smoothNormals=*/true, + /*blendWireframeColor=*/true)); HdMesh::ConfigureRepr(HdTokens->refined, HdMeshReprDesc(HdMeshGeomStyleSurf, HdCullStyleDontCare, /*lit=*/true, - /*smoothNormals=*/true)); + /*smoothNormals=*/true, + /*blendWireframeColor=*/false)); HdMesh::ConfigureRepr(HdTokens->refinedWire, HdMeshReprDesc(HdMeshGeomStyleEdgeOnly, HdCullStyleDontCare, /*lit=*/true, - /*smoothNormals=*/true)); + /*smoothNormals=*/true, + /*blendWireframeColor=*/true)); HdMesh::ConfigureRepr(HdTokens->refinedWireOnSurf, HdMeshReprDesc(HdMeshGeomStyleEdgeOnSurf, HdCullStyleDontCare, /*lit=*/true, - /*smoothNormals=*/true)); + /*smoothNormals=*/true, + /*blendWireframeColor=*/true)); HdBasisCurves::ConfigureRepr(HdTokens->hull, diff --git a/pxr/imaging/lib/hd/shaders/meshWire.glslfx b/pxr/imaging/lib/hd/shaders/meshWire.glslfx index 844ec3e5f5..57e378976f 100644 --- a/pxr/imaging/lib/hd/shaders/meshWire.glslfx +++ b/pxr/imaging/lib/hd/shaders/meshWire.glslfx @@ -178,7 +178,7 @@ vec4 ApplyEdgeColor(vec4 Cfill, vec4 patchCoord) } --- -------------------------------------------------------------------------- --- glsl MeshWire.Fragment.EdgeOnly +-- glsl MeshWire.Fragment.EdgeOnlyBlendColor in EdgeData { @@ -204,6 +204,27 @@ vec4 ApplyEdgeColor(vec4 Cfill, vec4 patchCoord) return Cfill; } +--- -------------------------------------------------------------------------- +-- glsl MeshWire.Fragment.EdgeOnlyNoBlend + +in EdgeData +{ + noperspective vec3 edgeDistance; +} inEdgeData; + +vec4 ApplyEdgeColor(vec4 Cfill, vec4 patchCoord) +{ + vec3 edgeDistance = inEdgeData.edgeDistance; + + float d = min(edgeDistance.x, + min(edgeDistance.y, + edgeDistance.z)); + float p = exp2(-4 * d * d); + if (p < 0.5) discard; + + return Cfill; +} + --- -------------------------------------------------------------------------- -- glsl MeshPatchWire.Fragment.EdgeOnSurface diff --git a/pxr/imaging/lib/hd/shaders/renderPass.glslfx b/pxr/imaging/lib/hd/shaders/renderPass.glslfx index 1ab07a20a3..9252aab5c9 100644 --- a/pxr/imaging/lib/hd/shaders/renderPass.glslfx +++ b/pxr/imaging/lib/hd/shaders/renderPass.glslfx @@ -98,7 +98,7 @@ vec4 GetWireframeColor() { #if defined(HD_HAS_wireframeColor) return HdGet_wireframeColor(); #else - return vec4(0,0,0,1); + return vec4(0,0,0,0); #endif } From 01b7253f75647a1baff0e3a82d1187ebbb1bb3c4 Mon Sep 17 00:00:00 2001 From: takahito-tejima Date: Mon, 17 Oct 2016 15:35:28 -0700 Subject: [PATCH 262/380] [UsdImaging, UsdImagingGL] remove Qt dependency use GarchGLDebugWindow instead of QGLWidget for the unit tests. (Internal change: 1664839) --- pxr/usdImaging/lib/usdImaging/CMakeLists.txt | 7 +- .../lib/usdImagingGL/CMakeLists.txt | 6 +- .../lib/usdImagingGL/unitTestGLDrawing.cpp | 195 ++++++++---------- .../lib/usdImagingGL/unitTestGLDrawing.h | 12 +- 4 files changed, 90 insertions(+), 130 deletions(-) diff --git a/pxr/usdImaging/lib/usdImaging/CMakeLists.txt b/pxr/usdImaging/lib/usdImaging/CMakeLists.txt index ec5ee3a5f2..a2135fffd4 100644 --- a/pxr/usdImaging/lib/usdImaging/CMakeLists.txt +++ b/pxr/usdImaging/lib/usdImaging/CMakeLists.txt @@ -1,11 +1,6 @@ set(PXR_PREFIX pxr/usdImaging) set(PXR_PACKAGE usdImaging) -set(optionalPublicClasses "") -if (QT4_FOUND) - list(APPEND optionalPublicClasses unitTestHelper) -endif() - # Note: both python include directives are included for compatibility. pxr_shared_library(usdImaging LIBRARIES @@ -57,7 +52,7 @@ pxr_shared_library(usdImaging primAdapter sphereAdapter nurbsPatchAdapter - ${optionalPublicClasses} + unitTestHelper PUBLIC_HEADERS version.h diff --git a/pxr/usdImaging/lib/usdImagingGL/CMakeLists.txt b/pxr/usdImaging/lib/usdImagingGL/CMakeLists.txt index 2aaafcedc0..39349b9b05 100644 --- a/pxr/usdImaging/lib/usdImagingGL/CMakeLists.txt +++ b/pxr/usdImaging/lib/usdImagingGL/CMakeLists.txt @@ -61,19 +61,17 @@ pxr_shared_library(usdImagingGL __init__.py ) -if (QT4_FOUND) +if (X11_FOUND OR APPLE) pxr_build_test(testUsdImagingGLBasicDrawing LIBRARIES hd + garch glf - glfq usd usdUtils usdImaging usdImagingGL sdf - Qt4::QtCore - Qt4::QtOpenGL CPPFILES unitTestGLDrawing.cpp testenv/testUsdImagingGLBasicDrawing.cpp diff --git a/pxr/usdImaging/lib/usdImagingGL/unitTestGLDrawing.cpp b/pxr/usdImaging/lib/usdImagingGL/unitTestGLDrawing.cpp index cdb2af7b1d..be347cf85b 100644 --- a/pxr/usdImaging/lib/usdImagingGL/unitTestGLDrawing.cpp +++ b/pxr/usdImaging/lib/usdImagingGL/unitTestGLDrawing.cpp @@ -26,7 +26,7 @@ #include "pxr/usdImaging/usdImagingGL/unitTestGLDrawing.h" #include "pxr/imaging/glf/diagnostic.h" #include "pxr/imaging/glf/drawTarget.h" -#include "pxr/imaging/glfq/glDebugContext.h" +#include "pxr/imaging/garch/glDebugWindow.h" #include "pxr/base/arch/attributes.h" #include "pxr/base/gf/vec2i.h" @@ -34,10 +34,6 @@ #include "pxr/base/plug/registry.h" #include "pxr/base/arch/systemInfo.h" -#include -#include -#include - #include #include @@ -55,64 +51,48 @@ static void UsdImagingGL_UnitTestHelper_InitPlugins() //////////////////////////////////////////////////////////// -static QGLFormat -_GetGLFormat() -{ - QGLFormat fmt; - fmt.setDoubleBuffer(true); - fmt.setDepth(true); - fmt.setAlpha(true); - fmt.setStencil(true); - //fmt.setSampleBuffers(1); - //fmt.setSamples(4); - return fmt; -} - -class UsdImagingGL_UnitTestDrawingQGLWidget : public QGLWidget { +class UsdImagingGL_UnitTestWindow : public GarchGLDebugWindow { public: - typedef UsdImagingGL_UnitTestDrawingQGLWidget This; + typedef UsdImagingGL_UnitTestWindow This; public: - UsdImagingGL_UnitTestDrawingQGLWidget(UsdImagingGL_UnitTestGLDrawing * unitTest, - QWidget * parent = NULL); - virtual ~UsdImagingGL_UnitTestDrawingQGLWidget(); + UsdImagingGL_UnitTestWindow(UsdImagingGL_UnitTestGLDrawing * unitTest, + int w, int h); + virtual ~UsdImagingGL_UnitTestWindow(); void DrawOffscreen(); bool WriteToFile(std::string const & attachment, std::string const & filename); -protected: - // QGLWidget overrides - void initializeGL(); - void paintGL(); - - // QWidget overrides - virtual void keyReleaseEvent(QKeyEvent * event); - virtual void mousePressEvent(QMouseEvent * event); - virtual void mouseReleaseEvent(QMouseEvent * event); - virtual void mouseMoveEvent(QMouseEvent * event); + // GarchGLDebugWIndow overrides; + virtual void OnInitializeGL(); + virtual void OnUninitializeGL(); + virtual void OnPaintGL(); + virtual void OnKeyRelease(int key); + virtual void OnMousePress(int button, int x, int y, int modKeys); + virtual void OnMouseRelease(int button, int x, int y, int modKeys); + virtual void OnMouseMove(int x, int y, int modKeys); private: UsdImagingGL_UnitTestGLDrawing *_unitTest; GlfDrawTargetRefPtr _drawTarget; }; -UsdImagingGL_UnitTestDrawingQGLWidget::UsdImagingGL_UnitTestDrawingQGLWidget( - UsdImagingGL_UnitTestGLDrawing * unitTest, - QWidget * parent) : - QGLWidget(new GlfQGLDebugContext(_GetGLFormat()), parent), - _unitTest(unitTest) +UsdImagingGL_UnitTestWindow::UsdImagingGL_UnitTestWindow( + UsdImagingGL_UnitTestGLDrawing * unitTest, int w, int h) + : GarchGLDebugWindow("UsdImagingGL Test", w, h) + , _unitTest(unitTest) { } -UsdImagingGL_UnitTestDrawingQGLWidget::~UsdImagingGL_UnitTestDrawingQGLWidget() +UsdImagingGL_UnitTestWindow::~UsdImagingGL_UnitTestWindow() { } /* virtual */ void -UsdImagingGL_UnitTestDrawingQGLWidget::initializeGL() +UsdImagingGL_UnitTestWindow::OnInitializeGL() { GlfGlewInit(); GlfRegisterDefaultDebugOutputMessageCallback(); @@ -121,7 +101,7 @@ UsdImagingGL_UnitTestDrawingQGLWidget::initializeGL() // Create an offscreen draw target which is the same size as this // widget and initialize the unit test with the draw target bound. // - _drawTarget = GlfDrawTarget::New(GfVec2i(width(), height())); + _drawTarget = GlfDrawTarget::New(GfVec2i(GetWidth(), GetHeight())); _drawTarget->Bind(); _drawTarget->AddAttachment("color", GL_RGBA, GL_FLOAT, GL_RGBA); _drawTarget->AddAttachment("depth", GL_DEPTH_COMPONENT, GL_FLOAT, @@ -134,14 +114,25 @@ UsdImagingGL_UnitTestDrawingQGLWidget::initializeGL() /* virtual */ void -UsdImagingGL_UnitTestDrawingQGLWidget::paintGL() +UsdImagingGL_UnitTestWindow::OnUninitializeGL() +{ + _drawTarget = GlfDrawTargetRefPtr(); + + _unitTest->ShutdownTest(); +} + +/* virtual */ +void +UsdImagingGL_UnitTestWindow::OnPaintGL() { // // Update the draw target's size and execute the unit test with // the draw target bound. // + int width = GetWidth(); + int height = GetHeight(); _drawTarget->Bind(); - _drawTarget->SetSize(GfVec2i(width(), height())); + _drawTarget->SetSize(GfVec2i(width, height)); _unitTest->DrawTest(false); @@ -154,8 +145,8 @@ UsdImagingGL_UnitTestDrawingQGLWidget::paintGL() glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); glBindFramebuffer(GL_READ_FRAMEBUFFER, _drawTarget->GetFramebufferId()); - glBlitFramebuffer(0, 0, width(), height(), - 0, 0, width(), height(), + glBlitFramebuffer(0, 0, width, height, + 0, 0, width, height, GL_COLOR_BUFFER_BIT, GL_NEAREST); @@ -164,15 +155,10 @@ UsdImagingGL_UnitTestDrawingQGLWidget::paintGL() } void -UsdImagingGL_UnitTestDrawingQGLWidget::DrawOffscreen() +UsdImagingGL_UnitTestWindow::DrawOffscreen() { - // - // Ask Qt to initialize and draw - // - glInit(); - _drawTarget->Bind(); - _drawTarget->SetSize(GfVec2i(width(), height())); + _drawTarget->SetSize(GfVec2i(GetWidth(), GetHeight())); _unitTest->DrawTest(true); @@ -180,7 +166,7 @@ UsdImagingGL_UnitTestDrawingQGLWidget::DrawOffscreen() } bool -UsdImagingGL_UnitTestDrawingQGLWidget::WriteToFile(std::string const & attachment, +UsdImagingGL_UnitTestWindow::WriteToFile(std::string const & attachment, std::string const & filename) { // We need to unbind the draw target before writing to file to be sure the @@ -198,50 +184,37 @@ UsdImagingGL_UnitTestDrawingQGLWidget::WriteToFile(std::string const & attachmen /* virtual */ void -UsdImagingGL_UnitTestDrawingQGLWidget::keyReleaseEvent(QKeyEvent * event) +UsdImagingGL_UnitTestWindow::OnKeyRelease(int key) { - switch (event->key()) { - case Qt::Key_Escape: - case Qt::Key_Q: - QApplication::instance()->exit(0); - return; + switch (key) { + case 'q': + ExitApp(); + return; } + _unitTest->KeyRelease(key); } /* virtual */ void -UsdImagingGL_UnitTestDrawingQGLWidget::mousePressEvent(QMouseEvent * event) +UsdImagingGL_UnitTestWindow::OnMousePress(int button, + int x, int y, int modKeys) { - int button = 0; - switch(event->button()){ - case Qt::LeftButton: button = 0; break; - case Qt::MidButton: button = 1; break; - case Qt::RightButton: button = 2; break; - default: break; - } - _unitTest->MousePress(button, event->x(), event->y()); + _unitTest->MousePress(button, x, y, modKeys); } /* virtual */ void -UsdImagingGL_UnitTestDrawingQGLWidget::mouseReleaseEvent(QMouseEvent * event) +UsdImagingGL_UnitTestWindow::OnMouseRelease(int button, + int x, int y, int modKeys) { - int button = 0; - switch(event->button()){ - case Qt::LeftButton: button = 0; break; - case Qt::MidButton: button = 1; break; - case Qt::RightButton: button = 2; break; - default: break; - } - _unitTest->MouseRelease(button, event->x(), event->y()); + _unitTest->MouseRelease(button, x, y, modKeys); } /* virtual */ void -UsdImagingGL_UnitTestDrawingQGLWidget::mouseMoveEvent(QMouseEvent * event) +UsdImagingGL_UnitTestWindow::OnMouseMove(int x, int y, int modKeys) { - _unitTest->MouseMove(event->x(), event->y()); - glDraw(); + _unitTest->MouseMove(x, y, modKeys); } //////////////////////////////////////////////////////////// @@ -264,13 +237,13 @@ UsdImagingGL_UnitTestGLDrawing::~UsdImagingGL_UnitTestGLDrawing() int UsdImagingGL_UnitTestGLDrawing::GetWidth() const { - return _widget->width(); + return _widget->GetWidth(); } int UsdImagingGL_UnitTestGLDrawing::GetHeight() const { - return _widget->height(); + return _widget->GetHeight(); } bool @@ -280,12 +253,6 @@ UsdImagingGL_UnitTestGLDrawing::WriteToFile(std::string const & attachment, return _widget->WriteToFile(attachment, filename); } -void -UsdImagingGL_UnitTestGLDrawing::_Redraw() const -{ - _widget->update(); -} - struct UsdImagingGL_UnitTestGLDrawing::_Args { _Args() : offscreen(false) { } @@ -471,11 +438,32 @@ UsdImagingGL_UnitTestGLDrawing::_Parse(int argc, char *argv[], _Args* args) } } +/* virtual */ +void +UsdImagingGL_UnitTestGLDrawing::MousePress(int button, int x, int y, + int modKeys) +{ +} +/* virtual */ +void +UsdImagingGL_UnitTestGLDrawing::MouseRelease(int button, int x, int y, + int modKeys) +{ +} +/* virtual */ +void +UsdImagingGL_UnitTestGLDrawing::MouseMove(int x, int y, int modKeys) +{ +} +/* virtual */ +void +UsdImagingGL_UnitTestGLDrawing::KeyRelease(int key) +{ +} + void UsdImagingGL_UnitTestGLDrawing::RunTest(int argc, char *argv[]) { - QApplication app(argc, argv); - UsdImagingGL_UnitTestHelper_InitPlugins(); _Args args; @@ -498,18 +486,14 @@ UsdImagingGL_UnitTestGLDrawing::RunTest(int argc, char *argv[]) _stageFilePath = args.unresolvedStageFilePath; } - _widget = new UsdImagingGL_UnitTestDrawingQGLWidget(this); - _widget->setWindowTitle("Drawing Test"); - _widget->resize(640, 480); + _widget = new UsdImagingGL_UnitTestWindow(this, 640, 480); + _widget->Init(); if (_times.empty()) { _times.push_back(-999); } if (args.complexities.size() > 0) { - _widget->hide(); - _widget->makeCurrent(); - std::string imageFilePath = GetOutputFilePath(); TF_FOR_ALL(compIt, args.complexities) { @@ -523,26 +507,9 @@ UsdImagingGL_UnitTestGLDrawing::RunTest(int argc, char *argv[]) _widget->DrawOffscreen(); } - // Give tests the opportunity to shutdown any OGL - // buffers before they have no context available - ShutdownTest(); - _widget->doneCurrent(); - } else if (args.offscreen) { - _widget->hide(); - _widget->makeCurrent(); _widget->DrawOffscreen(); - - // Give tests the opportunity to shutdown any OGL - // buffers before they have no context available - ShutdownTest(); - _widget->doneCurrent(); } else { - _widget->show(); - app.exec(); - - // Give tests the opportunity to shutdown any OGL - // buffers before they have no context available - ShutdownTest(); + _widget->Run(); } } diff --git a/pxr/usdImaging/lib/usdImagingGL/unitTestGLDrawing.h b/pxr/usdImaging/lib/usdImagingGL/unitTestGLDrawing.h index 8095480520..4115872cae 100644 --- a/pxr/usdImaging/lib/usdImagingGL/unitTestGLDrawing.h +++ b/pxr/usdImaging/lib/usdImagingGL/unitTestGLDrawing.h @@ -33,7 +33,7 @@ #include #include -class UsdImagingGL_UnitTestDrawingQGLWidget; +class UsdImagingGL_UnitTestWindow; /// \class UsdImagingGL_UnitTestGLDrawing /// @@ -65,23 +65,23 @@ class UsdImagingGL_UnitTestGLDrawing { virtual void DrawTest(bool offscreen) = 0; virtual void ShutdownTest() { } - virtual void MousePress(int button, int x, int y) = 0; - virtual void MouseRelease(int button, int x, int y) = 0; - virtual void MouseMove(int x, int y) = 0; + virtual void MousePress(int button, int x, int y, int modKeys); + virtual void MouseRelease(int button, int x, int y, int modKeys); + virtual void MouseMove(int x, int y, int modKeys); + virtual void KeyRelease(int key); bool WriteToFile(std::string const & attachment, std::string const & filename) const; protected: float _GetComplexity() const { return _complexity; } bool _ShouldFrameAll() const { return _shouldFrameAll; } - void _Redraw() const; private: struct _Args; void _Parse(int argc, char *argv[], _Args* args); private: - UsdImagingGL_UnitTestDrawingQGLWidget *_widget; + UsdImagingGL_UnitTestWindow *_widget; bool _testLighting; bool _testIdRender; From bc7a6aff7977f0bb95315046571550fae46815a6 Mon Sep 17 00:00:00 2001 From: takahito-tejima Date: Mon, 17 Oct 2016 15:35:37 -0700 Subject: [PATCH 263/380] [Garch] fix OSX build issue a workaround for some modifier key symbols are inconsistent between SDK versions. also fixing typo of BOOL/bool causing a warning. (Internal change: 1664853) --- pxr/imaging/lib/garch/glPlatformDebugWindowDarwin.mm | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/pxr/imaging/lib/garch/glPlatformDebugWindowDarwin.mm b/pxr/imaging/lib/garch/glPlatformDebugWindowDarwin.mm index 9ab2febf28..f6d0823714 100644 --- a/pxr/imaging/lib/garch/glPlatformDebugWindowDarwin.mm +++ b/pxr/imaging/lib/garch/glPlatformDebugWindowDarwin.mm @@ -34,6 +34,13 @@ { int keys = 0; + // The 10.12 SDK has new symbols. +#if MAC_OS_X_VERSION_MAX_ALLOWED < 101200 + #define NSEventModifierFlagShift NSShiftKeyMask + #define NSEventModifierFlagControl NSControlKeyMask + #define NSEventModifierFlagOption NSAlternateKeyMask + #define NSEventModifierFlagCommand NSCommandKeyMask +#endif if (flags & NSEventModifierFlagShift) keys |= GarchGLDebugWindow::Shift; if (flags & NSEventModifierFlagControl) keys |= GarchGLDebugWindow::Ctrl; if (flags & NSEventModifierFlagOption) keys |= GarchGLDebugWindow::Alt; @@ -87,7 +94,7 @@ -(id)initGL:(NSRect)frame callback:(GarchGLDebugWindow*)cb return self; } --(bool)acceptsFirstResponder +-(BOOL)acceptsFirstResponder { return YES; } From 5b907b40b88d9f9f6802456881741f2d66f4f1e1 Mon Sep 17 00:00:00 2001 From: takahito-tejima Date: Mon, 17 Oct 2016 15:35:49 -0700 Subject: [PATCH 264/380] [usdviewq] fix axis/bbox drawing commit e212084 was too hasty to remove fixed GL matrix stack, which is still used for axis/bbox drawing. Partially revert the change so that Hydra drawing is taking the new path with other stuffs working. (Internal change: 1665023) --- pxr/usdImaging/lib/usdviewq/stageView.py | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/pxr/usdImaging/lib/usdviewq/stageView.py b/pxr/usdImaging/lib/usdviewq/stageView.py index 459fa3b230..30b82b47c0 100644 --- a/pxr/usdImaging/lib/usdviewq/stageView.py +++ b/pxr/usdImaging/lib/usdviewq/stageView.py @@ -1234,6 +1234,21 @@ def restoreViewState(self, viewState): self._freeCamera = self._freeCamera.clone() self.update() + + def setupOpenGLViewMatricesForFrustum(self, frustum): + from OpenGL import GL + import ctypes + GLMtx = ctypes.c_double * 16 + MakeGLMtx = lambda m: GLMtx.from_buffer_copy(m) + + GL.glMatrixMode(GL.GL_PROJECTION) + GL.glLoadIdentity() + GL.glMultMatrixd(MakeGLMtx(frustum.ComputeProjectionMatrix())) + + GL.glMatrixMode(GL.GL_MODELVIEW) + GL.glLoadIdentity() + GL.glMultMatrixd(MakeGLMtx(frustum.ComputeViewMatrix())) + def drawWireframeCube(self, size): from OpenGL import GL @@ -1308,7 +1323,8 @@ def paintGL(self): gfCamera.clippingPlanes] if self._nodes: - + self.setupOpenGLViewMatricesForFrustum(frustum) + GL.glColor3f(1.0,1.0,1.0) # for renderModes that need lights From e82841f2ad95024aa45f8017675b9481f33fa8f7 Mon Sep 17 00:00:00 2001 From: superfunc Date: Mon, 17 Oct 2016 15:36:54 -0700 Subject: [PATCH 265/380] [Usd] Remove usage of TF_FOR_ALL and BOOST_FOREACH from lib/usd. (Internal change: 1665049) --- pxr/usd/lib/usd/attributeQuery.cpp | 4 +- pxr/usd/lib/usd/clip.cpp | 1 - pxr/usd/lib/usd/clipCache.cpp | 7 +- pxr/usd/lib/usd/crateFile.cpp | 1 - pxr/usd/lib/usd/instanceCache.cpp | 1 - pxr/usd/lib/usd/instanceKey.cpp | 2 - pxr/usd/lib/usd/prim.cpp | 26 ++-- pxr/usd/lib/usd/prim.h | 1 - pxr/usd/lib/usd/relationship.cpp | 13 +- pxr/usd/lib/usd/schemaRegistry.cpp | 3 - pxr/usd/lib/usd/stage.cpp | 192 +++++++++++++------------- pxr/usd/lib/usd/stageCache.cpp | 30 ++-- pxr/usd/lib/usd/stageCacheContext.cpp | 11 +- pxr/usd/lib/usd/treeIterator.cpp | 1 - pxr/usd/lib/usd/variantSets.cpp | 27 ++-- 15 files changed, 163 insertions(+), 157 deletions(-) diff --git a/pxr/usd/lib/usd/attributeQuery.cpp b/pxr/usd/lib/usd/attributeQuery.cpp index 5db08221a0..6374f87cfe 100644 --- a/pxr/usd/lib/usd/attributeQuery.cpp +++ b/pxr/usd/lib/usd/attributeQuery.cpp @@ -57,8 +57,8 @@ UsdAttributeQuery::CreateQueries( { std::vector rval; rval.reserve(attrNames.size()); - TF_FOR_ALL(it, attrNames) { - rval.push_back(UsdAttributeQuery(prim, *it)); + for (const auto& attrName : attrNames) { + rval.push_back(UsdAttributeQuery(prim, attrName)); } return rval; diff --git a/pxr/usd/lib/usd/clip.cpp b/pxr/usd/lib/usd/clip.cpp index a395d9443b..f6f8f52e74 100644 --- a/pxr/usd/lib/usd/clip.cpp +++ b/pxr/usd/lib/usd/clip.cpp @@ -34,7 +34,6 @@ #include "pxr/base/tf/stringUtils.h" -#include #include #include diff --git a/pxr/usd/lib/usd/clipCache.cpp b/pxr/usd/lib/usd/clipCache.cpp index ac993077b5..3d76a4b618 100644 --- a/pxr/usd/lib/usd/clipCache.cpp +++ b/pxr/usd/lib/usd/clipCache.cpp @@ -38,7 +38,6 @@ #include "pxr/base/gf/vec2d.h" #include "pxr/base/tf/ostreamMethods.h" -#include #include Usd_ClipCache::Usd_ClipCache() @@ -321,9 +320,9 @@ Usd_ClipCache::InvalidateClipsForPrim(const SdfPath& path, Lifeboat* lifeboat) { tbb::mutex::scoped_lock lock(_mutex); - BOOST_FOREACH(const _ClipTable::value_type& entry, - _table.FindSubtreeRange(path)) { - + auto range = _table.FindSubtreeRange(path); + for (auto entryIter = range.first; entryIter != range.second; ++entryIter) { + const auto& entry = *entryIter; lifeboat->_clips.insert( lifeboat->_clips.end(), entry.second.begin(), entry.second.end()); } diff --git a/pxr/usd/lib/usd/crateFile.cpp b/pxr/usd/lib/usd/crateFile.cpp index 363dabdfae..6f1fd0bf0e 100644 --- a/pxr/usd/lib/usd/crateFile.cpp +++ b/pxr/usd/lib/usd/crateFile.cpp @@ -49,7 +49,6 @@ #include "pxr/base/tf/envSetting.h" #include "pxr/base/tf/errorMark.h" #include "pxr/base/tf/getenv.h" -#include "pxr/base/tf/iterator.h" #include "pxr/base/tf/mallocTag.h" #include "pxr/base/tf/ostreamMethods.h" #include "pxr/base/tf/stringUtils.h" diff --git a/pxr/usd/lib/usd/instanceCache.cpp b/pxr/usd/lib/usd/instanceCache.cpp index 5a5a5cb79b..d7eb12c00b 100644 --- a/pxr/usd/lib/usd/instanceCache.cpp +++ b/pxr/usd/lib/usd/instanceCache.cpp @@ -29,7 +29,6 @@ #include "pxr/base/tf/envSetting.h" #include "pxr/base/tracelite/trace.h" -#include #include using std::make_pair; diff --git a/pxr/usd/lib/usd/instanceKey.cpp b/pxr/usd/lib/usd/instanceKey.cpp index 109f67c803..4d13557e7b 100644 --- a/pxr/usd/lib/usd/instanceKey.cpp +++ b/pxr/usd/lib/usd/instanceKey.cpp @@ -25,8 +25,6 @@ #include "pxr/usd/usd/resolver.h" -#include - Usd_InstanceKey::Usd_InstanceKey() { } diff --git a/pxr/usd/lib/usd/prim.cpp b/pxr/usd/lib/usd/prim.cpp index dd5741ebc1..1aa1372c17 100644 --- a/pxr/usd/lib/usd/prim.cpp +++ b/pxr/usd/lib/usd/prim.cpp @@ -42,8 +42,6 @@ #include #include -#include - UsdPrim UsdPrim::GetChild(const TfToken &name) const { @@ -93,13 +91,13 @@ UsdPrim::_MakeProperties(const TfTokenVector &names) const std::vector props; UsdStage *stage = _GetStage(); props.reserve(names.size()); - TF_FOR_ALL(propName, names) { + for (const auto& propName : names) { SdfSpecType specType = - stage->_GetDefiningSpecType(*this, *propName); + stage->_GetDefiningSpecType(*this, propName); if (specType == SdfSpecTypeAttribute) { - props.push_back(GetAttribute(*propName)); + props.push_back(GetAttribute(propName)); } else if (TF_VERIFY(specType == SdfSpecTypeRelationship)) { - props.push_back(GetRelationship(*propName)); + props.push_back(GetRelationship(propName)); } } @@ -239,13 +237,13 @@ UsdPrim::_GetPropertiesInNamespace(const std::string &namespaces, // Prune out non-matches before we sort size_t insertionPt = 0; - TF_FOR_ALL(name, names) { - const std::string &s = name->GetString(); + for (const auto& name : names) { + const std::string &s = name.GetString(); if (s.size() > terminator and TfStringStartsWith(s, namespaces) and s[terminator] == delim) { - names[insertionPt++] = *name; + names[insertionPt++] = name; } } names.resize(insertionPt); @@ -327,9 +325,10 @@ UsdPrim::_GetAttributes(bool onlyAuthored) const // attribute names, however this vector is likely short lived and worth the // trade off of repeated reallocation. attrs.reserve(names.size()); - TF_FOR_ALL(propName, names) { - if (UsdAttribute attr = GetAttribute(*propName)) + for (const auto& propName : names) { + if (UsdAttribute attr = GetAttribute(propName)) { attrs.push_back(attr); + } } return attrs; @@ -387,9 +386,10 @@ UsdPrim::_GetRelationships(bool onlyAuthored) const // relationship names, however this vector is likely short lived and worth // the trade off of repeated reallocation. rels.reserve(names.size()); - TF_FOR_ALL(propName, names) { - if (UsdRelationship rel = GetRelationship(*propName)) + for (const auto& propName : names) { + if (UsdRelationship rel = GetRelationship(propName)) { rels.push_back(rel); + } } return rels; diff --git a/pxr/usd/lib/usd/prim.h b/pxr/usd/lib/usd/prim.h index 30406a9144..fec3990990 100644 --- a/pxr/usd/lib/usd/prim.h +++ b/pxr/usd/lib/usd/prim.h @@ -34,7 +34,6 @@ #include "pxr/base/tracelite/trace.h" #include "pxr/base/tf/declarePtrs.h" -#include "pxr/base/tf/iterator.h" #include "pxr/base/tf/refBase.h" #include "pxr/base/tf/token.h" #include "pxr/base/tf/weakBase.h" diff --git a/pxr/usd/lib/usd/relationship.cpp b/pxr/usd/lib/usd/relationship.cpp index 69799f4d97..69c28e03d5 100644 --- a/pxr/usd/lib/usd/relationship.cpp +++ b/pxr/usd/lib/usd/relationship.cpp @@ -35,8 +35,6 @@ #include "pxr/usd/sdf/schema.h" #include "pxr/base/tracelite/trace.h" -#include - #include #include #include @@ -334,12 +332,12 @@ UsdRelationship::_GetForwardedTargets(SdfPathSet* visited, bool success = GetTargets(&curTargets, forwardToObjectsInMasters); // Process all targets at this relationship. - TF_FOR_ALL(trgIt, curTargets) { - UsdPrim nextPrim = GetStage()->GetPrimAtPath(trgIt->GetPrimPath()); + for (const auto& target : curTargets) { + UsdPrim nextPrim = GetStage()->GetPrimAtPath(target.GetPrimPath()); if (nextPrim) { if (UsdRelationship rel = - nextPrim.GetRelationship(trgIt->GetNameToken())) { + nextPrim.GetRelationship(target.GetNameToken())) { // It doesn't matter if we fail here, just track the error // state and continue attempting to gather targets. success = success and @@ -350,8 +348,9 @@ UsdRelationship::_GetForwardedTargets(SdfPathSet* visited, } } - if (uniqueTargets->insert(*trgIt).second) - targets->push_back(*trgIt); + if (uniqueTargets->insert(target).second) { + targets->push_back(target); + } } return success; diff --git a/pxr/usd/lib/usd/schemaRegistry.cpp b/pxr/usd/lib/usd/schemaRegistry.cpp index ac3c6593bc..ccd8c8a52f 100644 --- a/pxr/usd/lib/usd/schemaRegistry.cpp +++ b/pxr/usd/lib/usd/schemaRegistry.cpp @@ -34,13 +34,10 @@ #include "pxr/base/tf/fileUtils.h" #include "pxr/base/tf/instantiateSingleton.h" -#include "pxr/base/tf/iterator.h" #include "pxr/base/tf/registryManager.h" #include "pxr/base/tf/token.h" #include "pxr/base/tf/type.h" -#include - #include #include #include diff --git a/pxr/usd/lib/usd/stage.cpp b/pxr/usd/lib/usd/stage.cpp index 2cc60ee7e1..d5f829325e 100644 --- a/pxr/usd/lib/usd/stage.cpp +++ b/pxr/usd/lib/usd/stage.cpp @@ -88,7 +88,6 @@ #include "pxr/base/work/utils.h" #include -#include #include #include #include @@ -126,8 +125,7 @@ TF_MAKE_STATIC_DATA(PcpVariantFallbackMap, _usdGlobalVariantFallbackMap) PcpVariantFallbackMap fallbacks; PlugPluginPtrVector plugs = PlugRegistry::GetInstance().GetAllPlugins(); - TF_FOR_ALL(plugIter, plugs) { - PlugPluginPtr plug = *plugIter; + for (const auto& plug : plugs) { JsObject metadata = plug->GetMetadata(); JsValue dictVal; if (TfMapLookup(metadata, "UsdVariantFallbacks", &dictVal)) { @@ -138,9 +136,9 @@ TF_MAKE_STATIC_DATA(PcpVariantFallbackMap, _usdGlobalVariantFallbackMap) continue; } JsObject dict = dictVal.Get(); - TF_FOR_ALL(d, dict) { - std::string vset = d->first; - if (not d->second.IsArray()) { + for (const auto& d : dict) { + std::string vset = d.first; + if (not d.second.IsArray()) { TF_CODING_ERROR( "%s[UsdVariantFallbacks] value for %s must " "be an arrays.", @@ -148,7 +146,7 @@ TF_MAKE_STATIC_DATA(PcpVariantFallbackMap, _usdGlobalVariantFallbackMap) continue; } std::vector vsels = - d->second.GetArrayOf(); + d.second.GetArrayOf(); if (not vsels.empty()) { fallbacks[vset] = vsels; } @@ -531,8 +529,7 @@ UsdStage::_InstantiateStage(const SdfLayerRefPtr &rootLayer, stage->_RegisterPerLayerNotices(); // Publish this stage into all current writable caches. - BOOST_FOREACH(UsdStageCache *cache, - UsdStageCacheContext::_GetWritableCaches()) { + for (const auto cache : UsdStageCacheContext::_GetWritableCaches()) { cache->Insert(stage); } @@ -1746,23 +1743,24 @@ UsdStage::_LoadAndUnload(const SdfPathSet &loadSet, // loaded because we need to iterate and will enter an infinite loop if we // do not reduce the load set on each iteration. This manifests below in // the unloadedOnly=true argument. - TF_FOR_ALL(pathIt, loadSet) { - if (not _IsValidForLoadUnload(*pathIt)) + for (const auto& path : loadSet) { + if (not _IsValidForLoadUnload(path)) { continue; + } - _DiscoverPayloads(*pathIt, &finalLoadSet, true /*unloadedOnly*/); - _DiscoverAncestorPayloads(*pathIt, &finalLoadSet, - true /*unloadedOnly*/); + _DiscoverPayloads(path, &finalLoadSet, true /*unloadedOnly*/); + _DiscoverAncestorPayloads(path, &finalLoadSet, true /*unloadedOnly*/); } // Recursively populate the unload set. - TF_FOR_ALL(pathIt, unloadSet) { - if (not _IsValidForLoadUnload(*pathIt)) + for (const auto& path : unloadSet) { + if (not _IsValidForLoadUnload(path)) { continue; + } // PERFORMANCE: This should exclude any paths in the load set, // to avoid unloading and then reloading the same path. - _DiscoverPayloads(*pathIt, &finalUnloadSet); + _DiscoverPayloads(path, &finalUnloadSet); } // If we aren't changing the load set, terminate recursion. @@ -1775,21 +1773,21 @@ UsdStage::_LoadAndUnload(const SdfPathSet &loadSet, if (TfDebug::IsEnabled(USD_PAYLOADS)) { TF_DEBUG(USD_PAYLOADS).Msg("PAYLOAD: Load/Unload payload sets\n" " Include set:\n"); - TF_FOR_ALL(pathIt, loadSet) { - TF_DEBUG(USD_PAYLOADS).Msg("\t<%s>\n", pathIt->GetString().c_str()); + for (const auto& path : loadSet) { + TF_DEBUG(USD_PAYLOADS).Msg("\t<%s>\n", path.GetString().c_str()); } TF_DEBUG(USD_PAYLOADS).Msg(" Final Include set:\n"); - TF_FOR_ALL(pathIt, finalLoadSet) { - TF_DEBUG(USD_PAYLOADS).Msg("\t<%s>\n", pathIt->GetString().c_str()); + for (const auto& path : finalLoadSet) { + TF_DEBUG(USD_PAYLOADS).Msg("\t<%s>\n", path.GetString().c_str()); } TF_DEBUG(USD_PAYLOADS).Msg(" Exclude set:\n"); - TF_FOR_ALL(pathIt, unloadSet) { - TF_DEBUG(USD_PAYLOADS).Msg("\t<%s>\n", pathIt->GetString().c_str()); + for (const auto& path : unloadSet) { + TF_DEBUG(USD_PAYLOADS).Msg("\t<%s>\n", path.GetString().c_str()); } TF_DEBUG(USD_PAYLOADS).Msg(" Final Exclude set:\n"); - TF_FOR_ALL(pathIt, finalUnloadSet) { - TF_DEBUG(USD_PAYLOADS).Msg("\t<%s>\n", pathIt->GetString().c_str()); + for (const auto& path : finalUnloadSet) { + TF_DEBUG(USD_PAYLOADS).Msg("\t<%s>\n", path.GetString().c_str()); } } @@ -1826,7 +1824,7 @@ SdfPathSet UsdStage::GetLoadSet() { SdfPathSet loadSet; - BOOST_FOREACH(const SdfPath& primIndexPath, _cache->GetIncludedPayloads()) { + for (const auto& primIndexPath : _cache->GetIncludedPayloads()) { const SdfPath primPath = _GetPrimPathUsingPrimIndexAtPath(primIndexPath); if (TF_VERIFY(not primPath.IsEmpty(), "Unable to get prim path using " "prim index at path <%s>.", primIndexPath.GetText())) { @@ -1858,7 +1856,7 @@ UsdStage::GetMasters() const std::sort(masterPaths.begin(), masterPaths.end()); vector masterPrims; - BOOST_FOREACH(const SdfPath& path, masterPaths) { + for (const auto& path : masterPaths) { UsdPrim p = GetPrimAtPath(path); if (TF_VERIFY(p)) { masterPrims.push_back(p); @@ -1909,7 +1907,7 @@ UsdStage::_GetPrimPathUsingPrimIndexAtPath(const SdfPath& primIndexPath) const _instanceCache->GetPrimsInMastersUsingPrimIndexAtPath( primIndexPath); - BOOST_FOREACH(const SdfPath& pathInMaster, mastersUsingPrimIndex) { + for (const auto& pathInMaster : mastersUsingPrimIndex) { // If this path is a root prim path, it must be the path of a // master prim. This function wants to ignore master prims, // since they appear to have no prim index to the outside @@ -2040,15 +2038,17 @@ UsdStage::_ComposeChildren(Usd_PrimDataPtr prim, bool recurse) prim->GetPath().GetText()); SdfPath parentPath = prim->GetPath(); Usd_PrimDataPtr head = NULL, prev = NULL, cur = NULL; - TF_FOR_ALL(i, nameOrder) { - cur = _InstantiatePrim(parentPath.AppendChild(*i)); + for (const auto& child : nameOrder) { + cur = _InstantiatePrim(parentPath.AppendChild(child)); if (recurse) { _ComposeChildSubtree(cur, prim); } - if (not prev) + if (not prev) { head = cur; - else + } + else { prev->_SetSiblingLink(cur); + } prev = cur; } prim->_firstChild = head; @@ -2202,13 +2202,12 @@ UsdStage::_ReportErrors(const PcpErrorVector &errors, // Report any errors. if (not errors.empty() or not otherErrors.empty()) { std::string message = context + ":\n"; - BOOST_FOREACH(const PcpErrorBasePtr &err, errors) { - message += " " + - TfStringReplace(err->ToString(), "\n", "\n ") + '\n'; + for (const auto& err : errors) { + message += " " + TfStringReplace(err->ToString(), "\n", "\n ") + + '\n'; } - BOOST_FOREACH(const std::string &str, otherErrors) { - message += " " + - TfStringReplace(str, "\n", "\n ") + '\n'; + for (const auto& err : otherErrors) { + message += " " + TfStringReplace(err, "\n", "\n ") + '\n'; } TF_WARN(message); } @@ -2355,7 +2354,7 @@ UsdStage::_DestroyPrimsInParallel(const vector& paths) _primMapMutex = boost::in_place(); _dispatcher = boost::in_place(); - BOOST_FOREACH(const SdfPath& path, paths) { + for (const auto& path : paths) { Usd_PrimDataPtr prim = _GetPrimDataAtPath(path); _dispatcher->Run(&UsdStage::_DestroyPrim, this, prim); } @@ -2817,7 +2816,7 @@ _AddDependentPaths(const SdfLayerHandle &layer, const SdfPath &path, const PcpLayerStackPtrVector& layerStacks = cache.FindAllLayerStacksUsingLayer(layer); - BOOST_FOREACH(const PcpLayerStackPtr &layerStack, layerStacks) { + for (const auto& layerStack : layerStacks) { // If this path is in the cache's LayerStack, we always add it. if (layerStack == cache.GetLayerStack()) output->insert(path.StripAllVariantSelections()); @@ -2872,20 +2871,22 @@ UsdStage::_HandleLayersDidChange( // Add dependent paths for any PrimSpecs whose fields have changed that may // affect cached prim information. - TF_FOR_ALL(itr, n.GetChangeListMap()) { - + for(const auto& layerAndChangelist : n.GetChangeListMap()) { // If this layer does not pertain to us, skip. - if (_cache->FindAllLayerStacksUsingLayer(itr->first).empty()) + if (_cache->FindAllLayerStacksUsingLayer( + layerAndChangelist.first).empty()) { continue; + } - TF_FOR_ALL(entryIter, itr->second.GetEntryList()) { + for (const auto& entryList : layerAndChangelist.second.GetEntryList()) { - const SdfPath &path = entryIter->first; - const SdfChangeList::Entry &entry = entryIter->second; + const SdfPath &path = entryList.first; + const SdfChangeList::Entry &entry = entryList.second; TF_DEBUG(USD_CHANGES).Msg( "<%s> in @%s@ changed.\n", - path.GetText(), itr->first->GetIdentifier().c_str()); + path.GetText(), + layerAndChangelist.first->GetIdentifier().c_str()); bool willRecompose = false; if (path == SdfPath::AbsoluteRootPath() or @@ -2894,20 +2895,21 @@ UsdStage::_HandleLayersDidChange( if (entry.flags.didReorderChildren) { willRecompose = true; } else { - TF_FOR_ALL(infoIter, entry.infoChanged) { - if ((infoIter->first == SdfFieldKeys->Active) or - (infoIter->first == SdfFieldKeys->Kind) or - (infoIter->first == SdfFieldKeys->TypeName) or - (infoIter->first == SdfFieldKeys->Specifier) or + for (const auto& info : entry.infoChanged) { + const auto infoKey = info.first; + if ((infoKey == SdfFieldKeys->Active) or + (infoKey == SdfFieldKeys->Kind) or + (infoKey == SdfFieldKeys->TypeName) or + (infoKey == SdfFieldKeys->Specifier) or // XXX: Could be more specific when recomposing due // to clip changes. E.g., only update the clip // resolver and bits on each prim. - UsdIsClipRelatedField(infoIter->first)) { + UsdIsClipRelatedField(infoKey)) { TF_DEBUG(USD_CHANGES).Msg( "Changed field: %s\n", - infoIter->first.GetText()); + infoKey.GetText()); willRecompose = true; break; @@ -2916,8 +2918,8 @@ UsdStage::_HandleLayersDidChange( } if (willRecompose) { - _AddDependentPaths( - itr->first, path, *_cache, &pathsToRecompose); + _AddDependentPaths(layerAndChangelist.first, path, + *_cache, &pathsToRecompose); } } @@ -2925,8 +2927,8 @@ UsdStage::_HandleLayersDidChange( // scene paths separately so we can notify clients about the // changes. if (not willRecompose) { - _AddDependentPaths( - itr->first, path, *_cache, &otherChangedPaths); + _AddDependentPaths(layerAndChangelist.first, path, + *_cache, &otherChangedPaths); } } } @@ -3021,25 +3023,25 @@ void UsdStage::_Recompose(const PcpChanges &changes, if (not cacheChanges.empty()) { const PcpCacheChanges &ourChanges = cacheChanges.begin()->second; - TF_FOR_ALL(itr, ourChanges.didChangeSignificantly) { + for (const auto& path : ourChanges.didChangeSignificantly) { // Translate the real path from Pcp into a stage-relative path - pathsToRecompose->insert(*itr); + pathsToRecompose->insert(path); TF_DEBUG(USD_CHANGES).Msg("Did Change Significantly: %s\n", - itr->GetText()); + path.GetText()); } - TF_FOR_ALL(itr, ourChanges.didChangeSpecs) { + for (const auto& path : ourChanges.didChangeSpecs) { // Translate the real path from Pcp into a stage-relative path - pathsToRecompose->insert(*itr); + pathsToRecompose->insert(path); TF_DEBUG(USD_CHANGES).Msg("Did Change Spec: %s\n", - itr->GetText()); + path.GetText()); } - TF_FOR_ALL(itr, ourChanges.didChangePrims) { + for (const auto& path : ourChanges.didChangePrims) { // Translate the real path from Pcp into a stage-relative path - pathsToRecompose->insert(*itr); + pathsToRecompose->insert(path); TF_DEBUG(USD_CHANGES).Msg("Did Change Prim: %s\n", - itr->GetText()); + path.GetText()); } if (pathsToRecompose->empty()) { @@ -3058,8 +3060,8 @@ void UsdStage::_Recompose(const PcpChanges &changes, // of recomposition in the (likely) case that clip data hasn't changed // and the underlying clip layer can be reused. Usd_ClipCache::Lifeboat clipLifeboat; - TF_FOR_ALL(it, pathVecToRecompose) { - _clipCache->InvalidateClipsForPrim(*it, &clipLifeboat); + for (const auto& path : pathVecToRecompose) { + _clipCache->InvalidateClipsForPrim(path, &clipLifeboat); } typedef TfHashMap _MasterToPrimIndexMap; @@ -3070,7 +3072,7 @@ void UsdStage::_Recompose(const PcpChanges &changes, // stuff that's not active. SdfPathVector primPathsToRecompose; primPathsToRecompose.reserve(pathVecToRecompose.size()); - BOOST_FOREACH(const SdfPath &path, pathVecToRecompose) { + for (const SdfPath& path : pathVecToRecompose) { if (not path.IsAbsoluteRootOrPrimPath() or path.ContainsPrimVariantSelection()) { continue; @@ -3107,10 +3109,9 @@ void UsdStage::_Recompose(const PcpChanges &changes, // Determine what instance master prims on this stage need to // be recomposed due to instance prim index changes. SdfPathVector masterPrimsToRecompose; - BOOST_FOREACH(const SdfPath &path, primPathsToRecompose) { - BOOST_FOREACH( - const SdfPath& masterPath, - _instanceCache->GetPrimsInMastersUsingPrimIndexAtPath(path)) { + for (const SdfPath& path : primPathsToRecompose) { + for (const SdfPath& masterPath : + _instanceCache->GetPrimsInMastersUsingPrimIndexAtPath(path)) { masterPrimsToRecompose.push_back(masterPath); masterToPrimIndexMap[masterPath] = path; } @@ -3164,7 +3165,7 @@ void UsdStage::_Recompose(const PcpChanges &changes, SdfPathVector primIndexPathsForSubtrees; primIndexPathsForSubtrees.reserve(subtreesToRecompose.size()); - BOOST_FOREACH(const Usd_PrimDataPtr prim, subtreesToRecompose) { + for (const auto& prim : subtreesToRecompose) { primIndexPathsForSubtrees.push_back(TfMapLookupByValue( masterToPrimIndexMap, prim->GetPath(), prim->GetPath())); } @@ -3839,8 +3840,9 @@ static void _ApplyLayerOffset(Storage storage, const SdfTimeSampleMap &samples = _UncheckedGet(storage); SdfTimeSampleMap transformed; - TF_FOR_ALL(i, samples) - transformed[offset * i->first] = i->second; + for (const auto& sample : samples) { + transformed[offset * sample.first] = sample.second; + } _Set(storage, transformed); } } @@ -4652,7 +4654,7 @@ UsdStage::_ListMetadataFields(const UsdObject &obj, bool useFallbacks) const if (specType == SdfSpecTypeUnknown) specType = layer->GetSpecType(specId); - BOOST_FOREACH(const TfToken &fieldName, layer->ListFields(specId)) { + for (const auto& fieldName : layer->ListFields(specId)) { if (not _IsPrivateFieldKey(fieldName)) result.push_back(fieldName); } @@ -4662,7 +4664,7 @@ UsdStage::_ListMetadataFields(const UsdObject &obj, bool useFallbacks) const const SdfSchema::SpecDefinition* specDef = NULL; specDef = SdfSchema::GetInstance().GetSpecDefinition(specType); if (specDef) { - BOOST_FOREACH(const TfToken &fieldName, specDef->GetRequiredFields()) { + for (const auto& fieldName : specDef->GetRequiredFields()) { if (not _IsPrivateFieldKey(fieldName)) result.push_back(fieldName); } @@ -4671,7 +4673,7 @@ UsdStage::_ListMetadataFields(const UsdObject &obj, bool useFallbacks) const // If this is a builtin property, add any defined metadata fields. // XXX: this should handle prim definitions too. if (useFallbacks and propDef) { - BOOST_FOREACH(const TfToken &fieldName, propDef->ListFields()) { + for (const auto& fieldName : propDef->ListFields()) { if (not _IsPrivateFieldKey(fieldName)) result.push_back(fieldName); } @@ -4694,7 +4696,7 @@ UsdStage::_GetAllMetadata(const UsdObject &obj, UsdMetadataValueMap &result = *resultMap; TfTokenVector fieldNames = _ListMetadataFields(obj, useFallbacks); - BOOST_FOREACH(const TfToken &fieldName, fieldNames) { + for (const auto& fieldName : fieldNames) { VtValue val; StrongestValueComposer composer(&val); _GetMetadataImpl(obj, fieldName, TfToken(), useFallbacks, &composer); @@ -5354,8 +5356,8 @@ UsdStage::_GetValueFromResolveInfoImpl(const Usd_ResolveInfo &info, const std::vector& clipsAffectingPrim = _clipCache->GetClipsForPrim(prim.GetPath()); - TF_FOR_ALL(clipsIt, clipsAffectingPrim) { - const Usd_ClipRefPtrVector& clips = clipsIt->valueClips; + for (const auto& clipAffectingPrim : clipsAffectingPrim) { + const Usd_ClipRefPtrVector& clips = clipAffectingPrim.valueClips; for (size_t i = 0, numClips = clips.size(); i < numClips; ++i) { // Note that we do not apply layer offsets to the time. // Because clip metadata may be authored in different @@ -5442,12 +5444,12 @@ UsdStage::_GetTimeSampleMap(const UsdAttribute &attr, // for values on times where we know there are authored time samples. Usd_NullInterpolator nullInterpolator; - TF_FOR_ALL(t, timeSamples) { + for (const auto& timeSample : timeSamples) { VtValue value; - if (_GetValueImpl(*t, attr, &nullInterpolator, &value)) { - (*out)[*t] = value; + if (_GetValueImpl(timeSample, attr, &nullInterpolator, &value)) { + (*out)[timeSample] = value; } else { - (*out)[*t] = VtValue(SdfValueBlock()); + (*out)[timeSample] = VtValue(SdfValueBlock()); } } return true; @@ -5532,9 +5534,8 @@ UsdStage::_GetTimeSamplesInIntervalFromResolveInfo( // Loop through all the clips that apply to this node and // combine all the time samples that are provided. - TF_FOR_ALL(clipsIt, clipsAffectingPrim) { - TF_FOR_ALL(clipIt, clipsIt->valueClips) { - const Usd_ClipRefPtr& clip = *clipIt; + for (const auto& clipAffectingPrim : clipsAffectingPrim) { + for (const auto& clip : clipAffectingPrim.valueClips) { if (not _ClipAppliesToLayerStackSite( clip, info.layerStack, info.primPathInLayerStack)) { continue; @@ -5733,10 +5734,8 @@ UsdStage::_GetBracketingTimeSamplesFromResolveInfo(const Usd_ResolveInfo &info, const std::vector& clipsAffectingPrim = _clipCache->GetClipsForPrim(prim.GetPath()); - TF_FOR_ALL(clipsIt, clipsAffectingPrim) { - TF_FOR_ALL(clipIt, clipsIt->valueClips) { - const Usd_ClipRefPtr& clip = *clipIt; - + for (const auto& clipAffectingPrim : clipsAffectingPrim) { + for (const auto& clip : clipAffectingPrim.valueClips) { if (not _ClipAppliesToLayerStackSite( clip, info.layerStack, info.primPathInLayerStack) or desiredTime < clip->startTime @@ -5885,9 +5884,8 @@ UsdStage::_ValueMightBeTimeVaryingFromResolveInfo(const Usd_ResolveInfo &info, const std::vector& clipsAffectingPrim = _clipCache->GetClipsForPrim(attr.GetPrim().GetPath()); - TF_FOR_ALL(clipsIt, clipsAffectingPrim) { - TF_FOR_ALL(clipIt, clipsIt->valueClips) { - const Usd_ClipRefPtr& clip = *clipIt; + for (const auto& clipAffectingPrim : clipsAffectingPrim) { + for (const auto& clip : clipAffectingPrim.valueClips) { if (_ClipAppliesToLayerStackSite( clip, info.layerStack, info.primPathInLayerStack) and _HasTimeSamples(clip, specId)) { diff --git a/pxr/usd/lib/usd/stageCache.cpp b/pxr/usd/lib/usd/stageCache.cpp index 46f047171a..34bb1bd1df 100644 --- a/pxr/usd/lib/usd/stageCache.cpp +++ b/pxr/usd/lib/usd/stageCache.cpp @@ -32,7 +32,6 @@ #include "pxr/base/arch/nap.h" #include -#include #include #include #include @@ -384,7 +383,9 @@ UsdStageCache::FindOneMatching(const SdfLayerHandle &rootLayer, UsdStageRefPtr result; { LockGuard lock(_mutex); StagesByRootLayer &byRootLayer = _impl->stages.get(); - BOOST_FOREACH(const Entry &entry, byRootLayer.equal_range(rootLayer)) { + auto range = byRootLayer.equal_range(rootLayer); + for (auto entryIt = range.first; entryIt != range.second; ++entryIt) { + const auto& entry = *entryIt; if (entry.stage->GetSessionLayer() == sessionLayer) { result = entry.stage; break; @@ -411,7 +412,9 @@ UsdStageCache::FindOneMatching( UsdStageRefPtr result; { LockGuard lock(_mutex); StagesByRootLayer &byRootLayer = _impl->stages.get(); - BOOST_FOREACH(const Entry &entry, byRootLayer.equal_range(rootLayer)) { + auto range = byRootLayer.equal_range(rootLayer); + for (auto entryIt = range.first; entryIt != range.second; ++entryIt) { + const auto& entry = *entryIt; if (entry.stage->GetPathResolverContext() == pathResolverContext) { result = entry.stage; break; @@ -437,7 +440,9 @@ UsdStageCache::FindOneMatching( UsdStageRefPtr result; { LockGuard lock(_mutex); StagesByRootLayer &byRootLayer = _impl->stages.get(); - BOOST_FOREACH(const Entry &entry, byRootLayer.equal_range(rootLayer)) { + auto range = byRootLayer.equal_range(rootLayer); + for (auto entryIt = range.first; entryIt != range.second; ++entryIt) { + const auto& entry = *entryIt; if (entry.stage->GetSessionLayer() == sessionLayer and entry.stage->GetPathResolverContext() == pathResolverContext) { result = entry.stage; @@ -463,8 +468,11 @@ UsdStageCache::FindAllMatching(const SdfLayerHandle &rootLayer) const LockGuard lock(_mutex); StagesByRootLayer &byRootLayer = _impl->stages.get(); vector result; - BOOST_FOREACH(const Entry &entry, byRootLayer.equal_range(rootLayer)) + auto range = byRootLayer.equal_range(rootLayer); + for (auto entryIt = range.first; entryIt != range.second; ++entryIt) { + const auto& entry = *entryIt; result.push_back(entry.stage); + } return result; } @@ -475,7 +483,9 @@ UsdStageCache::FindAllMatching(const SdfLayerHandle &rootLayer, LockGuard lock(_mutex); StagesByRootLayer &byRootLayer = _impl->stages.get(); vector result; - BOOST_FOREACH(const Entry &entry, byRootLayer.equal_range(rootLayer)) { + auto range = byRootLayer.equal_range(rootLayer); + for (auto entryIt = range.first; entryIt != range.second; ++entryIt) { + const auto& entry = *entryIt; if (entry.stage->GetSessionLayer() == sessionLayer) result.push_back(entry.stage); } @@ -490,7 +500,9 @@ UsdStageCache::FindAllMatching( LockGuard lock(_mutex); StagesByRootLayer &byRootLayer = _impl->stages.get(); vector result; - BOOST_FOREACH(const Entry &entry, byRootLayer.equal_range(rootLayer)) { + auto range = byRootLayer.equal_range(rootLayer); + for (auto entryIt = range.first; entryIt != range.second; ++entryIt) { + const auto& entry = *entryIt; if (entry.stage->GetPathResolverContext() == pathResolverContext) result.push_back(entry.stage); } @@ -506,7 +518,9 @@ UsdStageCache::FindAllMatching( LockGuard lock(_mutex); StagesByRootLayer &byRootLayer = _impl->stages.get(); vector result; - BOOST_FOREACH(const Entry &entry, byRootLayer.equal_range(rootLayer)) { + auto range = byRootLayer.equal_range(rootLayer); + for (auto entryIt = range.first; entryIt != range.second; ++entryIt) { + const auto& entry = *entryIt; if (entry.stage->GetSessionLayer() == sessionLayer and entry.stage->GetPathResolverContext() == pathResolverContext) { result.push_back(entry.stage); diff --git a/pxr/usd/lib/usd/stageCacheContext.cpp b/pxr/usd/lib/usd/stageCacheContext.cpp index 3ba3a8bfd0..512c0967f7 100644 --- a/pxr/usd/lib/usd/stageCacheContext.cpp +++ b/pxr/usd/lib/usd/stageCacheContext.cpp @@ -27,8 +27,6 @@ #include "pxr/base/tf/registryManager.h" #include "pxr/base/tf/instantiateStacked.h" -#include - using std::vector; TF_INSTANTIATE_STACKED(UsdStageCacheContext); @@ -46,7 +44,8 @@ UsdStageCacheContext::_GetReadOnlyCaches() const Stack &stack = GetStack(); vector caches; caches.reserve(stack.size()); - BOOST_REVERSE_FOREACH(const UsdStageCacheContext *ctx, stack) { + for (auto ctxIter = stack.rbegin(); ctxIter != stack.rend(); ++ctxIter) { + const auto& ctx = *ctxIter; if (ctx->_blockType == UsdBlockStageCaches) { break; } else if (ctx->_blockType == UsdBlockStageCachePopulation) { @@ -65,7 +64,8 @@ UsdStageCacheContext::_GetReadableCaches() const Stack &stack = GetStack(); vector caches; caches.reserve(stack.size()); - BOOST_REVERSE_FOREACH(const UsdStageCacheContext *ctx, stack) { + for (auto ctxIter = stack.rbegin(); ctxIter != stack.rend(); ++ctxIter) { + const auto& ctx = *ctxIter; if (ctx->_blockType == UsdBlockStageCaches) { break; } else if (ctx->_blockType == UsdBlockStageCachePopulation) { @@ -85,7 +85,8 @@ UsdStageCacheContext::_GetWritableCaches() const Stack &stack = GetStack(); vector caches; caches.reserve(stack.size()); - BOOST_REVERSE_FOREACH(const UsdStageCacheContext *ctx, stack) { + for (auto ctxIter = stack.rbegin(); ctxIter != stack.rend(); ++ctxIter) { + const auto& ctx = *ctxIter; if (ctx->_blockType == UsdBlockStageCaches or ctx->_blockType == UsdBlockStageCachePopulation) { break; diff --git a/pxr/usd/lib/usd/treeIterator.cpp b/pxr/usd/lib/usd/treeIterator.cpp index 55eecfb4d0..2281897420 100644 --- a/pxr/usd/lib/usd/treeIterator.cpp +++ b/pxr/usd/lib/usd/treeIterator.cpp @@ -26,7 +26,6 @@ #include "pxr/usd/usd/prim.h" #include "pxr/usd/usd/stage.h" -#include "pxr/base/tf/iterator.h" #include "pxr/base/tf/diagnostic.h" UsdTreeIterator diff --git a/pxr/usd/lib/usd/variantSets.cpp b/pxr/usd/lib/usd/variantSets.cpp index d583609933..cd770ac656 100644 --- a/pxr/usd/lib/usd/variantSets.cpp +++ b/pxr/usd/lib/usd/variantSets.cpp @@ -38,8 +38,6 @@ #include "pxr/usd/pcp/composeSite.h" #include "pxr/usd/pcp/primIndex.h" -#include - using std::string; using std::vector; @@ -52,8 +50,8 @@ UsdVariantSet::FindOrCreateVariant(const std::string& variantName) { if (SdfVariantSetSpecHandle varSet = _FindOrCreateVariantSet()){ // If the variant spec already exists, we don't need to create it - TF_FOR_ALL(it, varSet->GetVariants()){ - if ((*it)->GetName() == variantName){ + for (const auto& variant : varSet->GetVariants()) { + if (variant->GetName() == variantName){ return true; } } @@ -92,10 +90,13 @@ UsdVariantSet::GetVariantSelection() const // Scan the composed prim for variant arcs for this variant set and // return the first selection found. This ensures that we reflect // whatever composition process selected the variant, such as fallbacks. - TF_FOR_ALL(i, _prim.GetPrimIndex().GetNodeRange()) { - if (i->GetArcType() == PcpArcTypeVariant) { + for (auto nodeIter = _prim.GetPrimIndex().GetNodeRange().first; + nodeIter != _prim.GetPrimIndex().GetNodeRange().second; + ++nodeIter) + { + if (nodeIter->GetArcType() == PcpArcTypeVariant) { std::pair vsel = - i->GetSite().path.GetVariantSelection(); + nodeIter->GetSite().path.GetVariantSelection(); if (vsel.first == _variantSetName) { return vsel.second; } @@ -107,12 +108,16 @@ UsdVariantSet::GetVariantSelection() const bool UsdVariantSet::HasAuthoredVariantSelection(std::string *value) const { - TF_FOR_ALL(i, _prim.GetPrimIndex().GetNodeRange()) { - string sel; - if (not value) + for (auto nodeIter = _prim.GetPrimIndex().GetNodeRange().first; + nodeIter != _prim.GetPrimIndex().GetNodeRange().second; + ++nodeIter) + { + string sel; + if (not value) { value = &sel; + } if (PcpComposeSiteVariantSelection( - i->GetSite(), _variantSetName, value)) { + nodeIter->GetSite(), _variantSetName, value)) { return true; } } From cd61ddf85a91eaca8362d44380040f96d0b13376 Mon Sep 17 00:00:00 2001 From: unhyperbolic Date: Mon, 17 Oct 2016 15:37:04 -0700 Subject: [PATCH 266/380] Remove enableShadows flag from HdxShadowTask (Internal change: 1665057) --- pxr/imaging/lib/hdx/shadowTask.cpp | 188 +++++++++++------------ pxr/imaging/lib/hdx/shadowTask.h | 3 - pxr/imaging/lib/hdx/unitTestDelegate.cpp | 1 - 3 files changed, 86 insertions(+), 106 deletions(-) diff --git a/pxr/imaging/lib/hdx/shadowTask.cpp b/pxr/imaging/lib/hdx/shadowTask.cpp index 0737b5332c..3678cc1f0a 100644 --- a/pxr/imaging/lib/hdx/shadowTask.cpp +++ b/pxr/imaging/lib/hdx/shadowTask.cpp @@ -43,7 +43,6 @@ HdxShadowTask::HdxShadowTask(HdSceneDelegate* delegate, SdfPath const& id) : HdSceneTask(delegate, id) , _collectionVersion(0) - , _enableShadows(false) , _depthBiasEnable(false) , _depthBiasConstantFactor(0.0f) , _depthBiasSlopeFactor(1.0f) @@ -57,12 +56,6 @@ HdxShadowTask::_Execute(HdTaskContext* ctx) HD_TRACE_FUNCTION(); HD_MALLOC_TAG_FUNCTION(); - // When the shadows are not enabled we don't need to do any - // shadow map computation - if (not _enableShadows) { - return; - } - // Extract the lighting context information from the task context GlfSimpleLightingContextRefPtr lightingContext; if (not _GetTaskContextData(ctx, HdxTokens->lightingContext, &lightingContext)) { @@ -146,11 +139,6 @@ HdxShadowTask::_Sync(HdTaskContext* ctx) return; } - // Store if the shadows need to be generated or not, - // this flag will be used to early out during Execute step when - // shadows are not needed - _enableShadows = params.enableShadows; - _depthBiasEnable = params.depthBiasEnable; _depthBiasConstantFactor = params.depthBiasConstantFactor; _depthBiasSlopeFactor = params.depthBiasSlopeFactor; @@ -163,99 +151,97 @@ HdxShadowTask::_Sync(HdTaskContext* ctx) _passes.clear(); _renderPassStates.clear(); - if (_enableShadows) { - HdSceneDelegate* delegate = GetDelegate(); - - // Extract the HD lights used to render the scene from the - // task context, we will use them to find out what - // lights are dirty and if we need to update the - // collection for shadows mapping - - // XXX: This is inefficient, need to be optimized - SdfPathVector sprimPaths = delegate->GetRenderIndex().GetSprimSubtree( - SdfPath::AbsoluteRootPath()); - SdfPathVector lightPaths = - HdxSimpleLightTask::ComputeIncludedLights( - sprimPaths, - params.lightIncludePaths, - params.lightExcludePaths); - - HdSprimSharedPtrVector lights; - TF_FOR_ALL (it, lightPaths) { - HdSprimSharedPtr const &sprim = delegate->GetRenderIndex().GetSprim(*it); - // XXX: or we could say instead of downcast, - // sprim->Has(HdxLightInterface) ? - if (boost::dynamic_pointer_cast(sprim)) { - lights.push_back(sprim); - } + HdSceneDelegate* delegate = GetDelegate(); + + // Extract the HD lights used to render the scene from the + // task context, we will use them to find out what + // lights are dirty and if we need to update the + // collection for shadows mapping + + // XXX: This is inefficient, need to be optimized + SdfPathVector sprimPaths = delegate->GetRenderIndex().GetSprimSubtree( + SdfPath::AbsoluteRootPath()); + SdfPathVector lightPaths = + HdxSimpleLightTask::ComputeIncludedLights( + sprimPaths, + params.lightIncludePaths, + params.lightExcludePaths); + + HdSprimSharedPtrVector lights; + TF_FOR_ALL (it, lightPaths) { + HdSprimSharedPtr const &sprim = delegate->GetRenderIndex().GetSprim(*it); + // XXX: or we could say instead of downcast, + // sprim->Has(HdxLightInterface) ? + if (boost::dynamic_pointer_cast(sprim)) { + lights.push_back(sprim); + } + } + + GlfSimpleLightVector const glfLights = lightingContext->GetLights(); + + TF_VERIFY(lights.size() == glfLights.size()); + + // Iterate through all lights and for those that have + // shadows enabled we will extract the colection from + // the render index and create a pass that during execution + // it will be used for generating each shadowmap + for (size_t lightId = 0; lightId < glfLights.size(); lightId++) { + + if (not glfLights[lightId].HasShadow()) { + continue; } - - GlfSimpleLightVector const glfLights = lightingContext->GetLights(); - - TF_VERIFY(lights.size() == glfLights.size()); - - // Iterate through all lights and for those that have - // shadows enabled we will extract the colection from - // the render index and create a pass that during execution - // it will be used for generating each shadowmap - for (size_t lightId = 0; lightId < glfLights.size(); lightId++) { - - if (not glfLights[lightId].HasShadow()) { - continue; - } - // Extract the collection from the HD light - VtValue vtShadowCollection = - lights[lightId]->Get(HdxLightTokens->shadowCollection); - const HdRprimCollection &col = - vtShadowCollection.IsHolding() ? + // Extract the collection from the HD light + VtValue vtShadowCollection = + lights[lightId]->Get(HdxLightTokens->shadowCollection); + const HdRprimCollection &col = + vtShadowCollection.IsHolding() ? vtShadowCollection.Get() : HdRprimCollection(); - // Creates a pass with the right geometry that will be - // use during Execute phase to draw the maps - HdRenderPassSharedPtr p = boost::make_shared - (&delegate->GetRenderIndex(), col); - - HdRenderPassStateSharedPtr renderPassState(new HdRenderPassState()); - - // Update the rest of the renderpass state parameters for this pass - renderPassState->SetOverrideColor(params.overrideColor); - renderPassState->SetWireframeColor(params.wireframeColor); - renderPassState->SetLightingEnabled(false); - // XXX : This can be removed when Hydra has support for - // transparent objects. - renderPassState->SetAlphaThreshold(1.0 /* params.alphaThreshold */); - renderPassState->SetTessLevel(params.tessLevel); - renderPassState->SetDrawingRange(params.drawingRange); - - // Invert front and back faces for shadow - // XXX: this should be taken care by shadow-repr. - switch (params.cullStyle) - { - case HdCullStyleBack: - renderPassState->SetCullStyle(HdCullStyleFront); - break; - - case HdCullStyleFront: - renderPassState->SetCullStyle(HdCullStyleBack); - break; - - case HdCullStyleBackUnlessDoubleSided: - renderPassState->SetCullStyle(HdCullStyleFrontUnlessDoubleSided); - break; - - case HdCullStyleFrontUnlessDoubleSided: - renderPassState->SetCullStyle(HdCullStyleBackUnlessDoubleSided); - break; - - default: - renderPassState->SetCullStyle(params.cullStyle); - break; - } - - _passes.push_back(p); - _renderPassStates.push_back(renderPassState); + // Creates a pass with the right geometry that will be + // use during Execute phase to draw the maps + HdRenderPassSharedPtr p = boost::make_shared + (&delegate->GetRenderIndex(), col); + + HdRenderPassStateSharedPtr renderPassState(new HdRenderPassState()); + + // Update the rest of the renderpass state parameters for this pass + renderPassState->SetOverrideColor(params.overrideColor); + renderPassState->SetWireframeColor(params.wireframeColor); + renderPassState->SetLightingEnabled(false); + // XXX : This can be removed when Hydra has support for + // transparent objects. + renderPassState->SetAlphaThreshold(1.0 /* params.alphaThreshold */); + renderPassState->SetTessLevel(params.tessLevel); + renderPassState->SetDrawingRange(params.drawingRange); + + // Invert front and back faces for shadow + // XXX: this should be taken care by shadow-repr. + switch (params.cullStyle) + { + case HdCullStyleBack: + renderPassState->SetCullStyle(HdCullStyleFront); + break; + + case HdCullStyleFront: + renderPassState->SetCullStyle(HdCullStyleBack); + break; + + case HdCullStyleBackUnlessDoubleSided: + renderPassState->SetCullStyle(HdCullStyleFrontUnlessDoubleSided); + break; + + case HdCullStyleFrontUnlessDoubleSided: + renderPassState->SetCullStyle(HdCullStyleBackUnlessDoubleSided); + break; + + default: + renderPassState->SetCullStyle(params.cullStyle); + break; } + + _passes.push_back(p); + _renderPassStates.push_back(renderPassState); } } @@ -292,7 +278,6 @@ std::ostream& operator<<(std::ostream& out, const HdxShadowTaskParams& pv) << pv.cullStyle << " " << pv.camera << " " << pv.viewport << " " - << pv.enableShadows << " " ; TF_FOR_ALL(it, pv.lightIncludePaths) { out << *it; @@ -319,7 +304,6 @@ bool operator==(const HdxShadowTaskParams& lhs, const HdxShadowTaskParams& rhs) lhs.cullStyle == rhs.cullStyle and lhs.camera == rhs.camera and lhs.viewport == rhs.viewport and - lhs.enableShadows == rhs.enableShadows and lhs.lightIncludePaths == rhs.lightIncludePaths and lhs.lightExcludePaths == rhs.lightExcludePaths ; diff --git a/pxr/imaging/lib/hdx/shadowTask.h b/pxr/imaging/lib/hdx/shadowTask.h index 0c2b1e6499..9f1ec5fc88 100644 --- a/pxr/imaging/lib/hdx/shadowTask.h +++ b/pxr/imaging/lib/hdx/shadowTask.h @@ -65,7 +65,6 @@ class HdxShadowTask : public HdSceneTask { HdRenderPassSharedPtrVector _passes; HdRenderPassStateSharedPtrVector _renderPassStates; int _collectionVersion; - bool _enableShadows; /// Polygon Offset State bool _depthBiasEnable; @@ -95,7 +94,6 @@ struct HdxShadowTaskParams : public HdTaskParams , viewport(0.0) , lightIncludePaths(1, SdfPath::AbsoluteRootPath()) , lightExcludePaths() - , enableShadows(false) {} // RenderPassState @@ -120,7 +118,6 @@ struct HdxShadowTaskParams : public HdTaskParams // Lights/Shadows specific paramenters SdfPathVector lightIncludePaths; SdfPathVector lightExcludePaths; - bool enableShadows; }; // VtValue requirements diff --git a/pxr/imaging/lib/hdx/unitTestDelegate.cpp b/pxr/imaging/lib/hdx/unitTestDelegate.cpp index cc2fe38ad1..e65e9f7a15 100644 --- a/pxr/imaging/lib/hdx/unitTestDelegate.cpp +++ b/pxr/imaging/lib/hdx/unitTestDelegate.cpp @@ -360,7 +360,6 @@ Hdx_UnitTestDelegate::AddShadowTask(SdfPath const &id) HdxShadowTaskParams params; params.camera = _cameraId; params.viewport = GfVec4f(0,0,512,512); - params.enableShadows = true; cache[HdTokens->children] = VtValue(SdfPathVector()); cache[HdTokens->params] = VtValue(params); } From 2b27122400985ce76dd91b870ef29f3ee5b366af Mon Sep 17 00:00:00 2001 From: unhyperbolic Date: Mon, 17 Oct 2016 16:04:40 -0700 Subject: [PATCH 267/380] In GlfSimpleShadowArray, introducing guards to some Getters so that we don't crash when binding lights and the shadow pass hadn't been run due to some other error. (Internal change: 1665181) --- pxr/imaging/lib/glf/simpleShadowArray.cpp | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/pxr/imaging/lib/glf/simpleShadowArray.cpp b/pxr/imaging/lib/glf/simpleShadowArray.cpp index 5a723c3e4a..d1c1eb1489 100644 --- a/pxr/imaging/lib/glf/simpleShadowArray.cpp +++ b/pxr/imaging/lib/glf/simpleShadowArray.cpp @@ -87,24 +87,40 @@ GlfSimpleShadowArray::SetNumLayers(size_t numLayers) GfMatrix4d GlfSimpleShadowArray::GetViewMatrix(size_t index) const { + if (not TF_VERIFY(index < _viewMatrix.size())) { + return GfMatrix4d(1.0); + } + return _viewMatrix[index]; } void GlfSimpleShadowArray::SetViewMatrix(size_t index, GfMatrix4d const & matrix) { + if (not TF_VERIFY(index < _viewMatrix.size())) { + return; + } + _viewMatrix[index] = matrix; } GfMatrix4d GlfSimpleShadowArray::GetProjectionMatrix(size_t index) const { + if (not TF_VERIFY(index < _projectionMatrix.size())) { + return GfMatrix4d(1.0); + } + return _projectionMatrix[index]; } void GlfSimpleShadowArray::SetProjectionMatrix(size_t index, GfMatrix4d const & matrix) { + if (not TF_VERIFY(index < _projectionMatrix.size())) { + return; + } + _projectionMatrix[index] = matrix; } From c54a96213c9af65b134d3afabc0aa9e461b310ad Mon Sep 17 00:00:00 2001 From: takahito-tejima Date: Mon, 17 Oct 2016 16:11:28 -0700 Subject: [PATCH 268/380] Removing glfq from pxr glfq is the last Qt C++ dependency in pxr. In pxr, it's being used for enabling debug context in usdview. it's useful, but we think it doesn't worth to ask Qt dependency just for it, and we have another way to debug GL errors such as API trace and GL debugger. For GL debugging in usdview, we'll revisit to add that functionality in another way later on. (Internal change: 1665204) --- pxr/imaging/lib/CMakeLists.txt | 1 - pxr/imaging/lib/glfq/CMakeLists.txt | 40 ----------- pxr/imaging/lib/glfq/__init__.py | 63 ----------------- pxr/imaging/lib/glfq/glDebugContext.cpp | 86 ------------------------ pxr/imaging/lib/glfq/glDebugContext.h | 66 ------------------ pxr/imaging/lib/glfq/module.cpp | 28 -------- pxr/imaging/lib/glfq/moduleDeps.cpp | 52 -------------- pxr/imaging/lib/glfq/overview.dox | 61 ----------------- pxr/usdImaging/lib/usdviewq/stageView.py | 4 +- 9 files changed, 1 insertion(+), 400 deletions(-) delete mode 100644 pxr/imaging/lib/glfq/CMakeLists.txt delete mode 100644 pxr/imaging/lib/glfq/__init__.py delete mode 100644 pxr/imaging/lib/glfq/glDebugContext.cpp delete mode 100644 pxr/imaging/lib/glfq/glDebugContext.h delete mode 100644 pxr/imaging/lib/glfq/module.cpp delete mode 100644 pxr/imaging/lib/glfq/moduleDeps.cpp delete mode 100644 pxr/imaging/lib/glfq/overview.dox diff --git a/pxr/imaging/lib/CMakeLists.txt b/pxr/imaging/lib/CMakeLists.txt index 33a3aece63..ffa79d865e 100644 --- a/pxr/imaging/lib/CMakeLists.txt +++ b/pxr/imaging/lib/CMakeLists.txt @@ -4,7 +4,6 @@ set(DIRS glf pxOsd hd - glfq hdx ) diff --git a/pxr/imaging/lib/glfq/CMakeLists.txt b/pxr/imaging/lib/glfq/CMakeLists.txt deleted file mode 100644 index 5fb6fa9725..0000000000 --- a/pxr/imaging/lib/glfq/CMakeLists.txt +++ /dev/null @@ -1,40 +0,0 @@ -set(PXR_PREFIX pxr/imaging) -set(PXR_PACKAGE glfq) - -if (NOT QT4_FOUND) - message(WARNING "Not building ${PXR_PACKAGE} because of missing dependency: Qt4") - return() -endif() - -pxr_shared_library(glfq - LIBRARIES - garch - glf - arch - tf - Qt4::QtCore - Qt4::QtGui - Qt4::QtOpenGL - Qt4::QtXml - Qt4::QtNetwork - ${Boost_SYSTEM_LIBRARY} - ${OPENGL_gl_LIBRARY} - ${GLEW_LIBRARY} - - INCLUDE_DIRS - ${Boost_INCLUDE_DIRS} - ${GLEW_INCLUDE_DIR} - - PUBLIC_CLASSES - glDebugContext - - CPPFILES - moduleDeps.cpp - - PYMODULE_CPPFILES - module.cpp - - PYTHON_FILES - __init__.py - -) diff --git a/pxr/imaging/lib/glfq/__init__.py b/pxr/imaging/lib/glfq/__init__.py deleted file mode 100644 index ca14ab81b3..0000000000 --- a/pxr/imaging/lib/glfq/__init__.py +++ /dev/null @@ -1,63 +0,0 @@ -# -# 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. -# -""" -glfq - -""" - -import _glfq -from pxr import Tf -Tf.PrepareModule(_glfq, locals()) -del _glfq, Tf - -def CreateGLDebugContext(glFormat): - from PySide import QtOpenGL - class GLDebugContext(QtOpenGL.QGLContext): - def __init__(self, glFormat): - QtOpenGL.QGLContext.__init__(self, glFormat) - self._platformContext = None - - def create(self, shareContext): - self._platformContext = None - return QtOpenGL.QGLContext.create(self, shareContext) - - def makeCurrent(self): - from pxr import Garch - QtOpenGL.QGLContext.makeCurrent(self) - if not self._platformContext: - self._platformContext = Garch.GLPlatformDebugContext( - self.format().majorVersion(), - self.format().minorVersion(), - self.format().profile() == QtOpenGL.QGLFormat.CoreProfile, - self.format().directRendering()) - self._platformContext.makeCurrent() - return GLDebugContext(glFormat) - -try: - from . import __DOC - __DOC.Execute(locals()) - del __DOC -except Exception: - pass - diff --git a/pxr/imaging/lib/glfq/glDebugContext.cpp b/pxr/imaging/lib/glfq/glDebugContext.cpp deleted file mode 100644 index 90eb140702..0000000000 --- a/pxr/imaging/lib/glfq/glDebugContext.cpp +++ /dev/null @@ -1,86 +0,0 @@ -// -// 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. -// -#include "pxr/imaging/glfq/glDebugContext.h" -#include "pxr/imaging/garch/glPlatformDebugContext.h" - -#include "pxr/base/tf/diagnostic.h" - -GlfQGLDebugContext::GlfQGLDebugContext(const QGLFormat & format) - : QGLContext(format) -{ - // nothing -} - -GlfQGLDebugContext::~GlfQGLDebugContext() -{ - // nothing -} - -/* virtual */ -bool -GlfQGLDebugContext::create(const QGLContext * shareContext) -{ - _platformContext.reset(); - return Parent::create(shareContext); -} - -/* virtual */ -void -GlfQGLDebugContext::makeCurrent() -{ - Parent::makeCurrent(); - if (not _platformContext) { - _platformContext.reset(new - GarchGLPlatformDebugContext( - format().majorVersion(), - format().minorVersion(), - format().profile() == QGLFormat::CoreProfile, - format().directRendering())); - } - TF_VERIFY(_platformContext); - _platformContext->makeCurrent(); - -} - -#if defined(ARCH_OS_DARWIN) -/* virtual */ -void* -GlfQGLDebugContext::chooseMacVisual(GDHandle handle) -{ - if (not _platformContext) { - _platformContext.reset(new - GarchGLPlatformDebugContext( - format().majorVersion(), - format().minorVersion(), - format().profile() == QGLFormat::CoreProfile, - format().directRendering())); - } - TF_VERIFY(_platformContext); - void * visual = _platformContext->chooseMacVisual(); - if (not visual) { - return Parent::chooseMacVisual(handle); - } - return visual; -} -#endif diff --git a/pxr/imaging/lib/glfq/glDebugContext.h b/pxr/imaging/lib/glfq/glDebugContext.h deleted file mode 100644 index 0a438fc20b..0000000000 --- a/pxr/imaging/lib/glfq/glDebugContext.h +++ /dev/null @@ -1,66 +0,0 @@ -// -// 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 GLFQ_GLDEBUG_CONTEXT_H -#define GLFQ_GLDEBUG_CONTEXT_H - -#include "pxr/base/arch/defines.h" -#include "pxr/base/tf/declarePtrs.h" -#include "pxr/base/tf/weakBase.h" - -#include - -#include - -class GarchGLPlatformDebugContext; - -TF_DECLARE_WEAK_PTRS(GlfQGLDebugContext); - -/// \class GlfQGLDebugContext -/// -/// Extends QGLContext to support OpenGL Debug Output. -/// -/// Unextended Qt does not support the creation of a GL context that -/// enables GL Debug Output. This class extends QGLContext by -/// creating a context which does support GL Debug Output. -/// -class GlfQGLDebugContext : public QGLContext, public TfWeakBase { -public: - typedef QGLContext Parent; - -public: - GlfQGLDebugContext(const QGLFormat & format); - virtual ~GlfQGLDebugContext(); - - // QGLContext overrides - virtual bool create(const QGLContext * shareContext); - virtual void makeCurrent(); -#if defined(ARCH_OS_DARWIN) - virtual void* chooseMacVisual(GDHandle handle); -#endif - -public: - boost::scoped_ptr _platformContext; -}; - -#endif // GLFQ_GL_DEBUG_CONTEXT_H diff --git a/pxr/imaging/lib/glfq/module.cpp b/pxr/imaging/lib/glfq/module.cpp deleted file mode 100644 index 70395ad5c5..0000000000 --- a/pxr/imaging/lib/glfq/module.cpp +++ /dev/null @@ -1,28 +0,0 @@ -// -// 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. -// -#include "pxr/base/tf/pyModule.h" - -TF_WRAP_MODULE -{ -} diff --git a/pxr/imaging/lib/glfq/moduleDeps.cpp b/pxr/imaging/lib/glfq/moduleDeps.cpp deleted file mode 100644 index e39ff5290a..0000000000 --- a/pxr/imaging/lib/glfq/moduleDeps.cpp +++ /dev/null @@ -1,52 +0,0 @@ -// -// 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. -// -//////////////////////////////////////////////////////////////////////// -// This file is generated by the makeScriptModuleLoader script. Do not -// edit directly. - -#include "pxr/base/tf/registryManager.h" -#include "pxr/base/tf/scriptModuleLoader.h" -#include "pxr/base/tf/token.h" - -#include - -TF_REGISTRY_FUNCTION(TfScriptModuleLoader) { - std::vector reqs; - reqs.reserve(12); - reqs.push_back(TfToken("ar")); - reqs.push_back(TfToken("arch")); - reqs.push_back(TfToken("garch")); - reqs.push_back(TfToken("gf")); - reqs.push_back(TfToken("glf")); - reqs.push_back(TfToken("js")); - reqs.push_back(TfToken("plug")); - reqs.push_back(TfToken("sdf")); - reqs.push_back(TfToken("tf")); - reqs.push_back(TfToken("tracelite")); - reqs.push_back(TfToken("vt")); - reqs.push_back(TfToken("work")); - TfScriptModuleLoader::GetInstance(). - RegisterLibrary(TfToken("glfq"), TfToken("pxr.Glfq"), reqs); -} - diff --git a/pxr/imaging/lib/glfq/overview.dox b/pxr/imaging/lib/glfq/overview.dox deleted file mode 100644 index 7c800fd649..0000000000 --- a/pxr/imaging/lib/glfq/overview.dox +++ /dev/null @@ -1,61 +0,0 @@ -/*! -\mainpage - -Provides a QGLContext specialized to support OpenGL debug output. - -OpenGL debug output can provide more detailed diagnostic information -than is otherwise available to OpenGL applications. - -The classes in this module make it easy to enable OpenGL debug output -in Qt applications by simply creating a custom QGLContext when initializing -a QGLWidget subclass. - -For convenience, the glf module provides a way to register a default -debug output message callback function, but it is also possible to use -the GL debug output API directly. - -Once your code has been modified to use this facility, you can enable -or disable the creation of a debug context by setting the env var -\p GLF_ENABLE_DEBUG_OUTPUT to true or false respectively. - -C++ Example: -\code -class MyQGLWidget : public QGLWidget { -public: - MyQGLWidget(const QGLFormat & format, QWidget * parent = NULL) - : QGLWidget(new GlfQGLDebugContext(format), parent) {} - -protected: - virtual void initializeGL() { - GlfGlewInit(); - GlfRegisterDefaultDebugOutputMessageCallback(); - // other initialization code - } - - virtual void paintGL() { - glClearColor(0.1, 0.1, 0.1, 1.0); - glClear(GL.GL_COLOR_BUFFER_BIT); - // other drawing code - } -}; -\endcode - -Python Example: -\code -class MyQGLWidget(QtOpenGL.QGLWidget): - def __init__(self, glFormat, parent=None): - super(MyQGLWidget, self).__init__(GlfQ.CreateGLDebugContext(glFormat), parent) - - def initializeGL(self): - Glf.GlewInit() - Glf.RegisterDefaultDebugOutputMessageCallback() - # other initialization code - - def paintGL(self): - GL.glClearColor(0.1, 0.1, 0.1, 1.0) - GL.glClear(GL.GL_COLOR_BUFFER_BIT) - # other drawing code - -\endcode - -*/ diff --git a/pxr/usdImaging/lib/usdviewq/stageView.py b/pxr/usdImaging/lib/usdviewq/stageView.py index 30b82b47c0..85185edeaa 100644 --- a/pxr/usdImaging/lib/usdviewq/stageView.py +++ b/pxr/usdImaging/lib/usdviewq/stageView.py @@ -34,7 +34,6 @@ from pxr import Tf from pxr import Gf from pxr import Glf -from pxr import Glfq from pxr import Sdf, Usd, UsdGeom, UsdUtils from pxr import UsdImagingGL from pxr import CameraUtil @@ -768,8 +767,7 @@ def __init__(self, parent=None, bboxCache=None, xformCache=None): if msaa == "1": glFormat.setSampleBuffers(True) glFormat.setSamples(4) - super(StageView, self).__init__( - Glfq.CreateGLDebugContext(glFormat), parent) + super(StageView, self).__init__(glFormat, parent) self._freeCamera = FreeCamera(True) self._lastComputedGfCamera = None From a42d6bb57bd3bc3c74256ac7b381811ce0236587 Mon Sep 17 00:00:00 2001 From: poljere Date: Mon, 17 Oct 2016 16:12:52 -0700 Subject: [PATCH 269/380] Providing better error detection in cases where we try to get a texture that has not been correctly inserted. Also, this change makes it so hd/surfaceshader does not insert textures in the registry, this is only done by hd/texture. [Hd] Surface shader now does not insert textures in the registry, it only checks if they are there. There is also better error handling for missing textures in SurfaceShaders. In order to support this changes it has been added a functionality in the instanceRegistry to check if an instance is there or not without registering it. (Internal change: 1665282) --- pxr/imaging/lib/hd/instanceRegistry.h | 28 +++++++++++++++++++++++++ pxr/imaging/lib/hd/resourceRegistry.cpp | 9 ++++++++ pxr/imaging/lib/hd/resourceRegistry.h | 5 +++++ pxr/imaging/lib/hd/surfaceShader.cpp | 18 +++++++++------- 4 files changed, 53 insertions(+), 7 deletions(-) diff --git a/pxr/imaging/lib/hd/instanceRegistry.h b/pxr/imaging/lib/hd/instanceRegistry.h index ff700aa5ce..c158310dc4 100644 --- a/pxr/imaging/lib/hd/instanceRegistry.h +++ b/pxr/imaging/lib/hd/instanceRegistry.h @@ -119,6 +119,11 @@ class HdInstanceRegistry { std::unique_lock GetInstance(typename INSTANCE::KeyType const &key, INSTANCE *instance); + /// Returns a shared instance for a given key as a pair of (key, value) + /// only if the key exists in the dictionary. + std::unique_lock FindInstance(typename INSTANCE::KeyType const &key, + INSTANCE *instance, bool *found); + /// Remove entries which has unreferenced key and returns the count of /// remaining entries. size_t GarbageCollect(); @@ -172,6 +177,29 @@ HdInstanceRegistry::GetInstance(typename INSTANCE::KeyType const &key, return lock; } +template +std::unique_lock +HdInstanceRegistry::FindInstance(typename INSTANCE::KeyType const &key, + INSTANCE *instance, bool *found) +{ + HD_TRACE_FUNCTION(); + HD_MALLOC_TAG_FUNCTION(); + + // Grab Registry lock + // (and don't release it in this function, return it instead) + std::unique_lock lock(_regLock); + + typename _Dictionary::iterator it = _dictionary.find(key); + if (it == _dictionary.end()) { + *found = false; + } else { + *found = true; + instance->Create(key, it->second, &_dictionary, false /*firstInstance*/); + } + + return lock; +} + template size_t HdInstanceRegistry::GarbageCollect() diff --git a/pxr/imaging/lib/hd/resourceRegistry.cpp b/pxr/imaging/lib/hd/resourceRegistry.cpp index f7947c3c72..ca45386636 100644 --- a/pxr/imaging/lib/hd/resourceRegistry.cpp +++ b/pxr/imaging/lib/hd/resourceRegistry.cpp @@ -740,6 +740,15 @@ HdResourceRegistry::RegisterTextureResource(HdTextureResource::ID id, return _textureResourceRegistry.GetInstance(id, instance); } +std::unique_lock +HdResourceRegistry::FindTextureResource(HdTextureResource::ID id, + HdInstance *instance, + bool *found) +{ + return _textureResourceRegistry.FindInstance(id, instance, found); +} + + std::ostream &operator <<(std::ostream &out, const HdResourceRegistry& self) { diff --git a/pxr/imaging/lib/hd/resourceRegistry.h b/pxr/imaging/lib/hd/resourceRegistry.h index 5d005a08c7..01b6b39710 100644 --- a/pxr/imaging/lib/hd/resourceRegistry.h +++ b/pxr/imaging/lib/hd/resourceRegistry.h @@ -215,6 +215,11 @@ class HdResourceRegistry : public boost::noncopyable { std::unique_lock RegisterTextureResource(HdTextureResource::ID id, HdInstance *pInstance); + /// Find a texture in the texture registry. If found, it returns it. + std::unique_lock FindTextureResource(HdTextureResource::ID id, + HdInstance *instance, + bool *found); + /// Register a buffer allocated with \a count * \a commandNumUints * /// sizeof(GLuint) to be used as an indirect dispatch buffer. HdDispatchBufferSharedPtr RegisterDispatchBuffer( diff --git a/pxr/imaging/lib/hd/surfaceShader.cpp b/pxr/imaging/lib/hd/surfaceShader.cpp index ecc4e52dbf..f5dc307070 100644 --- a/pxr/imaging/lib/hd/surfaceShader.cpp +++ b/pxr/imaging/lib/hd/surfaceShader.cpp @@ -146,18 +146,23 @@ HdSurfaceShader::Sync() HdTextureResourceSharedPtr texResource; { - HdInstance texInstance; + HdInstance + texInstance; + bool textureResourceFound = false; std::unique_lock regLock = - resourceRegistry->RegisterTextureResource(texID, &texInstance); - - if (not TF_VERIFY(not texInstance.IsFirstInstance(), "%s", - paramIt->GetConnection().GetText())) { + resourceRegistry->FindTextureResource + (texID, &texInstance, &textureResourceFound); + if (not TF_VERIFY(textureResourceFound, + "No texture resource found with path %s", + paramIt->GetConnection().GetText())) { continue; } texResource = texInstance.GetValue(); - if (not TF_VERIFY(texResource)) { + if (not TF_VERIFY(texResource, + "Incorrect texture resource with path %s", + paramIt->GetConnection().GetText())) { continue; } } @@ -194,7 +199,6 @@ HdSurfaceShader::Sync() tex.handle)); sources.push_back(source); } - } else { tex.type = TextureDescriptor::TEXTURE_2D; tex.handle = bindless ? texResource->GetTexelsTextureHandle() From 1f93ea761a19148a1804b4b95465065af3d7488a Mon Sep 17 00:00:00 2001 From: takahito-tejima Date: Mon, 17 Oct 2016 16:16:39 -0700 Subject: [PATCH 270/380] fix FindOpenSubdiv.cmake It's failing because currently OPENSUBDIV_VERSION = v3_1_0_RC2 and that is parsed as version 2. fixing to see the first 3 numbers only. Fixes #82 (Internal change: 1665286) --- cmake/modules/FindOpenSubdiv.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/modules/FindOpenSubdiv.cmake b/cmake/modules/FindOpenSubdiv.cmake index 71eb3913f7..ac9787240e 100644 --- a/cmake/modules/FindOpenSubdiv.cmake +++ b/cmake/modules/FindOpenSubdiv.cmake @@ -58,7 +58,7 @@ if(OPENSUBDIV_INCLUDE_DIR AND EXISTS "${OPENSUBDIV_INCLUDE_DIR}/opensubdiv/versi REGEX "#define OPENSUBDIV_VERSION v.*$" ) string(REGEX - MATCHALL "[0-9_]+$" + MATCHALL "[0-9]_[0-9]_[0-9]" OPENSUBDIV_VERSION ${TMP} ) From 7c16b2e7ca91a0b7fe967047183f2313987e6682 Mon Sep 17 00:00:00 2001 From: superfunc Date: Mon, 17 Oct 2016 16:16:51 -0700 Subject: [PATCH 271/380] [Usd] Don't allow users to write out composed results to original file. In the case of single layers, this seems restrictive, but in the general case, it protects users from overwriting a thin root layer with a composed stage. (Internal change: 1665421) --- pxr/usd/bin/usddiff/usddiff.py | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/pxr/usd/bin/usddiff/usddiff.py b/pxr/usd/bin/usddiff/usddiff.py index c7017ee980..140e1b6a4d 100644 --- a/pxr/usd/bin/usddiff/usddiff.py +++ b/pxr/usd/bin/usddiff/usddiff.py @@ -77,6 +77,16 @@ def _getFileFormat(path): def _convertTo(inPath, outPath, usdcatCmd, flatten=None, fmt=None): call(_generateCatCommand(usdcatCmd, inPath, outPath, flatten, fmt)) + +def _tryEdit(fileName, tempFileName, usdcatCmd, fileType, composed): + if composed: + sys.exit('Error: Cannot write out flattened result.') + + if not os.access(fileName, os.W_OK): + sys.exit('Error: Cannot write to %s, insufficient permissions' % fileName) + + _convertTo(tempFileName, fileName, usdcatCmd, flatten=None, fmt=fileType) + def main(): import argparse parser = argparse.ArgumentParser(prog=os.path.basename(sys.argv[0]), @@ -139,22 +149,14 @@ def main(): # If we intend to edit either of the files if not results.noeffect: - accessError = 'Error: Cannot write to %s, insufficient permissions' - if tempBaselineChanged: - if not os.access(results.baseline, os.W_OK): - sys.exit(accessError % results.baseline) - _convertTo(tempBaseline.name, results.baseline, - usdcatCmd, flatten=results.compose, - fmt=baselineFileType) + if tempBaselineChanged: + _tryEdit(results.baseline, tempBaseline.name, + usdcatCmd, baselineFileType, results.compose) if tempComparisonChanged: - if not os.access(results.comparison, os.W_OK): - sys.exit(accessError % results.comparison) - - _convertTo(tempComparison.name, results.comparison, - usdcatCmd, flatten=results.compose, - fmt=comparisonFileType) + _tryEdit(results.comparison, tempComparison.name, + usdcatCmd, comparisonFileType, results.compose) sys.exit(diffResult) From 62c94b882c3a548c1eefcedade8886f38d352bf4 Mon Sep 17 00:00:00 2001 From: superfunc Date: Mon, 17 Oct 2016 16:17:01 -0700 Subject: [PATCH 272/380] [Usdview] Clean up value portion of metadata field. Previously, it could contain redundant commas and spaces. A good example of this issue is in the documentation string of certain properties(eg. proxyPrim). (Internal change: 1665541) --- pxr/usdImaging/lib/usdviewq/mainWindow.py | 143 +++++++++++++++++++--- 1 file changed, 129 insertions(+), 14 deletions(-) diff --git a/pxr/usdImaging/lib/usdviewq/mainWindow.py b/pxr/usdImaging/lib/usdviewq/mainWindow.py index fc0dc35675..50825a2029 100644 --- a/pxr/usdImaging/lib/usdviewq/mainWindow.py +++ b/pxr/usdImaging/lib/usdviewq/mainWindow.py @@ -1457,7 +1457,6 @@ def _showNodeViewHelpDlg(self): self._nodeViewHelpDlg.show() - def _redrawOptionToggled(self, checked): self._settings.setAndSave(RedrawOnScrub=checked) self._ui.frameSlider.setTracking(checked) @@ -3119,6 +3118,124 @@ def _getSelectedObject(self, selectedAttribute=None): def _getSelectedPrim(self): return self._currentNodes[0] if self._currentNodes else None + def _findIndentPos(self, s): + for index, char in enumerate(s): + if char != ' ': + return index + + return len(s) - 1 + + def _maxToolTipWidth(self): + return 90 + + def _maxToolTipHeight(self): + return 32 + + def _trimWidth(self, s, isList=False): + # We special-case the display offset because list + # items will have tags embedded in them. + offset = 10 if isList else 5 + + if len(s) >= self._maxToolTipWidth(): + # For strings, well do special ellipsis behavior + # which displays the last 5 chars with an ellipsis + # in between. For other values, we simply display a + # trailing ellipsis to indicate more data. + if s[0] == '\'' and s[-1] == '\'': + return (s[:self._maxToolTipWidth() - offset] + + '...' + + s[len(s) - offset:]) + else: + return s[:self._maxToolTipWidth()] + '...' + return s + + def _limitToolTipSize(self, s, isList=False): + ttStr = '' + + lines = s.split('
') + for index, line in enumerate(lines): + if index+1 > self._maxToolTipHeight(): + break + ttStr += self._trimWidth(line, isList) + if not isList and index != len(lines)-1: + ttStr += '
' + + if (len(lines) > self._maxToolTipHeight()): + ellipsis = ' '*self._findIndentPos(line) + '...' + if isList: + ellipsis = '
  • ' + ellipsis + '
  • ' + else: + ellipsis += '
    ' + + ttStr += ellipsis + ttStr += self._trimWidth(lines[len(lines)-2], isList) + + return ttStr + + def _addRichTextIndicators(self, s): + # - We'll need to use html-style spaces to ensure they are respected + # in the toolTip which uses richtext formatting. + # - We wrap the tooltip as a paragraph to ensure   's are + # respected by Qt's rendering engine. + return '

    ' + s.replace(' ', ' ') + '

    ' + + def _limitValueDisplaySize(self, s): + maxValueChars = 300 + return s[:maxValueChars] + + def _cleanStr(self, s, repl): + from itertools import groupby + # Remove redundant char seqs and strip newlines. + replaced = str(s).replace('\n', repl) + filtered = [u for (u, _) in groupby(replaced.split())] + return ' '.join(filtered) + + def _formatMetadataValueView(self, val): + from pprint import pformat, pprint + + valStr = self._cleanStr(val, ' ') + ttStr = '' + isList = False + + # For iterable things, like VtArrays and lists, we want to print + # a nice numbered list. + if isinstance(val, list) or getattr(val, "_isVtArray", False): + isList = True + + # We manually supply the index for our list elements + # because Qt's richtext processor starts the
      numbering at 1. + for index, value in enumerate(val): + last = len(val) - 1 + trimmed = self._cleanStr(value, ' ') + ttStr += ("
    1. " + str(index) + ": " + trimmed + "

    2. ") + + elif isinstance(val, dict): + # We stringify all dict elements so they display more nicely. + # For example, by default, the pprint operation would print a + # Vt Array as Vt.Array(N, (E1, ....). By running it through + # str(..). we'd get [(E1, E2), ....] which is more useful to + # the end user trying to examine their data. + for k, v in val.items(): + val[k] = str(v) + + # We'll need to strip the quotes generated by the str' operation above + stripQuotes = lambda s: s.replace('\'', '').replace('\"', "") + + valStr = stripQuotes(self._cleanStr(val, ' ')) + + formattedDict = pformat(val) + formattedDictLines = formattedDict.split('\n') + for index, line in enumerate(formattedDictLines): + ttStr += (stripQuotes(line) + + ('' if index == len(formattedDictLines) - 1 else '
      ')) + else: + ttStr = self._cleanStr(val, '
      ') + + valStr = self._limitValueDisplaySize(valStr) + ttStr = self._addRichTextIndicators( + self._limitToolTipSize(ttStr, isList)) + return valStr, ttStr + def _updateMetadataView(self, obj=None): """ Sets the contents of the metadata viewer""" @@ -3199,14 +3316,8 @@ def _updateMetadataView(self, obj=None): else: val = m[key] - # format the tooltip more legibly for things that are really - # lists. WBN to use this in the table itself, but that requires - # deeper Qt-fu - valStr = str(val).replace('\n', ', ') - ttStr = valStr - if isinstance(val, list): - ttStr = "\n".join(str(v) for v in val) - attrVal = QtGui.QTableWidgetItem(valStr[:500]) + valStr, ttStr = self._formatMetadataValueView(val) + attrVal = QtGui.QTableWidgetItem(valStr) attrVal.setToolTip(ttStr) tableWidget.setItem(i, 1, attrVal) @@ -3254,12 +3365,14 @@ def _updateLayerStackView(self, obj=None): layerItem.layerPath = layer.layer.realPath toolTip = "identifier: @%s@
      resolved path: %s" % \ (layer.layer.identifier, layerItem.layerPath) + toolTip = self._limitToolTipSize(toolTip) layerItem.setToolTip(toolTip) tableWidget.setItem(i, 0, layerItem) offsetItem = QtGui.QTableWidgetItem(layer.GetOffsetString()) offsetItem.layerPath = layer.layer.realPath - offsetItem.setToolTip(str(layer.offset)) + toolTip = self._limitToolTipSize(str(layer.offset)) + offsetItem.setToolTip(toolTip) tableWidget.setItem(i, 1, offsetItem) tableWidget.resizeColumnToContents(0) @@ -3290,24 +3403,26 @@ def _updateLayerStackView(self, obj=None): for i, spec in enumerate(specs): layerItem = QtGui.QTableWidgetItem(spec.layer.GetDisplayName()) - layerItem.setToolTip(spec.layer.realPath) + layerItem.setToolTip(self._limitToolTipSize(spec.layer.realPath)) tableWidget.setItem(i, 0, layerItem) pathItem = QtGui.QTableWidgetItem(spec.path.pathString) - pathItem.setToolTip(spec.path.pathString) + pathItem.setToolTip(self._limitToolTipSize(spec.path.pathString)) tableWidget.setItem(i, 1, pathItem) if path.IsPropertyPath(): valStr = _GetShortString(spec, self._currentFrame) + ttStr = valStr else: metadataKeys = spec.GetMetaDataInfoKeys() metadataDict = {} for mykey in metadataKeys: if spec.HasInfo(mykey): metadataDict[mykey] = spec.GetInfo(mykey) - valStr = str(metadataDict) + valStr, ttStr = self._formatMetadataValueView(metadataDict) + valueItem = QtGui.QTableWidgetItem(valStr) - valueItem.setToolTip(valStr) + valueItem.setToolTip(ttStr) tableWidget.setItem(i, 2, valueItem) # Add the data the context menu needs for j in range(3): From 1c98c4678dd0de548d473503bb217ef0558b2305 Mon Sep 17 00:00:00 2001 From: poljere Date: Mon, 17 Oct 2016 16:17:08 -0700 Subject: [PATCH 273/380] Refactor hd/texture so we first check the bits and we only do operations (create textures...) if they are needed [Hd] First check if we need to do anything before we do any operation on the texture (Internal change: 1665615) --- pxr/imaging/lib/hd/texture.cpp | 88 +++++++++++++++++----------------- 1 file changed, 45 insertions(+), 43 deletions(-) diff --git a/pxr/imaging/lib/hd/texture.cpp b/pxr/imaging/lib/hd/texture.cpp index 336d798889..eabecc9ea7 100644 --- a/pxr/imaging/lib/hd/texture.cpp +++ b/pxr/imaging/lib/hd/texture.cpp @@ -50,58 +50,60 @@ HdTexture::Sync() SdfPath const& id = GetID(); HdSceneDelegate* delegate = GetDelegate(); - HdResourceRegistry *resourceRegistry = &HdResourceRegistry::GetInstance(); HdChangeTracker& changeTracker = delegate->GetRenderIndex().GetChangeTracker(); HdChangeTracker::DirtyBits bits = changeTracker.GetTextureDirtyBits(id); - HdTextureResource::ID texID = delegate->GetTextureResourceID(id); - { - HdInstance texInstance; + // XXX : DirtyParams and DirtyTexture are currently the same but they + // can be separated functionally and have different + // delegate methods. + if (bits & HdChangeTracker::DirtyParams or + bits & HdChangeTracker::DirtyTexture) { - std::unique_lock regLock = - resourceRegistry->RegisterTextureResource(texID, &texInstance); + HdResourceRegistry *resourceRegistry = + &HdResourceRegistry::GetInstance(); + HdTextureResource::ID texID = delegate->GetTextureResourceID(id); + { + HdInstance + texInstance; - // XXX : DirtyParams and DirtyTexture are currently the same but they - // can be separated functionally and have different - // delegate methods. - if (texInstance.IsFirstInstance() or - bits & HdChangeTracker::DirtyParams or - bits & HdChangeTracker::DirtyTexture) { + std::unique_lock regLock = + resourceRegistry->RegisterTextureResource(texID, &texInstance); - HdTextureResourceSharedPtr texResource; - if (texID == HdTextureResource::ComputeFallbackUVHash()) { - GlfUVTextureStorageRefPtr texPtr = - GlfUVTextureStorage::New(1,1,VtValue(GfVec3d(0.0, 0.0, 0.0))); - GlfTextureHandleRefPtr texture = - GlfTextureRegistry::GetInstance().GetTextureHandle(texPtr); - texture->AddMemoryRequest(0); - texResource = HdTextureResourceSharedPtr( - new HdSimpleTextureResource(texture, false)); - } else if (texID == HdTextureResource::ComputeFallbackPtexHash()) { - texResource = - delegate->GetTextureResource(id); - // Hacky Ptex Fallback Implementation (nonfunctional) - // For future reference - /*if (texResource->GetTexelsTextureId() == 0) { - // fail to load a texture. use fallback default - if (texResource->IsPtex()) { - const size_t defaultPtexId = 0x48510398a84ebf94; - HdInstance - defaultTexInstance = resourceRegistry->RegisterTextureResource(defaultPtexId); - if (defaultTexInstance.IsFirstInstance()) { - HdTextureResourceSharedPtr defaultTexResource(new Hd_DefaultPtexTextureResource()); - defaultTexInstance.SetValue(defaultTexResource); + if (texInstance.IsFirstInstance()) { + HdTextureResourceSharedPtr texResource; + if (texID == HdTextureResource::ComputeFallbackUVHash()) { + GlfUVTextureStorageRefPtr texPtr = + GlfUVTextureStorage::New(1,1,VtValue(GfVec3d(0.0, 0.0, 0.0))); + GlfTextureHandleRefPtr texture = + GlfTextureRegistry::GetInstance().GetTextureHandle(texPtr); + texture->AddMemoryRequest(0); + texResource = HdTextureResourceSharedPtr( + new HdSimpleTextureResource(texture, false)); + } else if (texID == HdTextureResource::ComputeFallbackPtexHash()) { + texResource = delegate->GetTextureResource(id); + // Hacky Ptex Fallback Implementation (nonfunctional) + // For future reference + /*if (texResource->GetTexelsTextureId() == 0) { + // fail to load a texture. use fallback default + if (texResource->IsPtex()) { + const size_t defaultPtexId = 0x48510398a84ebf94; + HdInstance + defaultTexInstance = resourceRegistry->RegisterTextureResource(defaultPtexId); + if (defaultTexInstance.IsFirstInstance()) { + HdTextureResourceSharedPtr defaultTexResource(new Hd_DefaultPtexTextureResource()); + defaultTexInstance.SetValue(defaultTexResource); + } + texResource = defaultTexInstance.GetValue(); } - texResource = defaultTexInstance.GetValue(); - } - }*/ - } else { - texResource = - delegate->GetTextureResource(id); - } + }*/ + } else { + texResource = + delegate->GetTextureResource(id); + } - texInstance.SetValue(texResource); + texInstance.SetValue(texResource); + } } } } From f501b664db3804a78051356ef28d87d0ffb6ea87 Mon Sep 17 00:00:00 2001 From: unhyperbolic Date: Mon, 17 Oct 2016 16:17:19 -0700 Subject: [PATCH 274/380] Remove enableDrawTarget flag from HdxDrawTargetTask and update debugging output. (Internal change: 1665639) --- pxr/imaging/lib/hdx/drawTargetTask.cpp | 50 ++++++++++++++++-------- pxr/imaging/lib/hdx/drawTargetTask.h | 6 +-- pxr/imaging/lib/hdx/unitTestDelegate.cpp | 1 - 3 files changed, 35 insertions(+), 22 deletions(-) diff --git a/pxr/imaging/lib/hdx/drawTargetTask.cpp b/pxr/imaging/lib/hdx/drawTargetTask.cpp index 5d4195172e..452d505f82 100644 --- a/pxr/imaging/lib/hdx/drawTargetTask.cpp +++ b/pxr/imaging/lib/hdx/drawTargetTask.cpp @@ -39,7 +39,6 @@ HdxDrawTargetTask::HdxDrawTargetTask(HdSceneDelegate* delegate, SdfPath const& id) : HdSceneTask(delegate, id) - , _enableDrawTargets(false) , _currentDrawTargetSetVersion(0) , _renderPasses() , _depthBiasUseDefault(true) @@ -68,8 +67,6 @@ HdxDrawTargetTask::_Sync(HdTaskContext* ctx) return; } - _enableDrawTargets = params.enableDrawTargets; - // Raster State // XXX: Update master raster state that is used by all passes? _wireframeColor = params.wireframeColor; @@ -96,10 +93,6 @@ HdxDrawTargetTask::_Sync(HdTaskContext* ctx) _surfaceVisibility = params.surfaceVisibility; } - if (not _enableDrawTargets) { - return; - } - HdSceneDelegate* delegate = GetDelegate(); HdRenderIndex &renderIndex = delegate->GetRenderIndex(); HdChangeTracker& changeTracker = renderIndex.GetChangeTracker(); @@ -255,12 +248,6 @@ HdxDrawTargetTask::_Execute(HdTaskContext* ctx) HD_TRACE_FUNCTION(); HD_MALLOC_TAG_FUNCTION(); - // When the draw targets are not enabled we don't need to do any - // draw target computation - if (not _enableDrawTargets) { - return; - } - // Apply polygon offset to whole pass. // XXX TODO: Move to an appropriate home glPushAttrib(GL_POLYGON_BIT | GL_DEPTH_BUFFER_BIT); @@ -333,15 +320,46 @@ HdxDrawTargetTask::_Execute(HdTaskContext* ctx) std::ostream& operator<<(std::ostream& out, const HdxDrawTargetTaskParams& pv) { - out << "GlimRG Draw Target Task Params: (...) " - << pv.enableDrawTargets; + out << "HdxDrawTargetTaskParams: (...) \n" + << " overrideColor = " << pv.overrideColor << "\n" + << " wireframeColor = " << pv.wireframeColor << "\n" + << " enableLighting = " << pv.enableLighting << "\n" + << " alphaThreshold = " << pv.alphaThreshold << "\n" + << " tessLevel = " << pv.tessLevel << "\n" + << " drawingRange = " << pv.drawingRange << "\n" + << " depthBiasUseDefault = " << pv.depthBiasUseDefault << "\n" + << " depthBiasEnable = " << pv.depthBiasEnable << "\n" + << " depthBiasConstantFactor = " << pv.depthBiasConstantFactor << "\n" + << " depthFunc = " << pv.depthFunc << "\n" + << " cullStyle = " << pv.cullStyle << "\n" + << " geomStyle = " << pv.geomStyle << "\n" + << " complexity = " << pv.complexity << "\n" + << " hullVisibility = " << pv.hullVisibility << "\n" + << " surfaceVisibility = " << pv.surfaceVisibility << "\n" + ; return out; } bool operator==(const HdxDrawTargetTaskParams& lhs, const HdxDrawTargetTaskParams& rhs) { - return (lhs.enableDrawTargets == rhs.enableDrawTargets); + return + lhs.overrideColor == rhs.overrideColor and + lhs.wireframeColor == rhs.wireframeColor and + lhs.enableLighting == rhs.enableLighting and + lhs.alphaThreshold == rhs.alphaThreshold and + lhs.tessLevel == rhs.tessLevel and + lhs.drawingRange == rhs.drawingRange and + lhs.depthBiasUseDefault == rhs.depthBiasUseDefault and + lhs.depthBiasEnable == rhs.depthBiasEnable and + lhs.depthBiasConstantFactor == rhs.depthBiasConstantFactor and + lhs.depthBiasSlopeFactor == rhs.depthBiasSlopeFactor and + lhs.depthFunc == rhs.depthFunc and + lhs.cullStyle == rhs.cullStyle and + lhs.geomStyle == rhs.geomStyle and + lhs.complexity == rhs.complexity and + lhs.hullVisibility == rhs.hullVisibility and + lhs.surfaceVisibility == rhs.surfaceVisibility; } bool operator!=(const HdxDrawTargetTaskParams& lhs, const HdxDrawTargetTaskParams& rhs) diff --git a/pxr/imaging/lib/hdx/drawTargetTask.h b/pxr/imaging/lib/hdx/drawTargetTask.h index c7992cb54a..8c73cc8330 100644 --- a/pxr/imaging/lib/hdx/drawTargetTask.h +++ b/pxr/imaging/lib/hdx/drawTargetTask.h @@ -62,7 +62,6 @@ class HdxDrawTargetTask : public HdSceneTask { HdxDrawTargetWeakPtr target; unsigned int version; }; - bool _enableDrawTargets; unsigned _currentDrawTargetSetVersion; @@ -106,8 +105,7 @@ class HdxDrawTargetTask : public HdSceneTask { struct HdxDrawTargetTaskParams { HdxDrawTargetTaskParams() - : enableDrawTargets(false) - , overrideColor(0.0) + : overrideColor(0.0) , wireframeColor(0.0) , enableLighting(false) , alphaThreshold(0.0) @@ -125,8 +123,6 @@ struct HdxDrawTargetTaskParams , surfaceVisibility(true) {} - bool enableDrawTargets; - // ClipPlanesVector clipPlanes; GfVec4f overrideColor; GfVec4f wireframeColor; diff --git a/pxr/imaging/lib/hdx/unitTestDelegate.cpp b/pxr/imaging/lib/hdx/unitTestDelegate.cpp index e65e9f7a15..3a15d70fa8 100644 --- a/pxr/imaging/lib/hdx/unitTestDelegate.cpp +++ b/pxr/imaging/lib/hdx/unitTestDelegate.cpp @@ -380,7 +380,6 @@ Hdx_UnitTestDelegate::AddDrawTargetTask(SdfPath const &id) cache[HdTokens->children] = VtValue(SdfPathVector()); HdxDrawTargetTaskParams params; - params.enableDrawTargets = true; params.enableLighting = true; cache[HdTokens->params] = params; From c3da5f75a93071afe765a2e8550ee9bac68e5821 Mon Sep 17 00:00:00 2001 From: George ElKoura Date: Mon, 24 Oct 2016 22:56:27 -0700 Subject: [PATCH 275/380] Fixed an incorrect merge. --- pxr/usdImaging/lib/usdImagingGL/hdEngine.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pxr/usdImaging/lib/usdImagingGL/hdEngine.h b/pxr/usdImaging/lib/usdImagingGL/hdEngine.h index 89c9b580f1..b7e47dc676 100644 --- a/pxr/usdImaging/lib/usdImagingGL/hdEngine.h +++ b/pxr/usdImaging/lib/usdImagingGL/hdEngine.h @@ -62,7 +62,7 @@ class UsdImagingGLHdEngine : public UsdImagingGLEngine UsdImagingGLHdEngineSharedPtr()); USDIMAGINGGL_API - virtual ~UsdImagingHdEngine(); + virtual ~UsdImagingGLHdEngine(); USDIMAGINGGL_API HdRenderIndexSharedPtr GetRenderIndex() const; From f71bc50f8b97c6b35a2d87efe09faab5063cc8b4 Mon Sep 17 00:00:00 2001 From: George ElKoura Date: Mon, 24 Oct 2016 23:09:21 -0700 Subject: [PATCH 276/380] Adding symbol visibility to adapter code in usdImaging now that we need it exported for usdImagingGL. --- pxr/usdImaging/lib/usdImaging/capsuleAdapter.h | 4 ++++ pxr/usdImaging/lib/usdImaging/coneAdapter.h | 4 ++++ pxr/usdImaging/lib/usdImaging/cubeAdapter.h | 5 +++++ pxr/usdImaging/lib/usdImaging/cylinderAdapter.h | 4 ++++ pxr/usdImaging/lib/usdImaging/gprimAdapter.h | 3 +++ pxr/usdImaging/lib/usdImaging/nurbsPatchAdapter.h | 4 ++++ pxr/usdImaging/lib/usdImaging/sphereAdapter.h | 5 +++++ 7 files changed, 29 insertions(+) diff --git a/pxr/usdImaging/lib/usdImaging/capsuleAdapter.h b/pxr/usdImaging/lib/usdImaging/capsuleAdapter.h index 802d272888..0ebd4bd5ba 100644 --- a/pxr/usdImaging/lib/usdImaging/capsuleAdapter.h +++ b/pxr/usdImaging/lib/usdImaging/capsuleAdapter.h @@ -24,6 +24,8 @@ #ifndef USDIMAGING_CAPSULE_ADAPTER_H #define USDIMAGING_CAPSULE_ADAPTER_H +#include "pxr/usdImaging/usdImaging/api.h" + #include "pxr/usdImaging/usdImaging/gprimAdapter.h" class UsdGeomCapsule; @@ -79,9 +81,11 @@ class UsdImagingCapsuleAdapter : public UsdImagingGprimAdapter { UsdImagingInstancerContext const* instancerContext = NULL); + USDIMAGING_API static VtValue GetMeshPoints(UsdPrim const& prim, UsdTimeCode time); + USDIMAGING_API static VtValue GetMeshTopology(); }; diff --git a/pxr/usdImaging/lib/usdImaging/coneAdapter.h b/pxr/usdImaging/lib/usdImaging/coneAdapter.h index a3552c037c..cc62564124 100644 --- a/pxr/usdImaging/lib/usdImaging/coneAdapter.h +++ b/pxr/usdImaging/lib/usdImaging/coneAdapter.h @@ -24,6 +24,8 @@ #ifndef USDIMAGING_CONE_ADAPTER_H #define USDIMAGING_CONE_ADAPTER_H +#include "pxr/usdImaging/usdImaging/api.h" + #include "pxr/usdImaging/usdImaging/gprimAdapter.h" class UsdGeomCone; @@ -79,9 +81,11 @@ class UsdImagingConeAdapter : public UsdImagingGprimAdapter { UsdImagingInstancerContext const* instancerContext = NULL); + USDIMAGING_API static VtValue GetMeshPoints(UsdPrim const& prim, UsdTimeCode time); + USDIMAGING_API static VtValue GetMeshTopology(); }; diff --git a/pxr/usdImaging/lib/usdImaging/cubeAdapter.h b/pxr/usdImaging/lib/usdImaging/cubeAdapter.h index 40b312ff97..657d55605b 100644 --- a/pxr/usdImaging/lib/usdImaging/cubeAdapter.h +++ b/pxr/usdImaging/lib/usdImaging/cubeAdapter.h @@ -24,6 +24,8 @@ #ifndef USDIMAGING_CUBE_ADAPTER_H #define USDIMAGING_CUBE_ADAPTER_H +#include "pxr/usdImaging/usdImaging/api.h" + #include "pxr/usdImaging/usdImaging/primAdapter.h" #include "pxr/usdImaging/usdImaging/gprimAdapter.h" @@ -80,11 +82,14 @@ class UsdImagingCubeAdapter : public UsdImagingGprimAdapter { UsdImagingInstancerContext const* instancerContext = NULL); + USDIMAGING_API static VtValue GetMeshPoints(UsdPrim const& prim, UsdTimeCode time); + USDIMAGING_API static VtValue GetMeshTopology(); + USDIMAGING_API static GfMatrix4d GetMeshTransform(UsdPrim const& prim, UsdTimeCode time); }; diff --git a/pxr/usdImaging/lib/usdImaging/cylinderAdapter.h b/pxr/usdImaging/lib/usdImaging/cylinderAdapter.h index 462c888318..77fe7987d0 100644 --- a/pxr/usdImaging/lib/usdImaging/cylinderAdapter.h +++ b/pxr/usdImaging/lib/usdImaging/cylinderAdapter.h @@ -24,6 +24,8 @@ #ifndef USDIMAGING_CYLINDER_ADAPTER_H #define USDIMAGING_CYLINDER_ADAPTER_H +#include "pxr/usdImaging/usdImaging/api.h" + #include "pxr/usdImaging/usdImaging/gprimAdapter.h" class UsdGeomCylinder; @@ -79,9 +81,11 @@ class UsdImagingCylinderAdapter : public UsdImagingGprimAdapter { UsdImagingInstancerContext const* instancerContext = NULL); + USDIMAGING_API static VtValue GetMeshPoints(UsdPrim const& prim, UsdTimeCode time); + USDIMAGING_API static VtValue GetMeshTopology(); }; diff --git a/pxr/usdImaging/lib/usdImaging/gprimAdapter.h b/pxr/usdImaging/lib/usdImaging/gprimAdapter.h index 854e8e16d3..f936974570 100644 --- a/pxr/usdImaging/lib/usdImaging/gprimAdapter.h +++ b/pxr/usdImaging/lib/usdImaging/gprimAdapter.h @@ -24,6 +24,8 @@ #ifndef USDIMAGING_GPRIM_ADAPTER_H #define USDIMAGING_GPRIM_ADAPTER_H +#include "pxr/usdImaging/usdImaging/api.h" + #include "pxr/usdImaging/usdImaging/primAdapter.h" #include "pxr/usd/usdGeom/xformCache.h" @@ -92,6 +94,7 @@ class UsdImagingGprimAdapter : public UsdImagingPrimAdapter { /// Returns the color and opacity for a given prim, taking into account /// surface shader colors and explicitly authored color on the prim. + USDIMAGING_API static VtValue GetColorAndOpacity(UsdPrim const& prim, UsdImagingValueCache::PrimvarInfo* primvarInfo, UsdTimeCode time); diff --git a/pxr/usdImaging/lib/usdImaging/nurbsPatchAdapter.h b/pxr/usdImaging/lib/usdImaging/nurbsPatchAdapter.h index 1d0ef46f5a..c2786f8840 100644 --- a/pxr/usdImaging/lib/usdImaging/nurbsPatchAdapter.h +++ b/pxr/usdImaging/lib/usdImaging/nurbsPatchAdapter.h @@ -24,6 +24,8 @@ #ifndef USDIMAGING_NURBS_PATCH_ADAPTER_H #define USDIMAGING_NURBS_PATCH_ADAPTER_H +#include "pxr/usdImaging/usdImaging/api.h" + #include "pxr/usdImaging/usdImaging/primAdapter.h" #include "pxr/usdImaging/usdImaging/gprimAdapter.h" @@ -78,9 +80,11 @@ class UsdImagingNurbsPatchAdapter : public UsdImagingGprimAdapter { UsdImagingInstancerContext const* instancerContext = NULL); + USDIMAGING_API static VtValue GetMeshPoints(UsdPrim const& prim, UsdTimeCode time); + USDIMAGING_API static VtValue GetMeshTopology(UsdPrim const& prim, UsdTimeCode time); }; diff --git a/pxr/usdImaging/lib/usdImaging/sphereAdapter.h b/pxr/usdImaging/lib/usdImaging/sphereAdapter.h index 2d5cfb5cc1..9af75f2fcd 100644 --- a/pxr/usdImaging/lib/usdImaging/sphereAdapter.h +++ b/pxr/usdImaging/lib/usdImaging/sphereAdapter.h @@ -24,6 +24,8 @@ #ifndef USDIMAGING_SPHERE_ADAPTER_H #define USDIMAGING_SPHERE_ADAPTER_H +#include "pxr/usdImaging/usdImaging/api.h" + #include "pxr/usdImaging/usdImaging/primAdapter.h" #include "pxr/usdImaging/usdImaging/gprimAdapter.h" @@ -80,11 +82,14 @@ class UsdImagingSphereAdapter : public UsdImagingGprimAdapter { UsdImagingInstancerContext const* instancerContext = NULL); + USDIMAGING_API static VtValue GetMeshPoints(UsdPrim const& prim, UsdTimeCode time); + USDIMAGING_API static VtValue GetMeshTopology(); + USDIMAGING_API static GfMatrix4d GetMeshTransform(UsdPrim const& prim, UsdTimeCode time); }; From 7895312c2a68c229e3e9948b5db747061c119e53 Mon Sep 17 00:00:00 2001 From: MWDD Date: Tue, 25 Oct 2016 13:44:36 -0700 Subject: [PATCH 277/380] Partial Hydra Support for Reloading Shader Programs. This change provides Hydra support for reloading shader programs for Surface and Geometry shaders. It doesn't currently support Lighting, Render Pass and Culling shaders. The engine marks all prims as dirty to trigger an re-evaluation of the shader state, marks all surface shaders as dirty to cause those prims to be synced. It also removes all the geometric shader instances from the GeometricShaderRegistry. Finally it causes the Fallback surface shader to be reloaded. Reloading Renderpass shader is now partially supported as we will correctly compile and re-link the shader if the contents of the file changes, but I'm not currently reloading the glslfxFile. Changes: - Added ReloadAllShaders that dirties state so it gets reevaluated and removes cache entries from the resource registry. - Added ability to remove all entries from the HdInstanceRegistry. - The Render Index can now reload the fallback surface shader, but creating an new one and swapping it with the old one. - Renderpass shader now uses the hash of the contents of the file rather than a hash of the filename. (Internal change: 1665781) --- pxr/imaging/lib/hd/changeTracker.cpp | 31 +++++++++++++++++++++++++ pxr/imaging/lib/hd/changeTracker.h | 10 +++++++- pxr/imaging/lib/hd/engine.cpp | 26 +++++++++++++++++++++ pxr/imaging/lib/hd/engine.h | 4 ++++ pxr/imaging/lib/hd/instanceRegistry.h | 12 ++++++++++ pxr/imaging/lib/hd/renderIndex.cpp | 15 ++++++++---- pxr/imaging/lib/hd/renderIndex.h | 2 ++ pxr/imaging/lib/hd/renderPassShader.cpp | 2 +- pxr/imaging/lib/hd/resourceRegistry.cpp | 5 ++++ pxr/imaging/lib/hd/resourceRegistry.h | 2 ++ 10 files changed, 103 insertions(+), 6 deletions(-) diff --git a/pxr/imaging/lib/hd/changeTracker.cpp b/pxr/imaging/lib/hd/changeTracker.cpp index d02fb78294..87f2e50413 100644 --- a/pxr/imaging/lib/hd/changeTracker.cpp +++ b/pxr/imaging/lib/hd/changeTracker.cpp @@ -246,6 +246,16 @@ HdChangeTracker::MarkShaderClean(SdfPath const& id, DirtyBits newBits) it->second = (it->second & Varying) | newBits; } +void HdChangeTracker::MarkAllShadersDirty(DirtyBits bits) +{ + HD_TRACE_FUNCTION(); + + for (_IDStateMap::iterator it = _shaderState.begin(); + it != _shaderState.end(); ++it) { + it->second |= bits; + } +} + // -------------------------------------------------------------------------- // /// \name Task Object Tracking // -------------------------------------------------------------------------- // @@ -655,6 +665,27 @@ HdChangeTracker::MarkPrimVarDirty(SdfPath const& id, TfToken const& name) MarkRprimDirty(id, flag); } + +void +HdChangeTracker::MarkAllRprimsDirty(DirtyBits bits) +{ + HD_TRACE_FUNCTION(); + + bits = _PropagateDirtyBits(bits); + + for (_IDStateMap::iterator it = _rprimState.begin(); + it != _rprimState.end(); ++it) { + it->second |= bits; + } + + ++_changeCount; + + if (bits & DirtyVisibility) { + ++_visChangeCount; + } +} + + /*static*/ void HdChangeTracker::MarkPrimVarDirty(DirtyBits *dirtyBits, TfToken const &name) diff --git a/pxr/imaging/lib/hd/changeTracker.h b/pxr/imaging/lib/hd/changeTracker.h index 2837066cf7..651278ebc9 100644 --- a/pxr/imaging/lib/hd/changeTracker.h +++ b/pxr/imaging/lib/hd/changeTracker.h @@ -126,7 +126,12 @@ class HdChangeTracker : public boost::noncopyable { /// Mark the primvar for the rprim with \p id as being dirty. void MarkPrimVarDirty(SdfPath const& id, TfToken const& name); - /// Clear Varying bit of all prims. + /// Flag all the Rprim with the given \p id as being dirty. Multiple calls + /// with different dirty bits accumulate. + /// Doesn't touch varying state. + void MarkAllRprimsDirty(DirtyBits bits); + + // Clear Varying bit of all prims. /// /// The idea is that from frame to frame (update iteration), the set of /// dirty rprims and their dirty bits do not change; that is, the same @@ -275,6 +280,9 @@ class HdChangeTracker : public boost::noncopyable { /// Set the dirty flags to \p newBits. void MarkShaderClean(SdfPath const& id, DirtyBits newBits=Clean); + /// Sets all shaders to the given dirty \p bits + void MarkAllShadersDirty(DirtyBits bits); + // ---------------------------------------------------------------------- // /// @} /// \name Task Object Tracking diff --git a/pxr/imaging/lib/hd/engine.cpp b/pxr/imaging/lib/hd/engine.cpp index f2ebf2b79d..3edf9e5339 100644 --- a/pxr/imaging/lib/hd/engine.cpp +++ b/pxr/imaging/lib/hd/engine.cpp @@ -187,3 +187,29 @@ HdEngine::Execute(HdRenderIndex& index, HdTaskSharedPtrVector const &tasks) (*it)->Execute(&_context); } } + + +void +HdEngine::ReloadAllShaders(HdRenderIndex& index) +{ + HdChangeTracker &tracker = index.GetChangeTracker(); + + // 1st dirty all rprims, so they will trigger shader reload + tracker.MarkAllRprimsDirty(HdChangeTracker::AllDirty); + + // Dirty all surface shaders + tracker.MarkAllShadersDirty(HdChangeTracker::AllDirty); + + // Invalidate Geometry shader cache in Resource Registry. + _resourceRegistry->InvalidateGeometricShaderRegistry(); + + // Fallback Shader + index.ReloadFallbackShader(); + + + // Note: Several Shaders are not currently captured in this + // - Lighting Shaders + // - Render Pass Shaders + // - Culling Shader + +} diff --git a/pxr/imaging/lib/hd/engine.h b/pxr/imaging/lib/hd/engine.h index 48dc8d6aad..afb2abf40c 100644 --- a/pxr/imaging/lib/hd/engine.h +++ b/pxr/imaging/lib/hd/engine.h @@ -74,6 +74,10 @@ class HdEngine { HdRenderPassSharedPtr const &renderPass, HdRenderPassStateSharedPtr const &renderPassState); + + void ReloadAllShaders(HdRenderIndex& index); + + private: void _InitCaps() const; diff --git a/pxr/imaging/lib/hd/instanceRegistry.h b/pxr/imaging/lib/hd/instanceRegistry.h index c158310dc4..6fb49cf1be 100644 --- a/pxr/imaging/lib/hd/instanceRegistry.h +++ b/pxr/imaging/lib/hd/instanceRegistry.h @@ -134,6 +134,8 @@ class HdInstanceRegistry { const_iterator begin() const { return _dictionary.begin(); } const_iterator end() const { return _dictionary.end(); } + void Invalidate(); + private: template static bool _IsUnique(boost::shared_ptr const &value) { @@ -222,4 +224,14 @@ HdInstanceRegistry::GarbageCollect() return count; } +template +void +HdInstanceRegistry::Invalidate() +{ + HD_TRACE_FUNCTION(); + HD_MALLOC_TAG_FUNCTION(); + + _dictionary.clear(); +} + #endif // HD_INSTANCE_REGISTRY_H diff --git a/pxr/imaging/lib/hd/renderIndex.cpp b/pxr/imaging/lib/hd/renderIndex.cpp index fda1dc16c2..e946a3bbf6 100644 --- a/pxr/imaging/lib/hd/renderIndex.cpp +++ b/pxr/imaging/lib/hd/renderIndex.cpp @@ -61,10 +61,7 @@ HdRenderIndex::HdRenderIndex() : _nextPrimId(1) { // Creating the fallback shader - GlfGLSLFXSharedPtr glslfx = GlfGLSLFXSharedPtr(new GlfGLSLFX( - HdPackageFallbackSurfaceShader())); - - _surfaceFallback = HdSurfaceShaderSharedPtr(new HdGLSLFXShader(glslfx)); + ReloadFallbackShader(); // Register well-known collection types (to be deprecated) // XXX: for compatibility and smooth transition, @@ -350,6 +347,16 @@ HdRenderIndex::RemoveShader(SdfPath const& id) _shaderMap.erase(it); } +void +HdRenderIndex::ReloadFallbackShader() +{ + GlfGLSLFXSharedPtr glslfx = GlfGLSLFXSharedPtr(new GlfGLSLFX( + HdPackageFallbackSurfaceShader())); + + _surfaceFallback = HdSurfaceShaderSharedPtr(new HdGLSLFXShader(glslfx)); +} + + // -------------------------------------------------------------------------- // /// \name Task Support // -------------------------------------------------------------------------- // diff --git a/pxr/imaging/lib/hd/renderIndex.h b/pxr/imaging/lib/hd/renderIndex.h index ce8cda583d..90353e84ac 100644 --- a/pxr/imaging/lib/hd/renderIndex.h +++ b/pxr/imaging/lib/hd/renderIndex.h @@ -186,6 +186,8 @@ class HdRenderIndex : public boost::noncopyable { return _surfaceFallback; }; + void ReloadFallbackShader(); + // ---------------------------------------------------------------------- // /// \name Task Support // ---------------------------------------------------------------------- // diff --git a/pxr/imaging/lib/hd/renderPassShader.cpp b/pxr/imaging/lib/hd/renderPassShader.cpp index c6f7962c06..604480d728 100644 --- a/pxr/imaging/lib/hd/renderPassShader.cpp +++ b/pxr/imaging/lib/hd/renderPassShader.cpp @@ -73,7 +73,7 @@ HdRenderPassShader::ComputeHash() const // if nothing changed, returns the cached hash value if (_hashValid) return _hash; - _hash = _glslfxFile.Hash(); + _hash = _glslfx->GetHash(); // cullFaces are dynamic, no need to put in the hash. diff --git a/pxr/imaging/lib/hd/resourceRegistry.cpp b/pxr/imaging/lib/hd/resourceRegistry.cpp index ca45386636..d5679723ec 100644 --- a/pxr/imaging/lib/hd/resourceRegistry.cpp +++ b/pxr/imaging/lib/hd/resourceRegistry.cpp @@ -749,6 +749,11 @@ HdResourceRegistry::FindTextureResource(HdTextureResource::ID id, } +void HdResourceRegistry::InvalidateGeometricShaderRegistry() +{ + _geometricShaderRegistry.Invalidate(); +} + std::ostream &operator <<(std::ostream &out, const HdResourceRegistry& self) { diff --git a/pxr/imaging/lib/hd/resourceRegistry.h b/pxr/imaging/lib/hd/resourceRegistry.h index 01b6b39710..870a9a4d26 100644 --- a/pxr/imaging/lib/hd/resourceRegistry.h +++ b/pxr/imaging/lib/hd/resourceRegistry.h @@ -230,6 +230,8 @@ class HdResourceRegistry : public boost::noncopyable { HdPersistentBufferSharedPtr RegisterPersistentBuffer( TfToken const &role, size_t dataSize, void *data); + void InvalidateGeometricShaderRegistry(); + /// Remove any entries associated with expired dispatch buffers. void GarbageCollectDispatchBuffers(); From d55b91270464a65730e47e051ac2db0507e9925f Mon Sep 17 00:00:00 2001 From: superfunc Date: Tue, 25 Oct 2016 13:47:19 -0700 Subject: [PATCH 278/380] [Js] Remove BOOST_FOREACH usage. (Internal change: 1665957) --- pxr/base/lib/js/converter.h | 5 ++--- pxr/base/lib/js/json.cpp | 5 ++--- pxr/base/lib/js/testenv/testJsConverter.cpp | 2 +- 3 files changed, 5 insertions(+), 7 deletions(-) diff --git a/pxr/base/lib/js/converter.h b/pxr/base/lib/js/converter.h index a388e219de..a2e9b0a2ad 100644 --- a/pxr/base/lib/js/converter.h +++ b/pxr/base/lib/js/converter.h @@ -28,7 +28,6 @@ #include "pxr/base/js/value.h" #include "pxr/base/tf/diagnostic.h" -#include #include // Converts a \c JsValue \p value holding an \c int value to a \c ValueType @@ -114,7 +113,7 @@ class JsValueTypeConverter /// Converts \p object to \c MapType. static MapType _ObjectToMap(const JsObject& object) { MapType result; - BOOST_FOREACH(const JsObject::value_type& p, object) { + for (const auto& p : object) { result[p.first] = _ToValueType(p.second); } return result; @@ -124,7 +123,7 @@ class JsValueTypeConverter static VectorType _ArrayToVector(const JsArray& array) { VectorType result; result.reserve(array.size()); - BOOST_FOREACH(const JsValue& value, array) { + for (const auto& value : array) { result.push_back(_ToValueType(value)); } return result; diff --git a/pxr/base/lib/js/json.cpp b/pxr/base/lib/js/json.cpp index 8ea6d18ce1..eaa6662df9 100644 --- a/pxr/base/lib/js/json.cpp +++ b/pxr/base/lib/js/json.cpp @@ -26,7 +26,6 @@ #include "pxr/base/js/json.h" #include "pxr/base/tf/diagnostic.h" -#include #include #include @@ -126,7 +125,7 @@ _ToImplObjectValue( { rj::Value value(rj::kObjectType); - BOOST_FOREACH(const JsObject::value_type& p, object) { + for (const auto& p : object) { value.AddMember( rj::Value(p.first.c_str(), allocator).Move(), _JsValueToImplValue(p.second, allocator), @@ -144,7 +143,7 @@ _ToImplArrayValue( { rj::Value value(rj::kArrayType); - BOOST_FOREACH(const JsValue& e, array) { + for (const auto& e : array) { value.PushBack( rj::Value(_JsValueToImplValue(e, allocator)).Move(), allocator); diff --git a/pxr/base/lib/js/testenv/testJsConverter.cpp b/pxr/base/lib/js/testenv/testJsConverter.cpp index 653f45b235..be6f475cde 100644 --- a/pxr/base/lib/js/testenv/testJsConverter.cpp +++ b/pxr/base/lib/js/testenv/testJsConverter.cpp @@ -215,7 +215,7 @@ int main(int argc, char const *argv[]) std::cout << "checking converted values" << std::endl; - BOOST_FOREACH(const _Dictionary::value_type& p, aObject) { + for (const auto& p : aObject) { const std::type_info* ti = GetType(p.second); indent << "key " << p.first << " typeid is " << (ti ? ArchGetDemangled(*ti) : "nil") << std::endl; From 7f143e3554f116b03174e382be7cb572a5e1fb7e Mon Sep 17 00:00:00 2001 From: superfunc Date: Tue, 25 Oct 2016 13:47:28 -0700 Subject: [PATCH 279/380] [Pcp] Remove usage of BOOST_FOREACH. (Internal change: 1665958) --- pxr/usd/lib/pcp/cache.cpp | 72 +++++++++++---------- pxr/usd/lib/pcp/changes.cpp | 44 ++++++------- pxr/usd/lib/pcp/dependencies.cpp | 106 +++++++++++++++---------------- pxr/usd/lib/pcp/instanceKey.cpp | 10 ++- pxr/usd/lib/pcp/instancing.h | 2 - pxr/usd/lib/pcp/primIndex.cpp | 5 +- 6 files changed, 116 insertions(+), 123 deletions(-) diff --git a/pxr/usd/lib/pcp/cache.cpp b/pxr/usd/lib/pcp/cache.cpp index fc98b98436..3819a7e084 100644 --- a/pxr/usd/lib/pcp/cache.cpp +++ b/pxr/usd/lib/pcp/cache.cpp @@ -58,7 +58,6 @@ #include #include -#include #include #include @@ -535,7 +534,7 @@ PcpCache::_GetPathsUsingPcpSite( sourceNodes->clear(); sourceNodes->reserve(results.size()); - BOOST_FOREACH(const SdfPath& pcpSitePath, results) { + for (const auto& pcpSitePath : results) { SdfPath primUsingSite = pcpSitePath; PcpLayerStackSite usedSite(layerStack, path); PcpNodeRef nodeUsingSite; @@ -584,7 +583,7 @@ PcpCache::_UsesLayer(const SdfLayerHandle& layer) const const PcpLayerStackPtrVector& layerStacks = FindAllLayerStacksUsingLayer(layer); - BOOST_FOREACH(const PcpLayerStackPtr& layerStack, layerStacks) { + for (const auto& layerStack : layerStacks) { // PcpCache doesn't record dependencies on its root layer stack, // so we have to check that explicitly. if (layerStack == _layerStack or @@ -735,7 +734,7 @@ PcpCache::_GetPathsUsingPrim( const PcpLayerStackPtrVector& layerStacks = FindAllLayerStacksUsingLayer(layer); - BOOST_FOREACH(const PcpLayerStackPtr& layerStack, layerStacks) { + for (const auto& layerStack : layerStacks) { PcpNodeRefVector spookyNodes; const SdfPathVector spookyPaths = _GetPathsUsingPcpSite(layerStack, path, @@ -778,7 +777,7 @@ PcpCache::_GetPathsUsingPrim( layer, fallbackAncestor, sourceNodes); if (not result.empty()) { - BOOST_FOREACH(SdfPath& resultPath, result) { + for (auto& resultPath : result) { // Strip out any variant selections from the result path, // as each should be a Pcp site path and not a storage path. // XXX: This probably isn't handling @@ -798,7 +797,7 @@ PcpCache::_GetPathsUsingPrim( // Pcp site to site dependencies to find that dangling inherit. const PcpLayerStackPtrVector& layerStacks = FindAllLayerStacksUsingLayer(layer); - BOOST_FOREACH(const PcpLayerStackPtr& layerStack, layerStacks) { + for (const auto& layerStack : layerStacks) { PcpNodeRefVector nodes; const SdfPathVector paths = _GetPathsUsingPcpSite(layerStack, path, @@ -986,10 +985,12 @@ PcpCache::_GetPathsUsingSite( const bool descendantsNeedSourceNodes = (descendantsNeedPathTranslation or needsSourceNodes); - BOOST_FOREACH(const SdfPath& depPath, result) { - BOOST_FOREACH(const _PropertyIndexCache::value_type& v, - _propertyIndexCache.FindSubtreeRange(depPath)) { - + for (const auto& depPath : result) { + auto range = _propertyIndexCache.FindSubtreeRange(depPath); + for (auto valueIter = range.first; valueIter != range.second; + ++valueIter) + { + const auto& v = *valueIter; const SdfPath& propertyPath = v.first; const PcpPropertyIndex& propertyIndex = v.second; @@ -1174,7 +1175,7 @@ PcpCache::_Translate( layerOffsets->reserve(depSourceNodes.size()); } - BOOST_FOREACH(const PcpNodeRef& sourceNode, depSourceNodes) { + for (const auto& sourceNode : depSourceNodes) { const SdfPath translatedPath = PcpTranslatePathFromNodeToRoot(sourceNode, path); if (not translatedPath.IsEmpty()) { @@ -1238,7 +1239,8 @@ PcpCache::CanHaveOpinionForSite( // Iterate over all nodes. PcpNodeRange range = primIndex->GetNodeRange(); - BOOST_FOREACH(const PcpNodeRef& node, range) { + for (auto nodeIter = range.first; nodeIter != range.second; ++nodeIter) { + const auto& node = *nodeIter; // Ignore nodes that don't provide specs. if (node.CanContributeSpecs()) { // Check each layer stack that contributes specs only once. @@ -1372,7 +1374,7 @@ _TranslatePathAndTargetPaths( SdfPathVector targetPaths; path.GetAllTargetPathsRecursively(&targetPaths); - BOOST_FOREACH(const SdfPath& targetPath, targetPaths) { + for (const auto& targetPath : targetPaths) { // Do allow translation via -> in target paths. const SdfPath translatedTargetPath = node.GetMapToParent().MapSourceToTarget(targetPath); @@ -1685,7 +1687,7 @@ PcpCache::ComputeNamespaceEdits( // Get all sites in cache that depend on primPath in any of // the layer stacks. - BOOST_FOREACH(const PcpLayerStackPtr& layerStack, layerStacks) { + for (const auto& layerStack : layerStacks) { PcpNodeRefVector depNodes; depPaths = cache->_GetPathsUsingPcpSite( layerStack, primPath, PcpDirect | PcpAncestral, &depNodes); @@ -1700,7 +1702,7 @@ PcpCache::ComputeNamespaceEdits( } // Store the node for each dependent site. - BOOST_FOREACH(const PcpNodeRef& node, depNodes) { + for (const auto& node : depNodes) { _CacheNodeHelper::InsertCacheNodePair( cacheIndex, node, &nodes); } @@ -1714,7 +1716,7 @@ PcpCache::ComputeNamespaceEdits( PcpCache* cache = caches[cacheIndex]; // Get all sites in cache that depend on any spec in primSites. - BOOST_FOREACH(const SdfSite& primSite, primSites) { + for (const auto& primSite : primSites) { TF_VERIFY(primSite.path == primPath); PcpNodeRefVector depNodes; depPaths = @@ -1723,7 +1725,7 @@ PcpCache::ComputeNamespaceEdits( not spooky, &depNodes); // Store the node for each dependent site. - BOOST_FOREACH(const PcpNodeRef& node, depNodes) { + for (const auto& node : depNodes) { _CacheNodeHelper::InsertCacheNodePair( cacheIndex, node, &nodes); } @@ -1763,10 +1765,13 @@ PcpCache::ComputeNamespaceEdits( // at this cache's layer stack. Make sure to skip ancestral // nodes, since the code that handles direct inherits below // needs to have the nodes where the inherits are introduced. - BOOST_FOREACH(const SdfPath& descendantSite, descendantSites) { - BOOST_FOREACH(const PcpNodeRef& node, - _GetPrimIndex(descendantSite)->GetNodeRange( - PcpRangeTypeLocalInherit)) { + for (const auto& descendantSite : descendantSites) { + auto range = _GetPrimIndex(descendantSite)->GetNodeRange( + PcpRangeTypeLocalInherit); + for (auto nodeIter = range.first; nodeIter != range.second; + ++nodeIter) + { + const auto& node = *nodeIter; if (node.GetLayerStack() == _layerStack and not node.IsDueToAncestor()) { // Found an inherit using a descendant. @@ -1880,7 +1885,7 @@ PcpCache::ComputeNamespaceEdits( typedef NamespaceEdits::LayerStackSite LayerStackSite; typedef NamespaceEdits::CacheSite CacheSite; std::set sites; - BOOST_FOREACH(const CacheNodePair& cacheAndNode, nodes) { + for (const auto& cacheAndNode : nodes) { size_t cacheIndex = cacheAndNode.first; PcpNodeRef node = cacheAndNode.second; SdfPath oldNodePath = curPath; @@ -1979,7 +1984,7 @@ PcpCache::ComputeNamespaceEdits( // descendants. We don't want to remove those but we may // want to remove their descendants. std::set doNotRemoveSites; - BOOST_FOREACH(const CacheNodePair& cacheAndNode, descendantNodes) { + for (const auto& cacheAndNode : descendantNodes) { const PcpNodeRef& node = cacheAndNode.second; doNotRemoveSites.insert(node.GetParentNode().GetSite()); } @@ -1992,7 +1997,7 @@ PcpCache::ComputeNamespaceEdits( // namespace edited site and what each site depends on. std::map descendantPathsAndNodes; PcpNodeRefVector sourceNodes; - BOOST_FOREACH(const SdfLayerRefPtr& layer, _layerStack->GetLayers()) { + for (const auto& layer : _layerStack->GetLayers()) { SdfPathVector paths = cache->_GetPathsUsingSite(layer, curPath, UsingSiteAndDescendants, @@ -2053,7 +2058,7 @@ PcpCache::ComputeNamespaceEdits( // Fix up all direct inherits to a descendant site. if (not descendantNodes.empty()) { - BOOST_FOREACH(const CacheNodePair& cacheAndNode, descendantNodes) { + for (const auto& cacheAndNode : descendantNodes) { size_t cacheIndex = cacheAndNode.first; const PcpNodeRef& node = cacheAndNode.second; SdfPath oldNodePath = node.GetPath(); @@ -2125,7 +2130,7 @@ PcpCache::GetInvalidAssetPaths() const const PcpPrimIndex& primIndex = it->second; if (primIndex.GetRootNode()) { PcpErrorVector errors = primIndex.GetLocalErrors(); - BOOST_FOREACH(const PcpErrorBasePtr & e, errors) { + for (const auto& e : errors) { if (PcpErrorInvalidAssetPathPtr typedErr = dynamic_pointer_cast(e)){ result[primPath].push_back(typedErr->resolvedAssetPath); @@ -2294,7 +2299,7 @@ PcpCache::Reload(PcpChanges* changes) _layerStackCache->GetAllLayerStacks(); TF_FOR_ALL(layerStack, allLayerStacks) { const PcpErrorVector errors = (*layerStack)->GetLocalErrors(); - BOOST_FOREACH(const PcpErrorBasePtr& e, errors) { + for (const auto& e : errors) { if (PcpErrorInvalidSublayerPathPtr typedErr = dynamic_pointer_cast(e)) { changes->DidMaybeFixSublayer(this, @@ -2307,7 +2312,7 @@ PcpCache::Reload(PcpChanges* changes) const PcpPrimIndex& primIndex = it->second; if (primIndex.GetRootNode()) { const PcpErrorVector errors = primIndex.GetLocalErrors(); - BOOST_FOREACH(const PcpErrorBasePtr& e, errors) { + for (const auto& e : errors) { if (PcpErrorInvalidAssetPathPtr typedErr = dynamic_pointer_cast(e)) { changes->DidMaybeFixAsset(this, @@ -2342,12 +2347,13 @@ PcpCache::ReloadReferences(PcpChanges* changes, const SdfPath& primPath) // Traverse every PrimIndex at or under primPath to find // InvalidAssetPath errors, and collect the unique layer stacks used. std::set layerStacksAtOrUnderPrim; - BOOST_FOREACH(const _PrimIndexCache::value_type& entry, - _primIndexCache.FindSubtreeRange(primPath)) { + auto range = _primIndexCache.FindSubtreeRange(primPath); + for (auto entryIter = range.first; entryIter != range.second; ++entryIter) { + const auto& entry = *entryIter; const PcpPrimIndex& primIndex = entry.second; if (primIndex.GetRootNode()) { PcpErrorVector errors = primIndex.GetLocalErrors(); - BOOST_FOREACH(const PcpErrorBasePtr& e, errors) { + for (const auto& e : errors) { if (PcpErrorInvalidAssetPathPtr typedErr = dynamic_pointer_cast(e)) { @@ -2585,7 +2591,7 @@ struct Pcp_ParallelIndexer TfTokenVector names; PcpTokenSet prohibitedNames; index->ComputePrimChildNames(&names, &prohibitedNames); - BOOST_FOREACH(const TfToken &name, names) { + for (const auto& name : names) { // We only check the cache for the children if we got a cache // hit for this index. Pcp tends to invalidate entire subtrees // at once. @@ -2754,7 +2760,7 @@ PcpCache::_ComputePrimIndexesInParallel( GetPrimIndexInputs().USD(_usd), allErrors, &parentCache, mallocTag1, mallocTag2); - BOOST_FOREACH(const SdfPath &rootPath, roots) { + for (const auto& rootPath : roots) { // Obtain the parent index, if this is not the absolute root. Note that // the call to ComputePrimIndex below is not concurrency safe. const PcpPrimIndex *parentIndex = diff --git a/pxr/usd/lib/pcp/changes.cpp b/pxr/usd/lib/pcp/changes.cpp index 1d479c641d..f98c157b6b 100644 --- a/pxr/usd/lib/pcp/changes.cpp +++ b/pxr/usd/lib/pcp/changes.cpp @@ -38,7 +38,6 @@ #include "pxr/usd/sdf/layerUtils.h" #include "pxr/usd/ar/resolverContextBinder.h" #include "pxr/base/tracelite/trace.h" -#include static void @@ -392,7 +391,7 @@ PcpChanges::DidChange(const std::vector& caches, typedef std::vector CacheLayerStacksVector; CacheLayerStacksVector cacheLayerStacks; - BOOST_FOREACH(PcpCache* cache, caches) { + for (auto cache : caches) { PcpLayerStackPtrVector stacks = cache->FindAllLayerStacksUsingLayer(layer); if (not stacks.empty()) { @@ -598,7 +597,7 @@ PcpChanges::DidChange(const std::vector& caches, pathsWithSignificantChanges.insert(path); } else { - BOOST_FOREACH(const CacheLayerStacks& c, cacheLayerStacks) { + for (const auto& c : cacheLayerStacks) { PcpCache* cache = c.first; if (Pcp_DecoratorRequiresPrimIndexChange( cache->GetPayloadDecorator(), @@ -682,8 +681,7 @@ PcpChanges::DidChange(const std::vector& caches, // Note that in the below code, the order of the if statements does // matter, as a spec could be added, then removed (for example) within // the same change. - BOOST_FOREACH(const SpecChangesTypes::value_type& value, - pathsWithSpecChangesTypes) { + for (const auto& value : pathsWithSpecChangesTypes) { const SdfPath& path = value.first; if (path.IsPrimOrPrimVariantSelectionPath()) { if (value.second & Pcp_EntryChangeSpecsNonInert) { @@ -721,11 +719,11 @@ PcpChanges::DidChange(const std::vector& caches, // (layer,path). If there aren't any and we want to fallback to our // parent then find all paths in the cache that use the parent. In // either case mark the found paths as having a significant change. - BOOST_FOREACH(const SdfPath& path, pathsWithSignificantChanges) { + for (const auto& path : pathsWithSignificantChanges) { // Compute the closest ancestor that must have dependencies. SdfPath fallbackPath = findAncestor(path); - BOOST_FOREACH(PcpCache* cache, caches) { + for (auto cache : caches) { _DidChangeDependents( _ChangeTypeSignificant, cache, layer, path, fallbackPath, debugSummary); @@ -735,8 +733,7 @@ PcpChanges::DidChange(const std::vector& caches, // For every path we've found that has a significant change in // a specific cache, use the same logic as above to mark those paths // as having a significant change, but only in the associated cache. - BOOST_FOREACH(const CacheAndLayerPathPair& p, - pathsWithSignificantChangesByCache) { + for (const auto& p : pathsWithSignificantChangesByCache) { // Compute the closest ancestor that must have dependencies. SdfPath fallbackPath = findAncestor(p.second); @@ -789,7 +786,7 @@ PcpChanges::DidChange(const std::vector& caches, // there aren't any then find all paths in the cache that use the // parent. In either case mark the found paths as needing their // property spec stacks blown. - BOOST_FOREACH(const PathChangeValue& value, pathsWithSpecChanges) { + for (const auto& value : pathsWithSpecChanges) { const SdfPath& path = value.first; PathChangeBitmask changes = value.second; @@ -810,7 +807,7 @@ PcpChanges::DidChange(const std::vector& caches, // Compute the closest ancestor that must have dependencies. SdfPath fallbackPath = findAncestor(path); - BOOST_FOREACH(PcpCache* cache, caches) { + for (auto cache : caches) { _DidChangeDependents( changeType, cache, layer, path, fallbackPath, debugSummary); @@ -825,7 +822,7 @@ PcpChanges::DidChange(const std::vector& caches, SdfPathVector depPaths; PcpNodeRefVector depNodes; - BOOST_FOREACH(PcpCache* cache, caches) { + for (auto cache : caches) { PcpCacheChanges::PathEditMap& renameChanges = _GetRenameChanges(cache); @@ -839,7 +836,7 @@ PcpChanges::DidChange(const std::vector& caches, // act as if we're deleting the object at the new path. if (not newPath.IsEmpty()) { depPaths = cache->GetPathsUsingSite(layer, newPath); - BOOST_FOREACH(const SdfPath& depNewPath, depPaths) { + for (const auto& depNewPath : depPaths) { renameChanges[depNewPath] = SdfPath(); } } @@ -1055,7 +1052,7 @@ PcpChanges::DidMaybeFixAsset( SdfPathVector depPaths = cache->GetPathsUsingSite(layerStack, site.path, PcpDirect | PcpAncestral); - BOOST_FOREACH(const SdfPath& depPath, depPaths) { + for (const auto& depPath : depPaths) { PCP_APPEND_DEBUG(" <%s>\n", depPath.GetText()); DidChangeSignificantly(cache, depPath); } @@ -1329,7 +1326,7 @@ PcpChanges::_OptimizePathChanges( // sdOnly now has the path changes that Sd told us about but // DidChangePaths() did not. We must assume the worst. - BOOST_FOREACH(const PathPair& change, sdOnly) { + for (const auto& change : sdOnly) { const SdfPath& oldPath = change.first; const SdfPath& newPath = change.second; @@ -1434,7 +1431,7 @@ PcpChanges::_DidChangeDependents( if (cache->_usd) { const PcpLayerStackPtrVector& layerStacks = cache->FindAllLayerStacksUsingLayer(layer); - BOOST_FOREACH(const PcpLayerStackPtr &layerStack, layerStacks) { + for (const auto& layerStack : layerStacks) { if (layerStack == cache->GetLayerStack()) { depPaths.push_back(path.StripAllVariantSelections()); } @@ -1470,7 +1467,7 @@ PcpChanges::_DidChangeDependents( layer->GetIdentifier().c_str(), path.GetText(), TfStringReplace(pathDebugSummary, "\n", "\n ").c_str()); - BOOST_FOREACH(const SdfPath& depPath, depPaths) { + for (const auto& depPath : depPaths) { changeFuncs.RunFunctionsOnDependency(cache, depPath, layer, path); } } @@ -1507,7 +1504,7 @@ PcpChanges::_DidChangeDependents( layer->GetIdentifier().c_str(), path.GetText(), TfStringReplace(pathDebugSummary, "\n", "\n ").c_str()); - BOOST_FOREACH(const SdfPath& depPath, spookyDepPaths) { + for (const auto& depPath : spookyDepPaths) { changeFuncs.RunFunctionsOnDependency(cache, depPath, layer, path); } @@ -1645,7 +1642,7 @@ PcpChanges::_DidChangeSublayer( // stack that may need to be adjusted due to the addition or removal of // a layer from that stack. const SdfPath& rootPath = SdfPath::AbsoluteRootPath(); - BOOST_FOREACH(const PcpLayerStackPtr& layerStack, layerStacks) { + for (const auto& layerStack : layerStacks) { static bool recursive = true; SdfPathVector paths = cache->GetPathsUsingSite(layerStack, rootPath, @@ -1676,7 +1673,7 @@ PcpChanges::_DidChangeSublayer( layerStack->GetIdentifier().rootLayer-> GetIdentifier().c_str()); - BOOST_FOREACH(const SdfPath& path, paths) { + for (const auto& path : paths) { PCP_APPEND_DEBUG(" <%s>\n", path.GetText()); if (*significant) { DidChangeSignificantly(cache, path); @@ -1788,11 +1785,10 @@ PcpChanges::_DidChangeLayerStackRelocations( } // Resync affected prims. - BOOST_FOREACH(const SdfPath& path, - changes.pathsAffectedByRelocationChanges) { + for (const auto& path : changes.pathsAffectedByRelocationChanges) { PCP_APPEND_DEBUG(" Relocation change affected path <%s>\n", path.GetText()); - BOOST_FOREACH(PcpCache* cache, caches) { + for (auto cache : caches) { // Find paths to dependent caches. SdfPathSet depPathSet; @@ -1828,7 +1824,7 @@ PcpChanges::_DidChangeLayerStackRelocations( /* spooky = */ true); depPathSet.insert(depPathsSpooky.begin(), depPathsSpooky.end()); - BOOST_FOREACH(const SdfPath& depPath, depPathSet) { + for (const auto& depPath : depPathSet) { DidChangeSignificantly(cache, depPath); } } diff --git a/pxr/usd/lib/pcp/dependencies.cpp b/pxr/usd/lib/pcp/dependencies.cpp index af1b7f9659..59ef47fc67 100644 --- a/pxr/usd/lib/pcp/dependencies.cpp +++ b/pxr/usd/lib/pcp/dependencies.cpp @@ -41,7 +41,6 @@ #include "pxr/base/tf/mallocTag.h" #include "pxr/base/tf/stl.h" #include "pxr/base/work/arenaDispatcher.h" -#include #include #include #include @@ -458,8 +457,7 @@ Pcp_Dependencies::Add( pcpSitePath.GetText(), _FormatDependencies(dependencies).c_str()); - BOOST_FOREACH(const PcpPrimIndexDependencies::Map::value_type& dep, - dependencies.sites) { + for (const auto& dep : dependencies.sites) { const PcpPrimIndexDependencies::Site& site = dep.first; // Retain the layer stack. @@ -519,8 +517,7 @@ Pcp_Dependencies::AddSpookySitesUsedByPrim( pcpSitePath.GetText(), _FormatDependencies(spookyDependencies).c_str()); - BOOST_FOREACH(const PcpPrimIndexDependencies::Map::value_type& dep, - spookyDependencies.sites) { + for (const auto& dep : spookyDependencies.sites) { const PcpPrimIndexDependencies::Site& site = dep.first; // Spooky dependencies do not retain the layer stack. @@ -570,8 +567,8 @@ Pcp_Dependencies::Remove( // Discard sdToPcp entries, i.e. the entries in the reverse mapping of // the pcpToSd/sdToPcp bidirectional map. - BOOST_FOREACH(const Pcp_DependenciesData::PcpToSd::value_type& value, - range) { + for (auto valueIter = range.first; valueIter != range.second; ++valueIter) { + const auto& value = *valueIter; const Pcp_DependenciesData::SdfSiteMultiset& entry = value.second; if (TfDebug::IsEnabled(PCP_DEPENDENCIES)) { debugSites.push_back( @@ -581,7 +578,7 @@ Pcp_Dependencies::Remove( } // Remove the reverse mapping. - BOOST_FOREACH(const SdfSite& sdfSite, entry) { + for (const auto& sdfSite : entry) { _data->sdToPcp[sdfSite.layer][sdfSite.path].EraseOne(value.first); // Only mark this Sd site as needing to be flushed if we're @@ -641,8 +638,8 @@ Pcp_Dependencies::Remove( // Discard spookySdToPcp entries, i.e. the entries in the // reverse mapping of the spookyPcpToSd/spookySdToPcp // bidirectional map. - BOOST_FOREACH(const Pcp_DependenciesData::PcpToSd::value_type& value, - range) { + for (auto valueIter = range.first; valueIter != range.second; ++valueIter) { + const auto& value = *valueIter; const Pcp_DependenciesData::SdfSiteMultiset& entry = value.second; if (TfDebug::IsEnabled(PCP_DEPENDENCIES)) { debugSites.push_back( @@ -653,7 +650,7 @@ Pcp_Dependencies::Remove( } // Remove the reverse mapping. - BOOST_FOREACH(const SdfSite& sdfSite, entry) { + for (const auto& sdfSite : entry) { _data->spookySdToPcp[sdfSite.layer][sdfSite.path]. EraseOne(value.first); _data->sdfSpookySiteNeedsFlush.Insert(sdfSite); @@ -680,8 +677,10 @@ Pcp_Dependencies::Remove( // Discard sites using site entries, i.e. the entries in the reverse // mapping of the PcpSite dependencies bidirectional map. - BOOST_FOREACH(const Pcp_DependenciesData:: - SitesUsedBySite::value_type& value, siteRange) { + for (auto valueIter = siteRange.first; valueIter != siteRange.second; + ++valueIter) + { + const auto& value = *valueIter; if (TfDebug::IsEnabled(PCP_DEPENDENCIES)) { debugSites.push_back( TfStringPrintf(" <%s> (site):", @@ -691,8 +690,7 @@ Pcp_Dependencies::Remove( } // Remove the reverse mapping. - BOOST_FOREACH(const Pcp_DependenciesData::PcpStackSite& pcpSite, - value.second) { + for (const auto& pcpSite : value.second) { _data->sitesUsingSite[pcpSite.first][pcpSite.second]. EraseOne(value.first); _data->pcpSiteNeedsFlush.Insert(pcpSite); @@ -721,8 +719,10 @@ Pcp_Dependencies::Remove( // Discard sites using site entries, i.e. the entries in the reverse // mapping of the PcpSite dependencies bidirectional map. - BOOST_FOREACH(const Pcp_DependenciesData:: - SitesUsedBySite::value_type& value, siteRange) { + for (auto valueIter = siteRange.first; valueIter != siteRange.second; + ++valueIter) { + const auto& value = *valueIter; + if (TfDebug::IsEnabled(PCP_DEPENDENCIES)) { debugSites.push_back( TfStringPrintf(" <%s> (spooky site):", @@ -732,8 +732,7 @@ Pcp_Dependencies::Remove( } // Remove the reverse mapping. - BOOST_FOREACH(const Pcp_DependenciesData::PcpStackSite& pcpSite, - value.second) { + for (const auto& pcpSite : value.second) { _data->spookySitesUsingSite[pcpSite.first][pcpSite.second]. EraseOne(value.first); _data->pcpSpookySiteNeedsFlush.Insert(pcpSite); @@ -764,14 +763,13 @@ Pcp_Dependencies::RemoveAll(PcpLifeboat* lifeboat) // Collect all of the used layer stacks. std::set layerStacks; - BOOST_FOREACH(const Pcp_LayerStackRefCountMap::value_type& v, - _data->layerStacks) { + for (const auto& v : _data->layerStacks) { layerStacks.insert(v.first); } // Put layer stacks in the lifeboat. if (lifeboat) { - BOOST_FOREACH(const PcpLayerStackRefPtr& layerStack, layerStacks) { + for (const auto& layerStack : layerStacks) { lifeboat->Retain(layerStack); } } @@ -800,8 +798,7 @@ Pcp_Dependencies::RemoveAll(PcpLifeboat* lifeboat) // If we don't then Flush() will get upset when calling EraseOne() // for each layer stack in retainedLayerStacks since there won't be // an expected entry. - BOOST_FOREACH(const PcpLayerStackRefPtr& layerStack, - _data->retainedLayerStacks) { + for (const auto& layerStack : _data->retainedLayerStacks) { _data->layerStacks.Insert(layerStack); } } @@ -835,7 +832,7 @@ Pcp_Dependencies::Flush() // Go through Sd sites discarding unused sites and layers. anyFound = false; - BOOST_FOREACH(const SdfSite& sdfSite, sdfSites) { + for (const auto& sdfSite : sdfSites) { // Find the layer. Pcp_DependenciesData::SdToPcp::iterator i = _data->sdToPcp.find(sdfSite.layer); @@ -885,7 +882,7 @@ Pcp_Dependencies::Flush() // Flush spooky spec dependencies. anyFound = false; - BOOST_FOREACH(const SdfSite& sdfSite, sdfSpookySites) { + for (const auto& sdfSite : sdfSpookySites) { // Find the layer. const Pcp_DependenciesData::SdToPcp::iterator j = _data->spookySdToPcp.find(sdfSite.layer); @@ -919,7 +916,7 @@ Pcp_Dependencies::Flush() // Go through pcpSites discarding unused sites. This is the same // algorithm as above. anyFound = false; - BOOST_FOREACH(const Pcp_DependenciesData::PcpStackSite& pcpSite, pcpSites){ + for (const auto& pcpSite : pcpSites) { // Find the layer stack. Pcp_DependenciesData::SitesUsingSite::iterator i = _data->sitesUsingSite.find(pcpSite.first); @@ -955,8 +952,7 @@ Pcp_Dependencies::Flush() // Flush spooky site dependencies. anyFound = false; - BOOST_FOREACH(const Pcp_DependenciesData::PcpStackSite& pcpSite, - pcpSpookySites) { + for (const auto& pcpSite : pcpSpookySites) { const Pcp_DependenciesData::SitesUsingSite::iterator j = _data->spookySitesUsingSite.find(pcpSite.first); if (j != _data->spookySitesUsingSite.end()) { @@ -1104,8 +1100,9 @@ Pcp_GetSdToPcpDependenciesRecursive( sdToPcp.find(sdfSite.layer); if (i != sdToPcp.end()) { typedef Pcp_DependenciesData::PathToNodeMultiset::value_type ValueType; - BOOST_FOREACH(const ValueType& value, - i->second.FindSubtreeRange(sdfSite.path)) { + auto range = i->second.FindSubtreeRange(sdfSite.path); + for (auto valueIter = range.first; valueIter != range.second; ++valueIter) { + const auto& value = *valueIter; if (not primsOnly or value.first.IsPrimOrPrimVariantSelectionPath()) { TF_FOR_ALL(j, value.second) { @@ -1150,7 +1147,7 @@ Pcp_GetWithType( const Pcp_DependencyPathTypeMultiset& paths, unsigned int dependencyType) { - BOOST_FOREACH(const Pcp_DependencyPathType &curPath, paths) { + for (const auto& curPath : paths) { // Only include paths that match the specified type. if (dependencyType & curPath.dependencyType) { result->insert(curPath.path); @@ -1174,7 +1171,7 @@ Pcp_GetAncestral( Pcp_DependenciesData::PathToPathTypeMultiset::const_iterator j = pathsUsingSite.find(path); if (j != pathsUsingSite.end()) { - BOOST_FOREACH(const Pcp_DependencyPathType &curPath, j->second) { + for (const auto& curPath : j->second) { result->insert(originalPath .ReplacePrefix(path, curPath.path) .StripAllVariantSelections()); @@ -1254,10 +1251,10 @@ Pcp_Dependencies::GetLayersUsedByPrim(const SdfPath& path, // Get layer stacks. std::set layerStacks; if (recursive) { - BOOST_FOREACH(const ValueType& value, - _data->sitesUsedBySite.FindSubtreeRange(path)) { - BOOST_FOREACH(const Pcp_DependenciesData::PcpStackSite& site, - value.second) { + auto range = _data->sitesUsedBySite.FindSubtreeRange(path); + for (auto valueIter = range.first; valueIter != range.second; ++valueIter) { + const auto& value = *valueIter; + for (const auto& site : value.second) { layerStacks.insert(site.first); } } @@ -1266,8 +1263,7 @@ Pcp_Dependencies::GetLayersUsedByPrim(const SdfPath& path, Pcp_DependenciesData::SitesUsedBySite::const_iterator i = _data->sitesUsedBySite.find(path); if (i != _data->sitesUsedBySite.end()) { - BOOST_FOREACH(const Pcp_DependenciesData::PcpStackSite& site, - i->second) { + for (const auto& site : i->second) { layerStacks.insert(site.first); } } @@ -1275,7 +1271,7 @@ Pcp_Dependencies::GetLayersUsedByPrim(const SdfPath& path, // Get layers. SdfLayerHandleSet layers; - BOOST_FOREACH(const PcpLayerStackPtr& layerStack, layerStacks) { + for (const auto& layerStack : layerStacks) { const SdfLayerRefPtrVector& localLayers = layerStack->GetLayers(); layers.insert(localLayers.begin(), localLayers.end()); } @@ -1288,8 +1284,7 @@ Pcp_Dependencies::GetUsedLayers() const { SdfLayerHandleSet reachedLayers; - BOOST_FOREACH(const Pcp_LayerStackRefCountMap::value_type& v, - _data->layerStacks) { + for (const auto& v : _data->layerStacks) { const SdfLayerRefPtrVector& layers = v.first->GetLayers(); reachedLayers.insert(layers.begin(), layers.end()); } @@ -1302,8 +1297,7 @@ Pcp_Dependencies::GetUsedRootLayers() const { SdfLayerHandleSet reachedRootLayers; - BOOST_FOREACH(const Pcp_LayerStackRefCountMap::value_type& v, - _data->layerStacks) { + for (const auto& v : _data->layerStacks) { const PcpLayerStackPtr& layerStack = v.first; reachedRootLayers.insert(layerStack->GetIdentifier().rootLayer); } @@ -1425,7 +1419,7 @@ _DumpDependencies( // Print forward dependencies. if (not fwd.empty()) { s << prefix << T::GetForwardLabel() << ":" << std::endl; - BOOST_FOREACH(const T& x, fwd) { + for (const auto& x : fwd) { if (prev.a != x.a) { prev.a = x.a; s << " @" << x.GetIdentifier() << "@:" << std::endl; @@ -1445,7 +1439,7 @@ _DumpDependencies( if (not rev.empty()) { prev = T(); s << prefix << T::GetReverseLabel() << ":" << std::endl; - BOOST_FOREACH(const T& x, rev) { + for (const auto& x : rev) { if (prev.c != x.c) { prev.c = x.c; s << " <" << x.c.GetText() << ">:" << std::endl; @@ -1490,17 +1484,17 @@ _GetDependencies( fwd->clear(); rev->clear(); - BOOST_FOREACH(const DD::SdToPcp::value_type& x, fwdInput) { - BOOST_FOREACH(const DD::PathToNodeMultiset::value_type& y, x.second) { - BOOST_FOREACH(const PcpNodeRef& z, y.second) { + for (const auto& x : fwdInput) { + for (const auto& y : x.second) { + for (const auto& z : y.second) { fwd->insert(Pcp_DependenciesSpecTuple( x.first, y.first, z.GetRootNode().GetPath())); } } } - BOOST_FOREACH(const DD::PcpToSd::value_type& x, revInput) { - BOOST_FOREACH(const DD::SdfSiteMultiset::value_type& y, x.second) { + for (const auto& x : revInput) { + for (const auto& y : x.second) { rev->insert(Pcp_DependenciesSpecTuple(y.layer, y.path, x.first)); } } @@ -1519,16 +1513,16 @@ _GetDependencies( fwd->clear(); rev->clear(); - BOOST_FOREACH(const DD::SitesUsingSite::value_type& x, fwdInput) { - BOOST_FOREACH(const DD::PathToPathTypeMultiset::value_type& y,x.second){ - BOOST_FOREACH(const Pcp_DependencyPathType& z, y.second) { + for (const auto& x : fwdInput) { + for (const auto& y : x.second) { + for (const auto& z : y.second) { fwd->insert(Pcp_DependenciesSiteTuple(x.first, y.first,z.path)); } } } - BOOST_FOREACH(const DD::SitesUsedBySite::value_type& x, revInput) { - BOOST_FOREACH(const DD::PcpSiteMultiset::value_type& y, x.second) { + for (const auto& x : revInput) { + for (const auto& y : x.second) { rev->insert(Pcp_DependenciesSiteTuple(y.first, y.second, x.first)); } } diff --git a/pxr/usd/lib/pcp/instanceKey.cpp b/pxr/usd/lib/pcp/instanceKey.cpp index d21eecb4bf..44d3f0ec59 100644 --- a/pxr/usd/lib/pcp/instanceKey.cpp +++ b/pxr/usd/lib/pcp/instanceKey.cpp @@ -29,8 +29,6 @@ #include "pxr/base/tracelite/trace.h" -#include - struct PcpInstanceKey::_Collector { bool Visit(const PcpNodeRef& node, bool nodeIsInstanceable) @@ -83,10 +81,10 @@ PcpInstanceKey::PcpInstanceKey(const PcpPrimIndex& primIndex) } _variantSelection.assign(variantSelection.begin(), variantSelection.end()); - BOOST_FOREACH(const _Arc& arc, _arcs) { + for (const auto& arc : _arcs) { boost::hash_combine(_hash, arc.GetHash()); } - BOOST_FOREACH(const _VariantSelection& vsel, _variantSelection) { + for (const auto& vsel : _variantSelection) { boost::hash_combine(_hash, vsel); } } @@ -113,7 +111,7 @@ PcpInstanceKey::GetString() const s += " (none)\n"; } else { - BOOST_FOREACH(const _Arc& arc, _arcs) { + for (const auto& arc : _arcs) { s += TfStringPrintf(" %s%s : %s\n", TfEnum::GetDisplayName(arc._arcType).c_str(), (arc._timeOffset.IsIdentity() ? @@ -130,7 +128,7 @@ PcpInstanceKey::GetString() const s += " (none)"; } else { - BOOST_FOREACH(const _VariantSelection& vsel, _variantSelection) { + for (const auto& vsel : _variantSelection) { s += TfStringPrintf(" %s = %s\n", vsel.first.c_str(), vsel.second.c_str()); } diff --git a/pxr/usd/lib/pcp/instancing.h b/pxr/usd/lib/pcp/instancing.h index 123c4f8c99..6a90dd9e64 100644 --- a/pxr/usd/lib/pcp/instancing.h +++ b/pxr/usd/lib/pcp/instancing.h @@ -32,8 +32,6 @@ #include "pxr/usd/pcp/node_Iterator.h" #include "pxr/usd/pcp/primIndex.h" -#include - /// Helper function to determine whether the given prim index is /// instanceable. An instanceable prim index must have instanceable /// nodes and must have been tagged so that the composed value of diff --git a/pxr/usd/lib/pcp/primIndex.cpp b/pxr/usd/lib/pcp/primIndex.cpp index 436174f40f..feca32e24d 100644 --- a/pxr/usd/lib/pcp/primIndex.cpp +++ b/pxr/usd/lib/pcp/primIndex.cpp @@ -50,7 +50,6 @@ #include "pxr/base/tf/envSetting.h" #include "pxr/base/tf/mallocTag.h" -#include #include #include #include @@ -300,7 +299,9 @@ PcpNodeRef PcpPrimIndex::GetNodeProvidingSpec( const SdfLayerHandle& layer, const SdfPath& path) const { - BOOST_FOREACH(const PcpNodeRef& node, GetNodeRange()) { + auto range = GetNodeRange(); + for (auto nodeIter = range.first; nodeIter != range.second; ++nodeIter) { + const auto& node = *nodeIter; // If the site has the given path and contributes specs then // search for the layer. if (node.CanContributeSpecs() and From 931ef2997ac685f02dabbb7b88b45d21642beab4 Mon Sep 17 00:00:00 2001 From: superfunc Date: Tue, 25 Oct 2016 13:47:32 -0700 Subject: [PATCH 280/380] [UsdImaging] Remove unused include. (Internal change: 1665959) --- pxr/usdImaging/lib/usdImagingGL/gl.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/pxr/usdImaging/lib/usdImagingGL/gl.cpp b/pxr/usdImaging/lib/usdImagingGL/gl.cpp index 930089550e..61b718925e 100644 --- a/pxr/usdImaging/lib/usdImagingGL/gl.cpp +++ b/pxr/usdImaging/lib/usdImagingGL/gl.cpp @@ -35,8 +35,6 @@ #include "pxr/imaging/glf/glContext.h" #include "pxr/imaging/glf/textureRegistry.h" -#include - namespace { static From 2c7a41607a932f756b67334e0bfbcfc1292e2a2d Mon Sep 17 00:00:00 2001 From: superfunc Date: Tue, 25 Oct 2016 13:47:41 -0700 Subject: [PATCH 281/380] [UsdObj] Remove usage of BOOST_FOREACH. (Internal change: 1665960) --- extras/usd/examples/usdObj/stream.cpp | 15 +++++++-------- extras/usd/examples/usdObj/streamIO.cpp | 1 - extras/usd/examples/usdObj/translator.cpp | 10 ++++------ 3 files changed, 11 insertions(+), 15 deletions(-) diff --git a/extras/usd/examples/usdObj/stream.cpp b/extras/usd/examples/usdObj/stream.cpp index 06150b6046..ae9f89ca0c 100644 --- a/extras/usd/examples/usdObj/stream.cpp +++ b/extras/usd/examples/usdObj/stream.cpp @@ -26,8 +26,6 @@ #include "pxr/base/tf/enum.h" #include "pxr/base/tf/registryManager.h" -#include - #include #include @@ -205,7 +203,7 @@ void UsdObjStream::AppendComments(std::string const &text) { vector lines = TfStringSplit(text, "\n"); - BOOST_FOREACH(string const &line, lines) { + for (const auto& line : lines) { _comments.push_back(_MakeComment(line)); } _AddSequence(SequenceElem::Comments, lines.size()); @@ -216,7 +214,7 @@ UsdObjStream::PrependComments(string const &text) { vector lines = TfStringSplit(text, "\n"); // Mutate all the lines into comments. - BOOST_FOREACH(string &line, lines) { + for (const auto& line : lines) { line = _MakeComment(line); } // Insert them at the beginning. @@ -234,7 +232,7 @@ void UsdObjStream::AppendArbitraryText(std::string const &text) { vector lines = TfStringSplit(text, "\n"); - BOOST_FOREACH(string const &line, lines) { + for (const auto& line : lines) { if (_IsComment(line)) { AppendComments(line); } else { @@ -248,7 +246,8 @@ void UsdObjStream::PrependArbitraryText(string const &text) { vector lines = TfStringSplit(text, "\n"); - BOOST_REVERSE_FOREACH(string const &line, lines) { + for (auto lineIter = lines.rbegin(); lineIter != lines.rend(); ++lineIter){ + const auto& line = *lineIter; if (_IsComment(line)) { PrependComments(line); } else { @@ -352,7 +351,7 @@ UsdObjStream::AddData(UsdObjStream const &other) vector const &points = other.GetPoints(); // Add elements from the other data in sequence. - BOOST_FOREACH(SequenceElem const &elem, other.GetSequence()) { + for (const auto& elem : other.GetSequence()) { switch (elem.type) { default: TF_CODING_ERROR("Unknown sequence element '%s', aborting", @@ -373,7 +372,7 @@ UsdObjStream::AddData(UsdObjStream const &other) case SequenceElem::Groups: for (int i = 0; i != elem.repeat; ++i, ++groupIter) { AddGroup(_GetUniqueGroupName(groupIter->name)); - BOOST_FOREACH(Face const &face, groupIter->faces) { + for (const auto& face : groupIter->faces) { for (int j = face.pointsBegin; j != face.pointsEnd; ++j) AddPoint(OffsetPoint(points[j], offset)); diff --git a/extras/usd/examples/usdObj/streamIO.cpp b/extras/usd/examples/usdObj/streamIO.cpp index 61fc146e93..fc0e0962d7 100644 --- a/extras/usd/examples/usdObj/streamIO.cpp +++ b/extras/usd/examples/usdObj/streamIO.cpp @@ -24,7 +24,6 @@ #include "streamIO.h" #include "stream.h" -#include #include #include diff --git a/extras/usd/examples/usdObj/translator.cpp b/extras/usd/examples/usdObj/translator.cpp index a83946846f..5148cf2f6b 100644 --- a/extras/usd/examples/usdObj/translator.cpp +++ b/extras/usd/examples/usdObj/translator.cpp @@ -32,8 +32,6 @@ #include "pxr/base/gf/range3f.h" -#include - SdfLayerRefPtr UsdObjTranslateObjToUsd(const UsdObjStream &objStream) { @@ -65,15 +63,15 @@ UsdObjTranslateObjToUsd(const UsdObjStream &objStream) // Usd currently requires an extent, somewhat unfortunately. GfRange3f extent; - BOOST_FOREACH(const GfVec3f &pt, usdPoints) + for (const auto& pt : usdPoints) { extent.UnionWith(pt); + } VtVec3fArray extentArray(2); extentArray[0] = extent.GetMin(); extentArray[1] = extent.GetMax(); // Make a poly mesh for each group in the obj. - BOOST_FOREACH(const UsdObjStream::Group &group, objStream.GetGroups()) { - + for (const auto& group : objStream.GetGroups()) { if (not TfIsValidIdentifier(group.name)) { TF_WARN("Omitting OBJ group with invalid name '%s'", group.name.c_str()); @@ -96,7 +94,7 @@ UsdObjTranslateObjToUsd(const UsdObjStream &objStream) mesh.GetPointsAttr().Set(usdPoints); VtArray faceVertexCounts, faceVertexIndices; - BOOST_FOREACH(const UsdObjStream::Face &face, group.faces) { + for (const auto& face : group.faces) { faceVertexCounts.push_back(face.size()); for (int p = face.pointsBegin; p != face.pointsEnd; ++p) { faceVertexIndices.push_back(objPoints[p].vertIndex); From 4e49052a74a414fa5b0935ea12be08f603a766ee Mon Sep 17 00:00:00 2001 From: superfunc Date: Tue, 25 Oct 2016 13:47:44 -0700 Subject: [PATCH 282/380] [UsdAbc] Remove usage of BOOST_FOREACH. (Internal change: 1665961) --- pxr/usd/plugin/usdAbc/alembicReader.cpp | 22 +++++------- pxr/usd/plugin/usdAbc/alembicTest.cpp | 11 +++--- pxr/usd/plugin/usdAbc/alembicUtil.cpp | 10 +++--- pxr/usd/plugin/usdAbc/alembicWriter.cpp | 46 +++++++++++-------------- 4 files changed, 38 insertions(+), 51 deletions(-) diff --git a/pxr/usd/plugin/usdAbc/alembicReader.cpp b/pxr/usd/plugin/usdAbc/alembicReader.cpp index 56ce1d0010..60d0db653a 100644 --- a/pxr/usd/plugin/usdAbc/alembicReader.cpp +++ b/pxr/usd/plugin/usdAbc/alembicReader.cpp @@ -34,7 +34,6 @@ #include "pxr/base/tf/staticTokens.h" #include "pxr/base/tf/ostreamMethods.h" #include -#include #include #include #include @@ -1175,7 +1174,7 @@ _ReaderContext::VisitSpecs( SdfAbstractDataSpecVisitor* visitor) const { // Visit prims in path sorted order. - BOOST_FOREACH(const _PrimMap::value_type& v, _prims) { + for (const auto& v : _prims) { // Visit the prim. const SdfPath& primPath = v.first; if (not visitor->VisitSpec(owner, SdfAbstractDataSpecId(&primPath))) { @@ -1185,8 +1184,7 @@ _ReaderContext::VisitSpecs( // Visit the prim's properties in lexicographical sorted order. const Prim& prim = v.second; if (&prim != _pseudoRoot) { - BOOST_FOREACH(const PropertyMap::value_type& w, - prim.propertiesCache) { + for (const auto& w : prim.propertiesCache) { if (not visitor->VisitSpec(owner, SdfAbstractDataSpecId(&primPath, &w.first))) { return; @@ -1217,8 +1215,7 @@ _ReaderContext::List(const SdfAbstractDataSpecId& id) const } // Add metadata. - BOOST_FOREACH(const MetadataMap::value_type& v, - property->metadata) { + for (const auto& v : property->metadata) { result.push_back(v.first); } } @@ -1251,7 +1248,7 @@ _ReaderContext::List(const SdfAbstractDataSpecId& id) const if (not prim->children.empty()) { result.push_back(SdfChildrenKeys->PrimChildren); } - BOOST_FOREACH(const MetadataMap::value_type& v, prim->metadata) { + for (const auto& v : prim->metadata) { result.push_back(v.first); } } @@ -2784,7 +2781,7 @@ _ReadOther(_PrimReaderContext* context) { // Read every unextracted property to Usd using default converters. // This handles any property we don't have specific rules for. - BOOST_FOREACH(const std::string& name, context->GetUnextractedNames()) { + for (const auto& name : context->GetUnextractedNames()) { context->AddOutOfSchemaProperty( context->GetUsdName(name), context->Extract(name)); } @@ -2797,8 +2794,7 @@ _ReadOtherSchema(_PrimReaderContext* context) { // Read every unextracted property to Usd using default converters. // This handles any property we don't have specific rules for. - BOOST_FOREACH(const std::string& name, - context->GetUnextractedSchemaNames()) { + for (const auto& name : context->GetUnextractedSchemaNames()) { context->AddOutOfSchemaProperty( context->GetUsdName(name), context->ExtractSchema(name)); } @@ -3440,8 +3436,7 @@ _ReadPrim( // changed path to point at the master. const SdfPath instancePath = parentPath.AppendChild(TfToken(name)); _PrimReaderContext primContext(context, object, instancePath); - BOOST_FOREACH(const _ReaderSchema::PrimReader& reader, - context.GetSchema().GetPrimReaders(schemaName)) { + for (const auto& reader : context.GetSchema().GetPrimReaders(schemaName)) { TRACE_SCOPE("UsdAbc_AlembicDataReader:_ReadPrim"); reader(&primContext); } @@ -3476,8 +3471,7 @@ _ReadPrim( if (path != SdfPath::AbsoluteRootPath()) { // Read the properties. _PrimReaderContext primContext(context, object, path); - BOOST_FOREACH(const _ReaderSchema::PrimReader& reader, - context.GetSchema().GetPrimReaders(schemaName)) { + for (const auto& reader : context.GetSchema().GetPrimReaders(schemaName)) { TRACE_SCOPE("UsdAbc_AlembicDataReader:_ReadPrim"); reader(&primContext); } diff --git a/pxr/usd/plugin/usdAbc/alembicTest.cpp b/pxr/usd/plugin/usdAbc/alembicTest.cpp index 2e712cb943..6b9088ef11 100644 --- a/pxr/usd/plugin/usdAbc/alembicTest.cpp +++ b/pxr/usd/plugin/usdAbc/alembicTest.cpp @@ -27,7 +27,6 @@ #include "pxr/usd/sdf/layer.h" #include "pxr/usd/sdf/schema.h" #include "pxr/base/tf/ostreamMethods.h" -#include #include #include @@ -67,7 +66,7 @@ class UsdAbc_SortedDataSpecVisitor : public SdfAbstractDataSpecVisitor { std::sort(_ids.begin(), _ids.end()); // Pass ids to the wrapped visitor. - BOOST_FOREACH(const _SpecId& id, _ids) { + for (const auto& id : _ids) { if (_Pass(data, id)) { if (not _visitor->VisitSpec(data, id)) { break; @@ -231,7 +230,7 @@ struct UsdAbc_AlembicWriteVisitor : public SdfAbstractDataSpecVisitor { fprintf(stdout, "%*s", 2*int(path.GetPathElementCount()-1), ""); fprintf(stdout, "samples_at=[ "); - BOOST_FOREACH(double t, times) { + for (double t : times) { fprintf(stdout, "%g ", t); } fprintf(stdout, "]\n"); @@ -251,7 +250,7 @@ struct UsdAbc_AlembicWriteVisitor : public SdfAbstractDataSpecVisitor { tokens.erase(SdfFieldKeys->Default); tokens.erase(SdfFieldKeys->TimeSamples); const SdfSchema& schema = SdfSchema::GetInstance(); - BOOST_FOREACH(const TfToken& field, tokens) { + for (const auto& field : tokens) { const VtValue value = data.Get(id, field); if (value != schema.GetFallback(field)) { fprintf(stdout, "%*s# %s = %s\n", @@ -295,7 +294,7 @@ struct UsdAbc_AlembicWriteVisitor : public SdfAbstractDataSpecVisitor { static void UsdAbc_PrintTimes(const char* msg, const std::set& times) { fprintf(stdout, "%s: [", msg); - BOOST_FOREACH(double t, times) { + for (double t : times) { fprintf(stdout, " %f", t); } fprintf(stdout, " ]\n"); @@ -345,7 +344,7 @@ UsdAbc_TestAlembic(const std::string& pathname) std::set times = data->ListTimeSamplesForPath(id); if (not times.empty()) { fprintf(stdout, "\nExtent samples:\n"); - BOOST_FOREACH(double t, times) { + for (double t : times) { VtValue value; if (data->QueryTimeSample(id, t, &value)) { fprintf(stdout, " %f: %s\n", diff --git a/pxr/usd/plugin/usdAbc/alembicUtil.cpp b/pxr/usd/plugin/usdAbc/alembicUtil.cpp index 95a4cd8c10..eff89786a0 100644 --- a/pxr/usd/plugin/usdAbc/alembicUtil.cpp +++ b/pxr/usd/plugin/usdAbc/alembicUtil.cpp @@ -28,8 +28,6 @@ #include #include -#include - TF_DEFINE_PUBLIC_TOKENS(UsdAbc_AlembicContextFlagNames, USDABC_ALEMBIC_CONTEXT_FLAG_NAMES); @@ -242,7 +240,7 @@ SdfValueTypeName UsdAbc_AlembicDataConversion::FindConverter( const UsdAbc_AlembicType& alembicType) const { - BOOST_FOREACH(const _ConverterData &c, _typeConverters) { + for (const auto& c : _typeConverters) { if (c.abcType == alembicType) { return c.usdType; } @@ -255,7 +253,7 @@ UsdAbc_AlembicDataConversion::GetToUsdConverter( const UsdAbc_AlembicType& alembicType, const SdfValueTypeName &usdType) const { - BOOST_FOREACH(const _ConverterData &c, _typeConverters) { + for (const auto& c : _typeConverters) { if (c.usdType == usdType and c.abcType == alembicType) { return c.toUsdFn; } @@ -268,7 +266,7 @@ UsdAbc_AlembicType UsdAbc_AlembicDataConversion::FindConverter( const SdfValueTypeName& usdType) const { - BOOST_FOREACH(const _ConverterData &c, _typeConverters) { + for (const auto& c : _typeConverters) { if (c.usdType == usdType) { return c.abcType; } @@ -280,7 +278,7 @@ const UsdAbc_AlembicDataConversion::FromUsdConverter& UsdAbc_AlembicDataConversion::GetConverter( const SdfValueTypeName& usdType) const { - BOOST_FOREACH(const _ConverterData &c, _typeConverters) { + for (const auto& c : _typeConverters) { if (c.usdType == usdType) { return c.fromUsdFn; } diff --git a/pxr/usd/plugin/usdAbc/alembicWriter.cpp b/pxr/usd/plugin/usdAbc/alembicWriter.cpp index 8691f2e0cc..9589edeb25 100644 --- a/pxr/usd/plugin/usdAbc/alembicWriter.cpp +++ b/pxr/usd/plugin/usdAbc/alembicWriter.cpp @@ -41,7 +41,6 @@ #include #include #include -#include #include #include #include @@ -230,7 +229,7 @@ UsdSamples::_Validate() const TfType backupType = (type == TfType::Find()) ? TfType::Find() : type; restart: - BOOST_FOREACH(const SdfTimeSampleMap::value_type& v, *_samples) { + for (const auto& v : *_samples) { if (v.second.GetType() != type) { if (not TF_VERIFY(v.second.GetType() == backupType, "Expected sample at <%s> time %f of type '%s', " @@ -321,7 +320,7 @@ UsdSamples::Get(double time) const void UsdSamples::AddTimes(UsdAbc_TimeSamples* times) const { - BOOST_FOREACH(const SdfTimeSampleMap::value_type& v, *_samples) { + for (const auto& v : *_samples) { times->insert(v.first); } } @@ -745,7 +744,7 @@ _WriterContext::AddTimeSampling(const UsdAbc_TimeSamples& inSamples) // Scale and offset samples. UsdAbc_TimeSamples samples; - BOOST_FOREACH(double time, inSamples) { + for (double time : inSamples) { samples.insert((time - _timeOffset) / _timeScale); } @@ -1110,8 +1109,7 @@ _ReverseWindingOrder(UsdSamples* valuesMap, const UsdSamples& countsMap) typedef VtArray CountArray; SdfTimeSampleMap result; - BOOST_FOREACH(const SdfTimeSampleMap::value_type& v, - valuesMap->GetSamples()) { + for (const auto& v : valuesMap->GetSamples()) { const VtValue& valuesValue = v.second; const VtValue& countsValue = countsMap.Get(v.first); if (not TF_VERIFY(valuesValue.IsHolding())) { @@ -2057,7 +2055,7 @@ _WriteOutOfSchemaProperty( context->GetSchema().GetDataType(samples), _GetPropertyMetadata(*context, usdName, samples)); - BOOST_FOREACH(double time, context->GetSampleTimesUnion()) { + for (double time : context->GetSampleTimesUnion()) { _Copy(context->GetSchema(), converter, time, samples,&property); } property.setTimeSampling( @@ -2068,7 +2066,7 @@ _WriteOutOfSchemaProperty( context->GetSchema().GetDataType(samples), _GetPropertyMetadata(*context, usdName, samples)); - BOOST_FOREACH(double time, context->GetSampleTimesUnion()) { + for (double time : context->GetSampleTimesUnion()) { _Copy(context->GetSchema(), converter, time, samples,&property); } property.setTimeSampling( @@ -2098,7 +2096,7 @@ _WriteGenericProperty( if (context->GetSchema().IsValid(samples)) { T property(parent, alembicName, alembicDataType, _GetPropertyMetadata(*context, usdName, samples)); - BOOST_FOREACH(double time, context->GetSampleTimesUnion()) { + for (double time : context->GetSampleTimesUnion()) { _Copy(context->GetSchema(), converter, time, samples, &property); } property.setTimeSampling( @@ -2200,7 +2198,7 @@ _WriteNamespacedPropertyGroup( // however, that we don't confirm that conversion will succeed so // we may still create the property with nothing in it. bool anyProperties = false; - BOOST_FOREACH(const TfToken& name, context->GetUnextractedNames()) { + for (const auto& name : context->GetUnextractedNames()) { TfTokenVector names = SdfPath::TokenizeIdentifierAsTokens(name); if (names.size() >= 2 and names[0] == namespaceName) { anyProperties = true; @@ -2222,7 +2220,7 @@ _WriteNamespacedPropertyGroup( _CompoundPropertyTable subgroups(parent); // Convert each property. - BOOST_FOREACH(const TfToken& name, context->GetUnextractedNames()) { + for (const auto& name : context->GetUnextractedNames()) { TfTokenVector names = SdfPath::TokenizeIdentifierAsTokens(name); if (names.size() >= 2 and names[0] == namespaceName) { // Remove the namespace prefix. @@ -2313,7 +2311,7 @@ _WriteMayaColor(_PrimWriterContext* context) name, DataType(kFloat32POD, 4), metadata); - BOOST_FOREACH(double time, sampleTimes) { + for (double time : sampleTimes) { _Copy(context->GetSchema(), _CopyAdskColor, time, color,&property); } property.setTimeSampling(context->AddTimeSampling(sampleTimes)); @@ -2347,7 +2345,7 @@ _WriteOther(_PrimWriterContext* context) // Usd name with namespaces is written to Alembic with the namespaces // embedded in the name. // - BOOST_FOREACH(const TfToken& name, context->GetUnextractedNames()) { + for (const auto& name : context->GetUnextractedNames()) { _WriteOutOfSchemaProperty(context, context->GetParent().GetProperties(), name, context->GetAlembicPropertyName(name)); @@ -2483,7 +2481,7 @@ _WriteCameraParameters(_PrimWriterContext* context) // Copy all the samples to set up alembic camera frustum. typedef CameraSample SampleT; - BOOST_FOREACH(double time, context->GetSampleTimesUnion()) { + for (double time : context->GetSampleTimesUnion()) { // Build the sample. SampleT sample; @@ -2626,7 +2624,7 @@ _WriteXform(_PrimWriterContext* context) // At this point, all transform related attributes (including all xformOps) // should have been extracted. Validate here to make sure there aren't // any unextracted xformOp attributes. - BOOST_FOREACH(const TfToken& name, context->GetUnextractedNames()) { + for (const auto& name : context->GetUnextractedNames()) { if (UsdGeomXformOp::IsXformOp(name)) { TF_RUNTIME_ERROR("Found unextracted property '%s' in xformOp " "namespace.", name.GetText()); @@ -2661,7 +2659,7 @@ _WriteXform(_PrimWriterContext* context) // Copy all the samples. typedef XformSample SampleT; SampleT sample; - BOOST_FOREACH(double time, context->GetSampleTimesUnion()) { + for (double time : context->GetSampleTimesUnion()) { // Build the sample. sample.reset(); _CopyXform(time, transform, &sample); @@ -2731,7 +2729,7 @@ _WritePolyMesh(_PrimWriterContext* context) // Copy all the samples. typedef Type::schema_type::Sample SampleT; SampleT sample; - BOOST_FOREACH(double time, context->GetSampleTimesUnion()) { + for (double time : context->GetSampleTimesUnion()) { // Build the sample. sample.reset(); _CopySelfBounds(time, extent, &sample); @@ -2852,7 +2850,7 @@ _WriteSubD(_PrimWriterContext* context) typedef Type::schema_type::Sample SampleT; MySampleT mySample; SampleT& sample = mySample; - BOOST_FOREACH(double time, context->GetSampleTimesUnion()) { + for (double time : context->GetSampleTimesUnion()) { // Build the sample. Usd defaults faceVaryingLinearInterpolation to // edgeAndCorner but Alembic defaults to bilinear so set that first // in case we have no opinion. @@ -2969,7 +2967,7 @@ _WriteNurbsCurves(_PrimWriterContext* context) // Copy all the samples. typedef Type::schema_type::Sample SampleT; SampleT sample; - BOOST_FOREACH(double time, context->GetSampleTimesUnion()) { + for (double time : context->GetSampleTimesUnion()) { // Build the sample. sample.reset(); _CopySelfBounds(time, extent, &sample); @@ -3063,7 +3061,7 @@ _WriteBasisCurves(_PrimWriterContext* context) // Copy all the samples. typedef Type::schema_type::Sample SampleT; SampleT sample; - BOOST_FOREACH(double time, context->GetSampleTimesUnion()) { + for (double time : context->GetSampleTimesUnion()) { // Build the sample. sample.reset(); _CopySelfBounds(time, extent, &sample); @@ -3145,7 +3143,7 @@ _WritePoints(_PrimWriterContext* context) typedef Type::schema_type::Sample SampleT; SampleT sample; bool first = true; - BOOST_FOREACH(double time, context->GetSampleTimesUnion()) { + for (double time : context->GetSampleTimesUnion()) { // Build the sample. sample.reset(); _CopySelfBounds(time, extent, &sample); @@ -3233,8 +3231,7 @@ _WritePrim( // Write the properties. _PrimWriterContext primContext(context, parent, id); - BOOST_FOREACH(const _WriterSchema::PrimWriter& writer, - context.GetSchema().GetPrimWriters(typeName)) { + for (const auto& writer : context.GetSchema().GetPrimWriters(typeName)) { TRACE_SCOPE("UsdAbc_AlembicDataWriter:_WritePrim"); writer(&primContext); } @@ -3245,8 +3242,7 @@ _WritePrim( const VtValue childrenNames = context.GetData().Get(id, SdfChildrenKeys->PrimChildren); if (childrenNames.IsHolding()) { - BOOST_FOREACH(const TfToken& childName, - childrenNames.UncheckedGet()) { + for (const auto& childName : childrenNames.UncheckedGet()) { _WritePrim(context, prim, path.AppendChild(childName)); } } From e95783b69ef1fd3377bfe3409508e3da74f01920 Mon Sep 17 00:00:00 2001 From: superfunc Date: Tue, 25 Oct 2016 13:47:48 -0700 Subject: [PATCH 283/380] [Glf] Remove usage of BOOST_FOREACH. (Internal change: 1665962) --- pxr/imaging/lib/glf/dictionary.cpp | 4 +--- pxr/imaging/lib/glf/glContextRegistry.cpp | 5 ++--- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/pxr/imaging/lib/glf/dictionary.cpp b/pxr/imaging/lib/glf/dictionary.cpp index e68153385e..cdacb8402f 100644 --- a/pxr/imaging/lib/glf/dictionary.cpp +++ b/pxr/imaging/lib/glf/dictionary.cpp @@ -26,8 +26,6 @@ #include "pxr/base/tf/debug.h" #include "pxr/base/vt/dictionary.h" -#include - using namespace std; @@ -66,7 +64,7 @@ _Glf_GetDictionaryFromJSON( // XXX: This may not be worth the cost. // std::vector filtered = TfStringSplit(input, "\n"); - BOOST_FOREACH(std::string &line, filtered) { + for (auto & line : filtered) { // Clear comment lines but keep them to maintain line numbers for errors if (line.find('#') < line.find_first_not_of(" \t#")) line.clear(); diff --git a/pxr/imaging/lib/glf/glContextRegistry.cpp b/pxr/imaging/lib/glf/glContextRegistry.cpp index 9469f0386f..586d71a3c5 100644 --- a/pxr/imaging/lib/glf/glContextRegistry.cpp +++ b/pxr/imaging/lib/glf/glContextRegistry.cpp @@ -28,7 +28,6 @@ #include "pxr/imaging/garch/glPlatformContext.h" #include "pxr/base/tf/diagnostic.h" #include "pxr/base/tf/instantiateSingleton.h" -#include #include #include #include @@ -95,7 +94,7 @@ GlfGLContextRegistry::GetShared() _shared = GlfGLContextSharedPtr(); // Find the first interface with a shared context. - BOOST_FOREACH(GlfGLContextRegistrationInterface& iface, _interfaces) { + for (auto& iface : _interfaces) { if (GlfGLContextSharedPtr shared = iface.GetShared()) { _shared = shared; return _shared.get(); @@ -123,7 +122,7 @@ GlfGLContextRegistry::GetCurrent() // We don't know this raw state. Try syncing each interface to see // if any system thinks this state is current. - BOOST_FOREACH(GlfGLContextRegistrationInterface& iface, _interfaces) { + for (auto& iface : _interfaces) { if (GlfGLContextSharedPtr currentContext = iface.GetCurrent()) { if (currentContext->IsValid()) { GlfGLContext::MakeCurrent(currentContext); From 7eb4ee7bb9fcfd313d9f0d6da49ebd99d28305a2 Mon Sep 17 00:00:00 2001 From: superfunc Date: Tue, 25 Oct 2016 13:47:51 -0700 Subject: [PATCH 284/380] [Ar] Remove BOOST_FOREACH usage. (Internal change: 1665963) --- pxr/usd/lib/ar/defaultResolver.cpp | 6 ++---- pxr/usd/lib/ar/resolver.cpp | 3 +-- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/pxr/usd/lib/ar/defaultResolver.cpp b/pxr/usd/lib/ar/defaultResolver.cpp index b2438ff17b..73760b859b 100644 --- a/pxr/usd/lib/ar/defaultResolver.cpp +++ b/pxr/usd/lib/ar/defaultResolver.cpp @@ -35,8 +35,6 @@ #include -#include - static bool _IsFileRelative(const std::string& path) { return path.find("./") == 0 or path.find("../") == 0; @@ -56,7 +54,7 @@ Ar_DefaultResolver::Ar_DefaultResolver() const std::string envPath = TfGetenv("PXR_AR_DEFAULT_SEARCH_PATH"); if (not envPath.empty()) { - BOOST_FOREACH(const std::string& p, TfStringTokenize(envPath, ":")) { + for (const auto& p : TfStringTokenize(envPath, ":")) { _searchPath.push_back(TfAbsPath(p)); } } @@ -163,7 +161,7 @@ Ar_DefaultResolver::_ResolveNoCache(const std::string& path) // If that fails and the path is a search path, try to resolve // against each directory in the specified search paths. if (IsSearchPath(path)) { - BOOST_FOREACH(const std::string& searchPath, _searchPath) { + for (const auto& searchPath : _searchPath) { resolvedPath = _Resolve(searchPath, path); if (not resolvedPath.empty()) { return resolvedPath; diff --git a/pxr/usd/lib/ar/resolver.cpp b/pxr/usd/lib/ar/resolver.cpp index 07805f32ab..7863dfb873 100644 --- a/pxr/usd/lib/ar/resolver.cpp +++ b/pxr/usd/lib/ar/resolver.cpp @@ -41,7 +41,6 @@ #include "pxr/base/tf/stringUtils.h" #include "pxr/base/tf/type.h" -#include #include #include #include @@ -72,7 +71,7 @@ _GetTypeNames(const std::set& types) { std::vector typeNames; typeNames.reserve(types.size()); - BOOST_FOREACH(const TfType& type, types) { + for (const auto& type : types) { typeNames.push_back(type.GetTypeName()); } return TfStringJoin(typeNames); From 4638eef28e42b302a081fbee13e8be7acd5c4cbe Mon Sep 17 00:00:00 2001 From: superfunc Date: Tue, 25 Oct 2016 13:47:57 -0700 Subject: [PATCH 285/380] [UsdGeom] Remove BOOST_FOREACH usage. (Internal change: 1665964) --- pxr/usd/lib/usdGeom/bboxCache.cpp | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/pxr/usd/lib/usdGeom/bboxCache.cpp b/pxr/usd/lib/usdGeom/bboxCache.cpp index 346d0367c9..c701d3acc2 100644 --- a/pxr/usd/lib/usdGeom/bboxCache.cpp +++ b/pxr/usd/lib/usdGeom/bboxCache.cpp @@ -41,7 +41,6 @@ #include #include -#include #include // Thread-local Xform cache. @@ -115,7 +114,7 @@ class UsdGeomBBoxCache::_MasterBBoxResolver TRACE_FUNCTION(); _MasterTaskMap masterTasks; - BOOST_FOREACH(const UsdPrim& masterPrim, masterPrims) { + for (const auto& masterPrim : masterPrims) { _PopulateTasksForMaster(masterPrim, &masterTasks); } @@ -125,7 +124,7 @@ class UsdGeomBBoxCache::_MasterBBoxResolver _ThreadXformCache xfCache; WorkDispatcher dispatcher; - BOOST_FOREACH(const _MasterTaskMap::value_type& t, masterTasks) { + for (const auto& t : masterTasks) { if (t.second.numDependencies == 0) { dispatcher.Run( &_MasterBBoxResolver::_ExecuteTaskForMaster, @@ -156,7 +155,7 @@ class UsdGeomBBoxCache::_MasterBBoxResolver // Recursively populate the task map for the masters needed for // nested instances. - BOOST_FOREACH(const UsdPrim& reqMaster, requiredMasters) { + for (const auto& reqMaster : requiredMasters) { _PopulateTasksForMaster(reqMaster, masterTasks); (*masterTasks)[reqMaster].dependentMasters.push_back(masterPrim); } @@ -177,8 +176,7 @@ class UsdGeomBBoxCache::_MasterBBoxResolver // resolved. We're guaranteed that all the entries were populated by // _PopulateTasksForMaster, so we don't check the result of 'find()'. const _MasterTask& masterData = masterTasks->find(master)->second; - BOOST_FOREACH(const UsdPrim& dependentMaster, - masterData.dependentMasters) { + for (const auto& dependentMaster : masterData.dependentMasters) { _MasterTask& dependentMasterData = masterTasks->find(dependentMaster)->second; if (dependentMasterData.numDependencies.fetch_and_decrement() == 1){ From 6834d6fc586751e0bfeacb9c6ba0ff607ed9186f Mon Sep 17 00:00:00 2001 From: superfunc Date: Tue, 25 Oct 2016 13:48:01 -0700 Subject: [PATCH 286/380] [UsdUtils] Remove BOOST_FOREACH usage. (Internal change: 1665965) --- pxr/usd/lib/usdUtils/stitch.cpp | 29 +++++++++------------------- pxr/usd/lib/usdUtils/stitchClips.cpp | 2 -- 2 files changed, 9 insertions(+), 22 deletions(-) diff --git a/pxr/usd/lib/usdUtils/stitch.cpp b/pxr/usd/lib/usdUtils/stitch.cpp index db7cb2897d..5330a0d999 100644 --- a/pxr/usd/lib/usdUtils/stitch.cpp +++ b/pxr/usd/lib/usdUtils/stitch.cpp @@ -35,8 +35,6 @@ #include "pxr/base/tf/warning.h" #include "pxr/base/tf/token.h" -#include - #include #include #include @@ -195,8 +193,7 @@ namespace { const SdfPrimSpecHandle& weakPrim, bool ignoreTimeSamples) { - BOOST_FOREACH(SdfPrimSpecHandle const& weakPrimIter, - weakPrim->GetNameChildren()) { + for (const auto& weakPrimIter : weakPrim->GetNameChildren()) { // lookup prim in strong layer SdfPrimSpecHandle strongPrimHandle = strongPrim->GetPrimAtPath(weakPrimIter->GetPath()); @@ -232,9 +229,7 @@ namespace { const SdfPrimSpecHandle& weakPrim, bool ignoreTimeSamples) { - BOOST_FOREACH(SdfAttributeSpecHandle const& childAttribute, - weakPrim->GetAttributes()) { - + for (const auto& childAttribute : weakPrim->GetAttributes()) { SdfPath pathToChildAttr = childAttribute->GetPath(); SdfAttributeSpecHandle strongAttrHandle = strongPrim->GetAttributeAtPath(pathToChildAttr); @@ -257,9 +252,8 @@ namespace { // time samples needs special attention, we can't simply // call UsdUtilsStitchInfo(), because both attributes will // have the key 'timeSamples', and we must do an inner compare - BOOST_FOREACH(const double timeSamplePoint, - weakParent - ->ListTimeSamplesForPath(currAttrPath)) { + for (const double timeSamplePoint + : weakParent->ListTimeSamplesForPath(currAttrPath)) { // if the parent doesn't contain the time // sample point key in its dict if (not strongParent->QueryTimeSample(pathToChildAttr, @@ -283,9 +277,7 @@ namespace { const SdfPrimSpecHandle& weakPrim, bool ignoreTimeSamples) { - BOOST_FOREACH(SdfRelationshipSpecHandle const& childRelationship, - weakPrim->GetRelationships()) { - + for (const auto& childRelationship : weakPrim->GetRelationships()) { SdfPath pathToChildRel = childRelationship->GetPath(); SdfRelationshipSpecHandle strongRelHandle = strongPrim->GetRelationshipAtPath(pathToChildRel); @@ -326,20 +318,17 @@ namespace { UsdUtilsStitchInfo(newPrim, primToCopy, ignoreTimeSamples); // copy child prims - BOOST_FOREACH(SdfPrimSpecHandle const& childPrim, - primToCopy->GetNameChildren()) { + for (const auto& childPrim : primToCopy->GetNameChildren()) { _MakePrimCopy(newPrim, childPrim, ignoreTimeSamples); } // copy child attributes - BOOST_FOREACH(SdfAttributeSpecHandle const& childAttribute, - primToCopy->GetAttributes()) { + for (const auto& childAttribute : primToCopy->GetAttributes()) { _MakeAttributeCopy(newPrim, childAttribute, ignoreTimeSamples); } // copy child relationships - BOOST_FOREACH(SdfRelationshipSpecHandle const& childRelationship, - primToCopy->GetRelationships()) { + for (const auto& childRelationship : primToCopy->GetRelationships()) { _MakeRelationshipCopy(newPrim, childRelationship,ignoreTimeSamples); } } @@ -435,7 +424,7 @@ UsdUtilsStitchInfo(const SdfSpecHandle& strongObj, const SdfSpecHandle& weakObj, bool ignoreTimeSamples) { - BOOST_FOREACH(TfToken const& key, _ObtainRelevantKeysToStitch(weakObj)) { + for (const auto& key : _ObtainRelevantKeysToStitch(weakObj)) { const VtValue strongValue = strongObj->GetSchema().GetFallback(key); // if we have a dictionary type, we need to do a merge diff --git a/pxr/usd/lib/usdUtils/stitchClips.cpp b/pxr/usd/lib/usdUtils/stitchClips.cpp index 72da11ba4b..e682f7be08 100644 --- a/pxr/usd/lib/usdUtils/stitchClips.cpp +++ b/pxr/usd/lib/usdUtils/stitchClips.cpp @@ -47,8 +47,6 @@ #include -#include - #include #include #include From e1cc9bd038640e008805e30914568a77889534b0 Mon Sep 17 00:00:00 2001 From: superfunc Date: Tue, 25 Oct 2016 13:48:05 -0700 Subject: [PATCH 287/380] [UsdShade] Remove usage of BOOST_FOREACH. (Internal change: 1665966) --- pxr/usd/lib/usdShade/parameter.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/pxr/usd/lib/usdShade/parameter.cpp b/pxr/usd/lib/usdShade/parameter.cpp index ef96cb8a1f..19e47684a2 100644 --- a/pxr/usd/lib/usdShade/parameter.cpp +++ b/pxr/usd/lib/usdShade/parameter.cpp @@ -29,7 +29,6 @@ #include #include -#include #include "pxr/base/tf/envSetting.h" @@ -361,7 +360,7 @@ UsdShadeParameter::ClearSources() const success = rel.ClearTargets(/* removeSpec = */ true); } - BOOST_FOREACH(UsdRelationship elt, _GetElementConnections(_attr)){ + for (auto elt : _GetElementConnections(_attr)) { success = elt.ClearTargets(/* removeSpec = */ true) and success; } From ec8763ffd81bfea56e15c50fddd458df50c3b731 Mon Sep 17 00:00:00 2001 From: superfunc Date: Tue, 25 Oct 2016 13:48:09 -0700 Subject: [PATCH 288/380] [Sdf] Remove usage of BOOST_FOREACH. (Internal change: 1665967) --- pxr/usd/lib/sdf/abstractData.cpp | 2 -- pxr/usd/lib/sdf/fileFormatRegistry.cpp | 5 ++--- pxr/usd/lib/sdf/layer.cpp | 3 +-- pxr/usd/lib/sdf/namespaceEdit.cpp | 17 ++++++++--------- pxr/usd/lib/sdf/parserHelpers.cpp | 4 +--- pxr/usd/lib/sdf/specType.cpp | 3 +-- pxr/usd/lib/sdf/textReferenceParser.cpp | 4 ++-- pxr/usd/lib/sdf/types.cpp | 1 - pxr/usd/lib/sdf/valueTypeName.cpp | 3 +-- pxr/usd/lib/sdf/wrapNamespaceEdit.cpp | 3 +-- 10 files changed, 17 insertions(+), 28 deletions(-) diff --git a/pxr/usd/lib/sdf/abstractData.cpp b/pxr/usd/lib/sdf/abstractData.cpp index dbdae4f609..cdbfabc151 100644 --- a/pxr/usd/lib/sdf/abstractData.cpp +++ b/pxr/usd/lib/sdf/abstractData.cpp @@ -24,8 +24,6 @@ #include "pxr/usd/sdf/abstractData.h" #include "pxr/base/tracelite/trace.h" -#include - #include #include #include diff --git a/pxr/usd/lib/sdf/fileFormatRegistry.cpp b/pxr/usd/lib/sdf/fileFormatRegistry.cpp index 36acac8528..2e19ab7016 100644 --- a/pxr/usd/lib/sdf/fileFormatRegistry.cpp +++ b/pxr/usd/lib/sdf/fileFormatRegistry.cpp @@ -35,7 +35,6 @@ #include "pxr/base/tf/iterator.h" #include "pxr/base/tf/scopeDescription.h" #include "pxr/base/tf/staticTokens.h" -#include using std::string; using std::vector; @@ -176,7 +175,7 @@ Sdf_FileFormatRegistry::_RegisterFormatPlugins() if (TF_VERIFY(not formatBaseType.IsUnknown())) PlugRegistry::GetAllDerivedTypes(formatBaseType, &formatTypes); - BOOST_FOREACH(TfType formatType, formatTypes) { + for (auto formatType : formatTypes) { TF_DEBUG(SDF_FILE_FORMAT).Msg("_RegisterFormatPlugins: " "Type '%s'\n", formatType.GetTypeName().c_str()); @@ -301,7 +300,7 @@ Sdf_FileFormatRegistry::_RegisterFormatPlugins() // Record the extensions that this file format plugin can handle. // Note that an extension may be supported by multiple file format // plugins. - BOOST_FOREACH(string ext, extensions) { + for (auto ext : extensions) { if (ext.empty()) continue; diff --git a/pxr/usd/lib/sdf/layer.cpp b/pxr/usd/lib/sdf/layer.cpp index f5e844e240..ed81c85e31 100644 --- a/pxr/usd/lib/sdf/layer.cpp +++ b/pxr/usd/lib/sdf/layer.cpp @@ -63,7 +63,6 @@ #include "pxr/base/tf/stackTrace.h" #include -#include #include #include @@ -1936,7 +1935,7 @@ SdfLayer::Apply(const SdfBatchNamespaceEdit& edits) } SdfChangeBlock block; - BOOST_FOREACH(const SdfNamespaceEdit& edit, final) { + for (const auto& edit : final) { _DoEdit(self, edit); } diff --git a/pxr/usd/lib/sdf/namespaceEdit.cpp b/pxr/usd/lib/sdf/namespaceEdit.cpp index d47f962519..51daef1011 100644 --- a/pxr/usd/lib/sdf/namespaceEdit.cpp +++ b/pxr/usd/lib/sdf/namespaceEdit.cpp @@ -29,7 +29,6 @@ #include "pxr/base/tf/enum.h" #include "pxr/base/tf/registryManager.h" #include "pxr/base/tf/stringUtils.h" -#include #include #include #include @@ -427,7 +426,7 @@ SdfNamespaceEdit_Namespace::_UneditPath(const SdfPath& path) const { // Walk down to node. const _Node* node = &_root; - BOOST_FOREACH(const SdfPath& prefix, path.GetPrefixes()) { + for (const auto& prefix : path.GetPrefixes()) { const _Node* child = node->GetChild(prefix); if (not child) { return path.ReplacePrefix(prefix.GetParentPath(), @@ -443,7 +442,7 @@ SdfNamespaceEdit_Namespace::_GetNodeAtPath(const SdfPath& path) { // Walk down to node. _Node* node = &_root; - BOOST_FOREACH(const SdfPath& prefix, path.GetPrefixes()) { + for (const auto& prefix : path.GetPrefixes()) { node = node->GetChild(prefix); if (not node) { break; @@ -463,7 +462,7 @@ SdfNamespaceEdit_Namespace::_FindOrCreateNodeAtPath(const SdfPath& path) // Walk down to node. bool created; _Node* node = &_root; - BOOST_FOREACH(const SdfPath& prefix, path.GetPrefixes()) { + for (const auto& prefix : path.GetPrefixes()) { if (prefix.IsTargetPath()) { const SdfPath& target = prefix.GetTargetPath(); SdfPath originalTarget = _UneditPath(target); @@ -560,7 +559,7 @@ SdfNamespaceEdit_Namespace::_FixBackpointers( // Fix keys. static const bool fixTargetPaths = true; for (_BackpointerMap::iterator j = i; j != n; ++j) { - BOOST_FOREACH(_Node* node, j->second) { + for (auto node : j->second) { node->SetKey( boost::get(node->GetKey()). ReplacePrefix(currentPath, newPath, not fixTargetPaths)); @@ -579,7 +578,7 @@ SdfNamespaceEdit_Namespace::_FixBackpointers( if (TF_VERIFY(i == _nodesWithPath.end() or not i->first.HasPrefix(currentPath), "Found backpointers under new path")) { - BOOST_FOREACH(_BackpointerMap::value_type& v, tmp) { + for (auto& v : tmp) { _nodesWithPath[v.first.ReplacePrefix(currentPath, newPath)]. swap(v.second); } @@ -781,7 +780,7 @@ SdfBatchNamespaceEdit::Process( SdfNamespaceEdit_Namespace ns(fixBackpointers); // Try each edit in sequence. - BOOST_FOREACH(const SdfNamespaceEdit& edit, GetEdits()) { + for (const auto& edit : GetEdits()) { // Make sure paths are compatible. bool mismatch = false; if (edit.currentPath.IsPrimPath()) { @@ -928,7 +927,7 @@ SdfBatchNamespaceEdit::Process( SdfPathVector targetPaths; edit.currentPath.GetAllTargetPathsRecursively(&targetPaths); - BOOST_FOREACH(const SdfPath& targetPath, targetPaths) { + for (const auto& targetPath : targetPaths) { SdfPath originalPath = ns.GetOriginalPath(targetPath); if (not originalPath.IsEmpty() and originalPath != targetPath) { if (details) { @@ -942,7 +941,7 @@ SdfBatchNamespaceEdit::Process( } edit.newPath.GetAllTargetPathsRecursively(&targetPaths); - BOOST_FOREACH(const SdfPath& targetPath, targetPaths) { + for (const auto& targetPath : targetPaths) { SdfPath originalPath = ns.GetOriginalPath(targetPath); if (not originalPath.IsEmpty() and originalPath != targetPath) { if (details) { diff --git a/pxr/usd/lib/sdf/parserHelpers.cpp b/pxr/usd/lib/sdf/parserHelpers.cpp index 04c575e702..260a205cac 100644 --- a/pxr/usd/lib/sdf/parserHelpers.cpp +++ b/pxr/usd/lib/sdf/parserHelpers.cpp @@ -52,7 +52,6 @@ #include #include #include -#include #include #include @@ -380,8 +379,7 @@ TF_MAKE_STATIC_DATA(_ValueFactoryMap, _valueFactories) { // appropriate C++ type (which mostly involves moving the // MakeScalarValueImpl functions into the value type name // registration code). Then we could do this: - // BOOST_FOREACH(const SdfValueTypeName& typeName, - // SdfSchema::GetInstance().GetAllTypes()) { + // for (const auto& typeName : SdfSchema::GetInstance().GetAllTypes()) { // builder(typeName); // } // For symmetry (and I think it would actually be useful diff --git a/pxr/usd/lib/sdf/specType.cpp b/pxr/usd/lib/sdf/specType.cpp index a6113d637b..bcdf0a2925 100644 --- a/pxr/usd/lib/sdf/specType.cpp +++ b/pxr/usd/lib/sdf/specType.cpp @@ -37,7 +37,6 @@ #include "pxr/base/tf/stl.h" #include "pxr/base/tf/type.h" -#include #include "pxr/base/tf/hashmap.h" #include @@ -122,7 +121,7 @@ struct Sdf_SpecTypeInfo // specTypeInfoToTfType cache first to avoid hitting the TfType lock. inline TfType TfTypeFind(const std::type_info &specCPPtype) const { typedef pair Pair; - BOOST_FOREACH(const Pair &p, specTypeInfoToTfType) { + for (const auto& p : specTypeInfoToTfType) { if (p.first == &specCPPtype) return p.second; } diff --git a/pxr/usd/lib/sdf/textReferenceParser.cpp b/pxr/usd/lib/sdf/textReferenceParser.cpp index 124a675583..083df636bc 100644 --- a/pxr/usd/lib/sdf/textReferenceParser.cpp +++ b/pxr/usd/lib/sdf/textReferenceParser.cpp @@ -27,7 +27,6 @@ #include "pxr/base/tf/staticTokens.h" #include "pxr/base/tracelite/trace.h" -#include #include #include #include @@ -76,7 +75,8 @@ Sdf_ParseExternalReferences( // Matches a reference, with optional label/revision specifier. boost::regex assetRef("@([^@]+(?:[@#][^@,]+)?)?@"); - BOOST_FOREACH(const string& line, boost::make_iterator_range(begin, end)) { + for (auto lineIter = begin; lineIter != end; ++lineIter) { + const string& line = *lineIter; // Look for an approximation of the most common kinds of comments, and // skip lines that match. This doesn't handle SLASHTERIX style // comments, and may also incorrectly identify lines as comments, diff --git a/pxr/usd/lib/sdf/types.cpp b/pxr/usd/lib/sdf/types.cpp index eb9781719b..9eb4e20adb 100644 --- a/pxr/usd/lib/sdf/types.cpp +++ b/pxr/usd/lib/sdf/types.cpp @@ -37,7 +37,6 @@ #include "pxr/base/tf/registryManager.h" #include "pxr/base/tf/staticData.h" #include "pxr/base/tf/type.h" -#include #include using std::map; diff --git a/pxr/usd/lib/sdf/valueTypeName.cpp b/pxr/usd/lib/sdf/valueTypeName.cpp index 3756d8ef7a..ef334302d2 100644 --- a/pxr/usd/lib/sdf/valueTypeName.cpp +++ b/pxr/usd/lib/sdf/valueTypeName.cpp @@ -23,7 +23,6 @@ // #include "pxr/usd/sdf/valueTypeName.h" #include "pxr/usd/sdf/valueTypePrivate.h" -#include #include #include @@ -33,7 +32,7 @@ template bool IsValueIn(const C& container, V value) { - BOOST_FOREACH(const V& element, container) { + for (const auto& element : container) { if (element == value) { return true; } diff --git a/pxr/usd/lib/sdf/wrapNamespaceEdit.cpp b/pxr/usd/lib/sdf/wrapNamespaceEdit.cpp index 79b57db82b..413768be86 100644 --- a/pxr/usd/lib/sdf/wrapNamespaceEdit.cpp +++ b/pxr/usd/lib/sdf/wrapNamespaceEdit.cpp @@ -26,7 +26,6 @@ #include "pxr/base/tf/pyCall.h" #include "pxr/base/tf/pyContainerConversions.h" #include "pxr/base/tf/pyEnum.h" -#include #include #include #include @@ -89,7 +88,7 @@ std::string _StringifyBatchEdit(const SdfBatchNamespaceEdit& x) { std::vector edits; - BOOST_FOREACH(const SdfNamespaceEdit& edit, x.GetEdits()) { + for (const auto& edit : x.GetEdits()) { edits.push_back(_StringifyEdit(edit)); } if (edits.empty()) { From 9569c2ea156c40a06984aebe363a41aef80d20cc Mon Sep 17 00:00:00 2001 From: superfunc Date: Tue, 25 Oct 2016 13:48:16 -0700 Subject: [PATCH 289/380] [Vt] Remove usage of BOOST_FOREACH. (Internal change: 1665968) --- pxr/base/lib/vt/types.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/pxr/base/lib/vt/types.cpp b/pxr/base/lib/vt/types.cpp index 1733ebcb38..15ec47ca6f 100644 --- a/pxr/base/lib/vt/types.cpp +++ b/pxr/base/lib/vt/types.cpp @@ -33,7 +33,6 @@ #include #include -#include #include #include #include From 3976cd0ed351a067a573ab3a4627bf063da9b66e Mon Sep 17 00:00:00 2001 From: superfunc Date: Tue, 25 Oct 2016 13:48:20 -0700 Subject: [PATCH 290/380] [Tf] Remove usage of BOOST_FOREACH. (Internal change: 1665969) --- pxr/base/lib/tf/diagnosticMgr.cpp | 3 +-- pxr/base/lib/tf/errorMark.cpp | 1 - pxr/base/lib/tf/fileUtils.cpp | 5 ++--- pxr/base/lib/tf/regTest.cpp | 7 ++----- pxr/base/lib/tf/registryManager.cpp | 11 ++++------- pxr/base/lib/tf/type.cpp | 1 - 6 files changed, 9 insertions(+), 19 deletions(-) diff --git a/pxr/base/lib/tf/diagnosticMgr.cpp b/pxr/base/lib/tf/diagnosticMgr.cpp index 094c3f9405..c0068a3185 100644 --- a/pxr/base/lib/tf/diagnosticMgr.cpp +++ b/pxr/base/lib/tf/diagnosticMgr.cpp @@ -38,7 +38,6 @@ #include "pxr/base/arch/stackTrace.h" #include "pxr/base/arch/threads.h" -#include #include #include @@ -159,7 +158,7 @@ TfDiagnosticMgr::_SpliceErrors(ErrorList &src) } else { // Reassign new serial numbers to the errors. size_t serial = _nextSerial.fetch_and_add(src.size()); - BOOST_FOREACH(TfError &error, src) { + for (auto& error : src) { error._data->_serial = serial++; } // Now splice them into the main list. diff --git a/pxr/base/lib/tf/errorMark.cpp b/pxr/base/lib/tf/errorMark.cpp index 03ce9793f3..98ce03a0db 100644 --- a/pxr/base/lib/tf/errorMark.cpp +++ b/pxr/base/lib/tf/errorMark.cpp @@ -28,7 +28,6 @@ #include "pxr/base/tf/iterator.h" #include "pxr/base/arch/stackTrace.h" -#include #include #include diff --git a/pxr/base/lib/tf/fileUtils.cpp b/pxr/base/lib/tf/fileUtils.cpp index 12aa83f692..67afb5a878 100644 --- a/pxr/base/lib/tf/fileUtils.cpp +++ b/pxr/base/lib/tf/fileUtils.cpp @@ -32,7 +32,6 @@ #include #include -#include #include #include #include @@ -343,7 +342,7 @@ Tf_WalkDirsRec( // symbolic link again, omit it from the directory list to prevent the // directory from being followed until stat() eventually fails with ELOOP. if (followLinks) { - BOOST_FOREACH(const string& name, symlinknames) { + for (const auto& name : symlinknames) { struct stat st; if (stat(string(dirpath + "/" + name).c_str(), &st) == 0) { if (S_ISDIR(st.st_mode)) { @@ -365,7 +364,7 @@ Tf_WalkDirsRec( if (topDown and not func(dirpath, &dirnames, filenames)) return false; - BOOST_FOREACH(const string& name, dirnames) { + for (const auto& name : dirnames) { if (not Tf_WalkDirsRec(dirpath + "/" + name, func, topDown, onError, followLinks, linkTargets)) return false; diff --git a/pxr/base/lib/tf/regTest.cpp b/pxr/base/lib/tf/regTest.cpp index 108f6b33f5..977912bc99 100644 --- a/pxr/base/lib/tf/regTest.cpp +++ b/pxr/base/lib/tf/regTest.cpp @@ -25,15 +25,11 @@ #include "pxr/base/tf/errorMark.h" #include "pxr/base/tf/instantiateSingleton.h" -#include - #include #include #include #include - - TF_INSTANTIATE_SINGLETON(TfRegTest); using std::cerr; @@ -101,8 +97,9 @@ TfRegTest::_PrintTestNames() sort(names.begin(), names.end()); - BOOST_FOREACH(string const &name, names) + for (const auto& name : names) { cerr << "\n " << name; + } cerr << endl; } diff --git a/pxr/base/lib/tf/registryManager.cpp b/pxr/base/lib/tf/registryManager.cpp index b933f41c8f..0fd1ad793d 100644 --- a/pxr/base/lib/tf/registryManager.cpp +++ b/pxr/base/lib/tf/registryManager.cpp @@ -128,7 +128,6 @@ #include "pxr/base/arch/demangle.h" #include "pxr/base/arch/symbols.h" -#include #include #include @@ -444,7 +443,7 @@ Tf_RegistryManagerImpl::_ProcessLibraryNoLock() void Tf_RegistryManagerImpl::_UpdateSubscribersNoLock() { - BOOST_FOREACH(const TypeName& typeName, _orderedSubscriptions) { + for (const auto& typeName : _orderedSubscriptions) { _RunRegistrationFunctionsNoLock(typeName); } } @@ -456,8 +455,7 @@ Tf_RegistryManagerImpl::_TransferActiveLibraryNoLock() // Move active library functions to non-thread local storage type by type. _ActiveLibraryState& active = _active.local(); - BOOST_FOREACH(_RegistrationFunctionMap::value_type& v, - active.registrationFunctions) { + for(auto& v : active.registrationFunctions) { if (not movedAny and not v.second.empty()) { movedAny = (_subscriptions.count(v.first) != 0); } @@ -533,7 +531,7 @@ Tf_RegistryManagerImpl::_UnloadNoLock(const char* libraryName) TF_AXIOM(i->second.empty()); // Run the unload functions - BOOST_FOREACH(const UnloadFunction& func, unloadFunctions) { + for (const auto& func : unloadFunctions) { func(); } } @@ -543,8 +541,7 @@ Tf_RegistryManagerImpl::_UnloadNoLock(const char* libraryName) * crashes where the registry manager could attempt to execute a * registry function from the unloaded library. */ - BOOST_FOREACH(_RegistrationFunctionMap::value_type& k, - _registrationFunctions) { + for (auto& k : _registrationFunctions) { _RegistrationValueList& regValues = k.second; _RegistrationValueList::iterator regValueIt = regValues.begin(); while (regValueIt != regValues.end()) { diff --git a/pxr/base/lib/tf/type.cpp b/pxr/base/lib/tf/type.cpp index 15bddd905a..1f81df688c 100644 --- a/pxr/base/lib/tf/type.cpp +++ b/pxr/base/lib/tf/type.cpp @@ -36,7 +36,6 @@ #include "pxr/base/tf/typeInfoMap.h" #include "pxr/base/tf/typeNotice.h" -#include #include #include #include From 91ba3a3c13ab5c4731a617143f2370478c2e2b7c Mon Sep 17 00:00:00 2001 From: superfunc Date: Tue, 25 Oct 2016 13:48:28 -0700 Subject: [PATCH 291/380] [Work] Remove usage of BOOST_FOREACH. (Internal change: 1665970) --- pxr/base/lib/work/testenv/testWorkLoops.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/pxr/base/lib/work/testenv/testWorkLoops.cpp b/pxr/base/lib/work/testenv/testWorkLoops.cpp index 58c787e099..4635facf69 100644 --- a/pxr/base/lib/work/testenv/testWorkLoops.cpp +++ b/pxr/base/lib/work/testenv/testWorkLoops.cpp @@ -31,7 +31,6 @@ #include "pxr/base/tf/staticData.h" #include -#include #include #include @@ -46,7 +45,7 @@ _Double(size_t begin, size_t end, std::vector *v) static void _DoubleAll(std::vector &v) { - BOOST_FOREACH(int &i, v) { + for (int &i : v) { i *= 2; } } @@ -105,7 +104,7 @@ _DoTBBTestForEach( { static const size_t partitionSize = 20; std::vector< std::vector > vs(partitionSize); - BOOST_FOREACH(std::vector &v, vs) { + for (auto& v : vs) { _PopulateVector(arraySize / partitionSize, v); } @@ -119,7 +118,7 @@ _DoTBBTestForEach( if (verify) { TF_AXIOM(numIterations == 1); - BOOST_FOREACH(const std::vector &v, vs) { + for (const auto& v : vs) { _VerifyDoubled(v); } } From 8819f2ebd408d777fb6cb9d3be1b87044a84c40f Mon Sep 17 00:00:00 2001 From: superfunc Date: Tue, 25 Oct 2016 13:48:32 -0700 Subject: [PATCH 292/380] [Plug] Remove usage of BOOST_FOREACH (Internal change: 1665971) --- pxr/base/lib/plug/info.cpp | 9 ++++----- pxr/base/lib/plug/plugin.cpp | 1 - pxr/base/lib/plug/registry.cpp | 5 ++--- 3 files changed, 6 insertions(+), 9 deletions(-) diff --git a/pxr/base/lib/plug/info.cpp b/pxr/base/lib/plug/info.cpp index dd6cc46a22..96c6f40481 100644 --- a/pxr/base/lib/plug/info.cpp +++ b/pxr/base/lib/plug/info.cpp @@ -33,7 +33,6 @@ #include #include #include -#include #include #include #include @@ -266,7 +265,7 @@ _ReadPlugInfo(_ReadContext* context, std::string pathname) } // Report unexpected keys. - BOOST_FOREACH(const JsObject::value_type& v, top) { + for (const auto& v : top) { const JsObject::key_type& key = v.first; if (key != _Tokens->PluginsKey and key != _Tokens->IncludesKey) { @@ -384,7 +383,7 @@ _ReadPlugInfoWithWildcards(_ReadContext* context, const std::string& pathname) Msg("Globbing plugin info path %s\n", pathname.c_str()); // Yes, no recursive searches so do the glob. - BOOST_FOREACH(const std::string& match, TfGlob(pathname, 0)) { + for (const auto& match : TfGlob(pathname, 0)) { context->taskArena.Run(boost::bind(_ReadPlugInfo, context, match)); } return; @@ -667,7 +666,7 @@ Plug_RegistrationMetadata::Plug_RegistrationMetadata( } // Report unexpected keys. - BOOST_FOREACH(const JsObject::value_type& v, topInfo) { + for (const auto& v : topInfo) { const JsObject::key_type& subkey = v.first; if (subkey != _Tokens->TypeKey and subkey != _Tokens->NameKey and @@ -699,7 +698,7 @@ Plug_ReadPlugInfo( { TF_DEBUG(PLUG_INFO_SEARCH).Msg("Will check plugin info paths\n"); _ReadContext context(*taskArena, addVisitedPath, addPlugin); - BOOST_FOREACH(const std::string& pathname, pathnames) { + for (const auto& pathname : pathnames) { // For convenience we allow given paths that are directories but // don't end in "/" to be handled as directories. Includes in // plugInfo files must still explicitly append '/' to be handled diff --git a/pxr/base/lib/plug/plugin.cpp b/pxr/base/lib/plug/plugin.cpp index c02054dc5b..3af22d8337 100644 --- a/pxr/base/lib/plug/plugin.cpp +++ b/pxr/base/lib/plug/plugin.cpp @@ -47,7 +47,6 @@ #include "pxr/base/tracelite/trace.h" #include -#include #include #include diff --git a/pxr/base/lib/plug/registry.cpp b/pxr/base/lib/plug/registry.cpp index 294f2982f4..50f033d653 100644 --- a/pxr/base/lib/plug/registry.cpp +++ b/pxr/base/lib/plug/registry.cpp @@ -40,8 +40,6 @@ #include #include -#include - using std::pair; using std::string; using std::vector; @@ -155,8 +153,9 @@ PlugRegistry::_RegisterPlugins(const std::vector& pathsToPlugInfo) if (not newPlugins.empty()) { PlugPluginPtrVector v(newPlugins.begin(), newPlugins.end()); - BOOST_FOREACH(const PlugPluginPtr &plug, v) + for (const auto& plug : v) { plug->_DeclareTypes(); + } return v; } return PlugPluginPtrVector(); From 484d178be45ff732c34ff1e40c2dde51fa7b8c25 Mon Sep 17 00:00:00 2001 From: superfunc Date: Tue, 25 Oct 2016 13:48:57 -0700 Subject: [PATCH 293/380] [Usd] Rework issue template. (Internal change: 1666059) --- ISSUE_TEMPLATE.md | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/ISSUE_TEMPLATE.md b/ISSUE_TEMPLATE.md index 9a194e3aa9..dcc559647d 100644 --- a/ISSUE_TEMPLATE.md +++ b/ISSUE_TEMPLATE.md @@ -1,8 +1,10 @@ -### System Information (OS, Hardware, etc.) +### Description of Issue + +### Steps to Reproduce +1. + +### System Information (OS, Hardware) ### Package Versions ### Build Flags - -### Steps to Reproduce -1. From c34a8a67ff05f77ad178178097e86f305dba4fa0 Mon Sep 17 00:00:00 2001 From: superfunc Date: Tue, 25 Oct 2016 13:49:01 -0700 Subject: [PATCH 294/380] [Usd] Missed in BOOST_FOREACH removal. (Internal change: 1666060) --- extras/usd/examples/usdObj/stream.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extras/usd/examples/usdObj/stream.cpp b/extras/usd/examples/usdObj/stream.cpp index ae9f89ca0c..35f4e5b824 100644 --- a/extras/usd/examples/usdObj/stream.cpp +++ b/extras/usd/examples/usdObj/stream.cpp @@ -214,7 +214,7 @@ UsdObjStream::PrependComments(string const &text) { vector lines = TfStringSplit(text, "\n"); // Mutate all the lines into comments. - for (const auto& line : lines) { + for (auto& line : lines) { line = _MakeComment(line); } // Insert them at the beginning. From 7e20da3360c768cf7ece39ea714f7ce688f92247 Mon Sep 17 00:00:00 2001 From: superfunc Date: Tue, 25 Oct 2016 13:49:08 -0700 Subject: [PATCH 295/380] [Pxr] Add namespace header back in. (Internal change: 1666067) --- pxr/pxr.h.in | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 pxr/pxr.h.in diff --git a/pxr/pxr.h.in b/pxr/pxr.h.in new file mode 100644 index 0000000000..ff2d8af420 --- /dev/null +++ b/pxr/pxr.h.in @@ -0,0 +1,52 @@ +// +// 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_H +#define PXR_H + +#define PXR_USE_NAMESPACES @PXR_USE_NAMESPACES@ + +#if PXR_USE_NAMESPACES + +#define PXR_NS @PXR_EXTERNAL_NAMESPACE@ +#define PXR_INTERNAL_NS @PXR_INTERNAL_NAMESPACE@ + +namespace PXR_INTERNAL_NS { } +namespace PXR_NS { + using namespace PXR_INTERNAL_NS; +} + +#define PXR_NAMESPACE_OPEN_SCOPE namespace PXR_INTERNAL_NS { +#define PXR_NAMESPACE_CLOSE_SCOPE } +#define PXR_NAMESPACE_USING_DIRECTIVE using namespace PXR_NS; + +#else + +#define PXR_NS +#define PXR_NAMESPACE_OPEN_SCOPE +#define PXR_NAMESPACE_CLOSE_SCOPE +#define PXR_NAMESPACE_USING_DIRECTIVE + +#endif // PXR_USE_NAMESPACES + +#endif //PXR_H From 2af407afdf409bafd87eec7f74401ec7688aea65 Mon Sep 17 00:00:00 2001 From: bmwang Date: Tue, 25 Oct 2016 14:13:30 -0700 Subject: [PATCH 296/380] add an additional warning comment for difference between sgg and pxrusdin (Internal change: 1666142) --- third_party/katana/lib/usdKatana/readMaterial.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/third_party/katana/lib/usdKatana/readMaterial.cpp b/third_party/katana/lib/usdKatana/readMaterial.cpp index c4646fb772..2fcc988010 100644 --- a/third_party/katana/lib/usdKatana/readMaterial.cpp +++ b/third_party/katana/lib/usdKatana/readMaterial.cpp @@ -609,6 +609,14 @@ _GetMaterialAttr( // Eventually, this "derivesFrom" relationship will be // a "derives" composition in usd, in which case we'll have to // rewrite this to use partial usd composition + // + // Note that there are additional workarounds in using the + // "derivesFrom"/BaseMaterial relationship in the non-op SGG that + // would need to be replicated here if the USD Material AttributeFn + // were to use the PxrUsdIn op instead, particularly with respect to + // the tree structure that the non-op the SGG creates + // See _ConvertUsdMAterialPathToKatLocation in + // katanapkg/plugin/sgg/usd/utils.cpp UsdShadeMaterial materialSchema(materialPrim); if (materialSchema.HasBaseMaterial()) { SdfPath baseMaterialPath = UsdShadeMaterial( From ca6d09e647a4305a2878b150989fb25308701162 Mon Sep 17 00:00:00 2001 From: pixar-oss Date: Tue, 25 Oct 2016 14:14:25 -0700 Subject: [PATCH 297/380] Updated USD tutorials to use PxrUsdIn and PxrUsdVariantSelection nodes. (Internal change: 1666189) --- .../tutorials/endToEnd/assets/simple.katana | Bin 13490 -> 13855 bytes .../exampleModelingVariants.katana | Bin 10602 -> 5431 bytes 2 files changed, 0 insertions(+), 0 deletions(-) diff --git a/extras/usd/tutorials/endToEnd/assets/simple.katana b/extras/usd/tutorials/endToEnd/assets/simple.katana index f888d93a35469d26e508a2dcac8467a216ebc6e4..81371dd8d55ae94f142ab7d823839f4ddb31d245 100644 GIT binary patch literal 13855 zcmaL8LzFH`6SY~kZQFLeW$T=>ZQDF$+qP}nwr$($`~BTL=|SgUN90~B#4!eiCN`M-n1O6KfL#r~hs&49u>qBt%YjE{;Yf;uhBbSq4r{CeBWb zP8K%y)+P-9cR2}>tBIqNg`MsHsbFAXVEW%-CIP?@MnXaDH$bR^`~qG3SU7EQC7Ap9 z_Wn~qi|P|-!1OVrU`r=GXG{>UCEa`e9p|oeBs?jyS*a1 z`et0+>Akv&2IP(;Zr{)BD6G7dLb?l20M%FJLghCfpEPcc2*n%|EuW%#{OlV+YNq-R zD7XRh?Ysr=F|F0@;lnXKtY6=c%-rmlv!vr)DJ-nIjpEKydUY0V4-Ss+|NZ#cydQBd zLaH;Mk2@6nbq|b3vQ-D%ak>9v_8QgNs!OxJF?#sM>BqGM#eASBg^oJ9);ZVO*&*|o zqN<-Iu?7m32TBq24(os-E&-AaC6v?D+d0>lbYm~F(rJnL(^N)q;C5B&RF z-g`Ym;C6AWp&sVGXB~g@i$*!qw2A$EJ51qRFP}f33wh5I@KHc~T5#AXs+kaemRg~o z+_lKB|A=$x(rgkVaozg7))ZtHVK-Z5N1|WhkHLkJFxuzaT9GG85e?gpA-%xTmk5wW z%l%#+@WFAdxV~_hWkKZx>eE_uP=!6v9|C>I8NqGY$9Ut6SIHLwCkej@4ZQmYGL0=F zK*b5_){I0piRbg8sIt6pQi(a0)=YExJH44f`QWx(>}M871jm>XpMFg0Q7ks|u;|{qSME;7jx1$$j@8PHQG+1AOr~Dx+Yxaot2e$*AAx&bH z+;u$$$`8u6aJ5oKGw%YeT?%8BUC6x!`_B4+9+F?er(0w}2)fH_H>`#3Kl&+#y{i07 z1aGP(Y9I3Fdc7seRhxj}e?%Is74ReN5JFu@5meOGHt|zY*hPZs?f;Br^7r5F6)X5A z4?e9{yi>+B>6Ta#tASa5t``<|zUZJYc_HtK_S$_cM?yUXZkoTE>Ch0I0Sp+*Ql5HTJO!*2GzArJ%xiOQv)W4eisv`s~r8TEf3n`|D@ICX-w~ zI&{Z+CQj|HD)(82srP+)GziutiV!~y$MGmEqTFFJWSkzu3q6A4)&%?>?QNkMcU^UI z?!~-V7mF(caHC9j4g337ig8hBN2klD63KNRK)%Twb0AUgEJsjDJVTunr7ed2k?c!* zwfzpFh~mtkb=EdotTCN9lJxFm8=!T9qChX`p(Y4Hbo$)D{y+iEYZkp}vCjX-n`G1Z z3&e7}lFu%=(FOBFUQ!pN`x7A|F=X~-pJD9EGyU6Meg<;qIubc~dtpI?_}3>khYe2_ zDg%{;I3-jdw3lP>dEtW;-}v14JX=BXK22s?`wJKF30+%|c-g24MtL}rbZu5rdB%bJ`CsG}?HtQj1s z{#O%C+<*f0=t`&+3uKR=W8R30G&e_&1>-_*6%W798k!Qd3_5mea)n)H$B=c*OQFjb z5+hX&SY>@LF%>|eZUw3Tu&lOq>pLb7ScN*OO3v9e1+CdcOLdbsZ&Y}LDUmzIu{2PO z#9kUE6F_`e4o*O}i@R*c((@62kN(BoTQIy8CbQzGdTK7QWj={QUejo?c!lJpWD4vC z27XjQN*S!?uv7l|BR`M;P8b%ny&f3PwC%tEGmR~5D>ZgF?`$X5qz%T8#ZBA(E%+q6 z7P#P)-+r5%6H4AmB6Z6ze!iu<9CXCzh*HdBcKoMc+!ZSAkr0E+j?LxX+XW)I;`+>; zEeB1izTW`geVQV7M*;{I-=RHl7-&V>wOR8w5H3a^*yz#_6nIy$#y$txeUsU#E*qj1 z1;yNw>MK9wE>wSkCsk*cUdZN7m1%Wb!86=ZAer`8LxLFCGz0ZwUQ6Ng1%zjF3dTIC zEdU8itnm#BYUqm{`IDC#u7yUjr{0peD{X=SLR*3FOgb&^-X0Kpmh(gqmpy~I#iV*` zS-6;@xbdej2dJac$g?=$wBc>6z*8cVqtQLnwxUy3^EW$DnVSdpQlbN}Ic=jrB+cvc z?XbO=SZebeXG*#}cKWkeDvn zel%R){)X+ks;MBL_9*j{<3tp2W??jujbiO5_zDau2ZU>IiY_TGFZM&Mj;#w@^*yxi ziryP<@g8b!3kak21FYu87nyPkNVpTGW6;+5b?)in<3#NK>4-KK&W3PJ3fa95ZC%}y z+Hx@Mn1bff%UoY7`aUzKogT!HQxG&l(#F-IkUL6Gbdzym-W8J^bqwYq|odl{I z`Umy#6Sytw+kkdlb-DZnSdzROq$O-eH9q(t2u3F%4qfN#?Z>%LDrmw!8pW}k#xERu zP&X5Yle=?q$9O~A1h{y$yGZ_W9TK>NIp=s+K+W1x~>i5vz?Z6UH$4<>-Jp0Oa!m5`ue@_GZfHmQAUQjGs&gkx}X)U^{zfjuC%3& zjTeH$YQ;^~b6E#JWTOUN*bd}?>j{^V7nk_KgdF2fTtiq7&&VOl zsvM--{!PgJ?q!!RDWl!tmu1u;etR8nP<#*B9ER71I!hBRYAX@5eKJKK7OP{C>g3AH zw)hlrO&p7MO^b5tx?E(j)G@KEnK3z1&gd;R$Hg%@oyRH2qtC7&3C*;`$C*#4l(gPFL<<5+Chc46ukbM$i685?-FebUCXTKVgoS z-EnDLjAUx*JXDG3a=r_0eHM$)8Zf5xv8c0IO32Sb()*$Enjd0CRB~({Zgo7A%-?U- zBGHT(`!T~gi=I^LY+2xYGaokL7B@LyAR@tB;&G2w%4q}8)nFQl=>W5TNwam?0wH=g zVM|aFT6>vFyCVd4QY8hps1!oC-dZL(}_1bUi6)x2s^D|&9*pSZz`XHELJV1r?*2EO@4#~uF!<-PUU*auHdM!f|2$=!ug>%I_D-N z`eGRzvihea+mHe2dcjB}ltmeA8NeXYZltV%KiXauGi=O(J~|0~WGt2EbOA{`**CRf zbCwZtwQwe4La^>m?7COIqhAs0vm_5mcp-tTeCQC92#NvY%X0QmrBf|33m%%nYUSK1 z+W|y52{-wp+csWI>1DEMaTFCPDR1E*KGa}n4SfMfp--4DczFA@Jw;C#<3jOU<$F+K zj4?W+WMSi>{HN07+}&;JK|K?22SaN|zKs@E(4{uqTGeC?U3@k#?V@hh1CGz4zy6;3 zM=Pw^Jp`4QgZj>=9Iv9JAkAOGHX!K_v&FTmMJta`e&<+-Ya{dTLf`&N3J*t5$(-<1mH6!MEF{YWp=$2>xgH4KWE$%0 zr6j~5(4Tbk24#(Mht;!mS>-EN#$xu~#3Tc$Ta$&VqbOa~&o&0yIbq;W#BezJ=`sz@ z1N66%)#*x!`$>+trF+GffJ8N5ER(nRIHKMd+ecAk`VHt}!7VTJ;=_2Z3_?u$bKm=~pVEw~9#XY|aw<06SSo^oHN zmFi@f8g>G?CM~TAvEp)`KU!H&U(vN|SxdAS?;nf4vz5((5o~Sf*#ES$Fs&C$#{T|Y zH%xr_3%qy|HH{gzUjF8vgh*ZVXA2BB+W`ahV8J=~h|bNKYdiZUI<^E7@~}{6+asCs z&4diA;gZE}c?YkcYq#_#oG-*V#C#e}c?Qq^kL2d62*6M~MAAWBsZ+5QUFLpVQGRzL zNA)zXrcyPNt~-T|cJcZGNnHiRj}Sbc_Oa9QfJU>GO6G>ax?2H-CE#=56-yGi;-lG8($NKz2lRkKpYHI_i!q%Zlr?=VM&BRJ%DUd@_|>_d1IF?dFk!#8?j zImYYM;38gl9kg&sQ}Jmtp-~WcXCQqn0QF}YS9;Z1sF7L{96qubI_0EEQfcEpY%ukyWsvXF2=Y)=-iZ#s+f-u zQ5wfc1SYvi(4^u+HR(_FVap~Y$h zFFvjOhz_kh4~f}=OH^WwQI;$IVbdj_d?|iB>ow0vc8$^2`TxRWTjQdLrOVT%`yPyR zWw^A2itn^*qDl1H9XL7#xbZ0{nF~DZT?%b6W6@>1hf#dv9R@z12c>lIZz0cTs=%Ph zzq&5x^1_m86SmX7@por=Z9xlaVD=h4e#zn$;?(EPy*UeBteN#K{3B~oP_>?8Osl9$B?%>ks}1;GqaX`gC#RiO`r23*;i3i4GX zkRr>g7^fa2x9!uew2T5!>QjCnk-C`tih+6VsPsQm8Lou#y16PGyQ9sD7^*8ik|deu zaLMK$%Vp6tP1srmVbY$M6?Qt$6^r0cg<(SeJ^XFoYGg3vV*$=(>&tLG7du8Y*cC;+ z=qcZCyvsM%aUZHCTJ#)9G#a*n6za)?V8+*^K3Yduf?Ye={w zBoTlxy|NxlVpq=t@vctC>jFq!tC{s9rcSlL8jz`W+HmUJH0*I2s5qz}B-wX+9S+ID zIeHs2pyq|x4Fdbh@#Sq=&7BCzurTdiux&7DIgm=*6X*t$&C-XaUbG_X6l}}LfQFTf zu(P9b7&Y2eQO`Y&=mcsB>knSqB)tW-Qk)M<3f*S90gK=WtA%@xeVhrJruKKcr4P=I z?(f!W`sa}kPAeybWUx);TEjQenP}spCnR)S!p*9d9F6NsYa3&XSs~$-3g!HXwMdhq zWj6d0>Y7}ER)BD9CG-+VjTL#o?n93_?k5eDVhNR+8}t}_C3;wYqz+QC+(BnBan=$Yx(RLb$*RQawfAxt3^ z_J(;<7QX6f#Cv2>Iouz%L{`#^uZcJriP9(VRb1-9BYqG1s>VzidVq|XnaosvF7Lgy ziTxu?N0vO9Do5fk%*I+G8EztF=TZBGQ9TC!9|3A3uy;6II9f^Yc)_K*feOX*<5bpFs1j*`2fb_$n)3mn8?qG z9*mB!>38v*C%Lw~!NJYH!!q3Y-eJWs%rxVj9Xe6f8{x{|=$}y@07Hyc7kVo!kw;&b zF&;Nbw7Dhr!)%Q{tW1_j>xhXmX^t_|JmJ5H#x-=t6d_C?`oD?`j0jj7zd0hJn(EDr z@;IW^YRD9r4tB%G4HYu?ExZ@{baz~Em{2BCW86J&}TYJjZu_@HlmeoZ6Qh4g=LReYo zMyFRC405Egd^HC6X|JWAGwwUh-R^$q>n#m*}Ar-3YiV-{92{SNC+RWyFzN% z5Q^Ouz%!yna&1!F@-zk<$h=W7Gr73=l;%BJfMoZcAslQ3iB)1tmgXYyv=#rrqQB4N zOnMa>OcahQn>@u;g{cg~km(WI4@YRm+#EXgtHA=u5rIMAI>>+>QLNW}gzSaPvTO7=HsaO6~9ghR~JiLbMQ z?MAjUTG1*%dOI0I2aQ<`z|hSCmleUJtZ9~G7o^O!!7>#o3tESlJb3yQCTMlYm7&%@ z?4I#q(vO{y-;9eeVv;R4vJVz&Tg`VRBdLF&ojR9yjt4nrV4oRdbOpOojeK)-5=!Ji z;wz&}s96*tg1p{v?ku7~=%+^`s9m&GOmcG3bJ#IYIlrC+732kj=11wjYIb@NxX!@| zk+5BF2^PcWO*;hA6@f{ADPl@4eJX{vwD=+v0>`;zcMQqU%pmE~bTPVe{RhC+x zcxj&Mwr2GH2K#5e)wyakPeeo>$j#wr!5ljF`u7;+gZg7h@DMqFq5i$;prOJch`=G6 zZJX$oCbN1UCdn@4Pa~<|1zm8hfe&zUAzCN;7K)eW??Hl1o+bJ*K=upt4&}^~@4(s; zpt=E#@}^KUtMb9$zV3~=c@cH3&g~Vbxn6K82|R4)Gm{RoPG&VJ<*-Xs4bq{2^JuDM zd%EA5_jS3o)R%(@Vz+^fytST~TY(;j7Q$hB6?+`Kuhh+t$WFSIIAzGfUp zi}pH-)Y1yb+%BMGCLtu{eWnP$q3iMXW!p$G!pf)GccTz2${#4Q3ARu+nEcosT{$sk z^EDm*wYE_YGxf@b{|z5AnVuADakGGm#{0{0!JipnAbKGC)_f>(=$cR|qhP!Ok=-M! zx{DbPC0t6Y)VPw~YzuCs<9|g<{g-Crw%zjl8im595;L{R5~!Qr#wQM!Tix*Rx%{_% z;)VyRruiul%Y{Awjd=%ImR3%P66!NPhh?%fYSKifazbNNnwA0b`KFmCC`GiXhU-~# zxQva}s2wRz&*waQn#>T#jV~2r7_z-fW;oCAxM-NJYhj<1#_t1xP+piNo??O+GX*=NRtJ z-Wn7B{!^ce9qW>(8*IaVyYQf+BdZv_*8%8XU*R9dWYZpq6&9tNX9H=mztwAhNt->$ zol;_??0T?>ydTqG5i9se7CyghEZC$%7Ykg>U}>5Ecnvj?V0(OPEN}qB6o3#?P|u<- z|AHCeYE3CS?nu3?4XeHvkX0Db-ta{$=u1;z_D{%KjKL%6C$ z6*N2P^l;^0mps!JUGCJWj>_b((-qlQw*>rP*&^=uBhfiJgfb983|0=*O|733m-}K# z)w8fg_TiAY%Fr%rc0fo1;1g~1It`kWsO9<=SSKajNIPzfq$rt=$dlL#EeOhV5L{#7)PsOKpL$%|gQ-%-RA>x=&iO_ib?{!<27b zG!IVGYVO=V3wW<_Aoe z^kM>D4{eu8v5Aa5)Ar&DhdU&@T6;>9?%7G)hd3loM;HaplpYtC{s24%bso8ZG7qCP zOsaujRrEJsf+~?iidU7-v117PL#fU#dJKaag?*H5+AXVHDOzWG=9S?(Ubk=Hcx@>& zPeMWK`&GB0G=-N<&;ZJUDid=tsYXU-M6lj6x0O?>Q|V{l<9&Lx8kZWuLClCG%WLEK zi)Xxe!*PeulrEZy=~qf}3jO{@p(ac{bI*kok@spM5LMfNHV$CxWV#t*9No20&k9j7B#_p`Fz&r%fzUt#AjS8;^TXBElMpw z?X8#tuiHfC*!Gd~(}nGtoK(U~g|{Z>R!`h%QAozXJ{rx(K}f8B(U9VY=Ax@D4*SJY zF;s0eO9W#*4GgwNUeuX7kGNb%B17JC$RY>DwUoZd!hl69V!>FU+3}s58Kenaias)V z6(K^YVhK70g#Nl!wY2cvl3q39+lpE}CFGT;K#VLnNjWWg4U*c#KWTI7TO)%{HbczZT_wB>Zft zQrPnkLKuVnn2e6_Wc;SHnX!*1k>&j_-jzsv_KdEemiSqL1>pfXQr5IKiZBvRgqSNwF5lWWZ8L52&cL=4HF2D^*4DoiXAWYx*fu zFczYC-ad+H{&+k;sy))-;Xk$vj}jt{%z+cN2i;Py21Gn-bc#jYNX8gaRzK4@jN@8Y zofr#`s+oGj%K=u{yZ2y{(qd_6cr=Qty(TDs?UqloT4Jh&b*haQ z-@zg%|2fKxtM-(Ys7aNEo#a#FL~58TCyZ!(C@v_sO+dAm7L1ZcHBX&+a(q~>Xpd#^ zN9T@A#zRj3z^qGZDi|5UKFH8sH^YLA@GWYKoX;|Zt<&BxuFsYXh53rwJM0klMQBwP zIIJ2R2FENt3*4bf_2>-J?mT)@uu#k-U?ov0`4(Ux@9x?fgYUSX`Bz0p$Rg02;s}uZ zSrb_clCjh&|R`M_(`ZOtr&ydd$mtgL^0UC>juZ}F9|%e4%W7|)Xyl5Vh;TuHif8M#Ltqj z{wC=J2x6yFGTZ|@?D%@rTQ?yecAAf{(>bX5N4H~0gVLeOl-L(YJJQxTepW_EHWPX! z(HZ#o7j_|Rc_DVFKuGFFXoFHm_E{(MjXhyt*R%5jW<)SsQcviumZyO%+*cm(5iY*r ziFyQ`l1ijOO_dMnPxG83d*JwMZz~ML>4_V%?h+hRk>W#$$lLu#oXU2~c{F`Y#riKR z%n~cS;G+OGPZos=ZufYlp_DAO3@kIVu=}ob0*v)Vrg#^S^D0#nw9b%>h?mfWrREP~ z%NC)*I`f6DquAMXsjPBqrRM1|t9k!X4_bl$izdoag@?rygHC5N9MLpJ%GiYya7gt< zHG-amM|1|cP;oQgWSZ3U%}rngXM{{u>ba_QC?^v0e2-jX;8@=%)YRBS!Yt=mctZyt zd>gr7lEX)c?qT`js;YNn_F0d-4y`9%>=UYd?JPo>omZd0$5tu>W&6$}^c(PFvwRReR7cYo^ zQr0O4p?!k0ndU0C4GI2$6OI{(N|aPK_$fmsN3`$pxL`*u3?V0@l&8%*+#Ja4Eg&BZ zyvT~~iFR(c^{5BgXZ>FQNgj7tYxrmI}N{oedxnJi$FFD$c_!TfG&| z&a-fbwxu@B9*d5{tR6Q}feWYMot21M`rr}meW(PSG?j_q)K z-d!1|T91oob&mdb<|cNMyR);z?mA7Y-YI1gaGrnpoTwQkMfjH}sO6`cF1l=y#NGwC z(RQ2UXJdIqx_<*a5*U-IhDS{>l)P(Ye7|&3>M0YoFtzA)NiqzeBi~;h57q5;^ExWf z1Zk=(<;pS?bW2O9yaz32uU0`J5gHo0xLxy5i#!8r^n}xy4=I4<%5n8|H&n_1v(UjM zX7ZMT9;B!#UE$-naw!$?t@E8BHp5uGNt*AxDCWC-f!Nb7y0;(CNg!7${d67UwO0=< zTYD+qLHxWqJSEmYNZJI6LKuh9DH*b`sY27L`-W(qx+A}%F2cjeOIb?TDuq((b9n~D z8S~PUkZ)D<0p1ow2vSm>mKyzD&>2#axpmm<8uRNwn(UbKbZ_$U8Se>1B0TJAnJJ5<0rE zB@|U%(xoKPBc53KHy#KG<8x<0No5d@FL?F=`t}y|Su_Yky;6ekenG}6-@H9wX9rcE z?hB^B>%a*@&_7&e3sKc>Sbb*Dy7saTZF&d1d8(^7=ynj#b3pA~KCdBr zVIvc26JK-SkAXT#>VkYqf8Fp7@-DKad}n9$o%t#%iI}!js?jpDb2t9C&?w9|h1Wew zfBQh0iT5Mv&Lt7JiL=f#(OIokOJc+4pIF9t?$4eWGqaZm(t3bwrr$k%aqPBuvzHlq ziVWitz0kL!B5oB88egc}(g^cYO8}deD`-F)3 zTl+J%T)Ml)V<(cQ;xG*!B?=}~L^=Jn`nUcY2c=TMBL187?I$@L9X#xsG$ZMG>LO`d z8kT+8}a93i1tNtto&ZtQRUI5+!}^D}v+t*aIPiS%z+C z#u5=-sEdSMPZo48jx{Jktjdof+ZF*uf)9x7InM;6?sQr;>PMkw%Ud+7*bq@~N56zX zrUH$N%Gfm9_2Hd-UR;2_z8hm9b__-9w^K3P%fXjOro@4hT2&BsO)nJCSxG z`k^^&y;B_&J^mfK56pgMJM&?I+`{JrW!u}tKz-m7{7T^Iu~-Qq2s`?O0_lcI%;Je2 zE{;R2~ z*Iw8U>a8?7-%hYAM<@%RVOzLU)D1C6$pSQCt@Y_*rK$RfC6rCi;d`(_Ypl z;^B)%Szmcjz3|wtV01ipVOj~~@*&SE8)mF149TyaUAQ|oDoX5JiXOS40%4fA39Y@Z zxM0l)DeFXNw}JOmzg@$a9T#A|bHuwDfE1R$Y%Ia*=-CLbidS*|0h@h_^u7c!dZy%J zE{F>WX#32rxon8L4f+#3yYgoJ|H|6j|H%j&Ye4Xj?xMr3s2o)|3iJcgf10!AM5d6M znkRVY_ylX6OAj;e7oGuC@U_JIUNUU2@CL8X{i(W|-%O#~qlcu=cz9R01TmwBQoXFV z8Fwp1)#?0Q>w}s9A8E5fb+b7t4DaM{Sf#kx7}Cl7Kh8mo+*WgZG{wzFd@*Z(z?!0B zcMt``15#nfOy1;N&p%nL-WAh@tP^Y7#Tt&*ao<;~>Q}<4zPBgHPK>_*$}tW6c#h+% z?akZd=GKCb4WxE)@I$Y8XR(HsKN_DaLF4CdXZj7RjM>icVbA(5LPYjc_o)D`uMyQu zLEpH`mFFz;!oouSbGckRf@{~;vS(mc8(>rNkAMBghfe^*LDP_FxXkJu4It2X6`ePo zv5pw~Z+!zp>KW<>5X|YDmC(=Tbzjv8H47P5u7n^0%IFgSv_Ty@##;!t8+VJsz!ikCq;z7E#x6C6G-%XsY|} zhVg=uNc0=%ULDbCwL84`S>2mF&FVCaNLFOLHzoYcHGH-iX6v4AqG=vWV7v6Asn>f` z<(P7&sftv)hkt%^O_j;aHj| z4l~&DpXS6jR`hClQ1oAIYZNxXc=F-132)<8_taPC?Bg>3 zgk9lr1kAm$ z`9aZ6x32~~Ws4O#S=7+spk-4STQ$$nLxpwkfq2%>(>RXHjsqcR2M+x>=($0J`@~VT z5$fPdU$tY$H2z}qy=c8tBZS+O)e~aOr*7$CYlQ`z$PBJfcc=F5rdUTvHmi69IHeM9lNbusjfH~* zX+BvZSNmG{Sq1-5p|e~+PgEIGjQyHr9-N%Zort{4*B5fUE1TuROLtpFe|Yd(5voLd zSouudr|#A|maeJZpJ7=L`OjD@S~(!VW}%Co`da~sH(I$;63LyBu8M`qn{OR-8@9vl zxNf7HZ_Inqug{DB1oygz5xxZLY$R)+_X&`oDCZ!Vs>(|XJsLY5oaixF{w3KY;4C$B zFdVE;>D%;?Zw9Z<`3QJ{V++>oc*28SfB5&aUS-{Jf~8?w$c$>>`39kN8d$Vo1dbBO z=QXUQR~T^|>?JNh=NUbf17G)?JuJ0u+fy%ls%5zrUe+jYN0xl7^XRk=}lhvAgjMC4I>uU{?=bV%2j^Jd>QC~zzE#O;M;j8E!rcb zw=oCxMD5s#X3ze17}O{5c-uqm2ud6sqp0`r@2stFJnBaFdHjYs0Q(NU>0eeD?e8R?WK?Ih}mXfAS+Yy z1BR|xBA|Kw5FYhw^@fp8Y^U5#(<(6fgg{+gKharJ-9DSR{LZUZcLm&KJUTZQR%9<& z-i!Uh0S91uC0eLWHHX%*;K4*PH}~sf;Z4b`Oy@67XD?2tFAgUc9*O=`rSlwf9`U}N2w{$4Hh9Pk!)wB65$L}ROhAptEL`BXEX@U>+FgT8g0|+y zLCy{@yUC=YzM^T_bhBmqux&@P=={Mrj`SrI{1v)qzlo@Ip!9|xn?N3s*Otu}O3!J` z-OGzz@`|V!Is#tp8-J~o<^yH}FtHNn{=!>_)a-x8ffE-Z+5|rVwO<;9S}T3$!&@x# zYpm?~YV|Fx4USUB404BKS7eLHb4w^dp+UnK;VR$Y(^9)lYB-qjDRLrHS8mQ2d^MN$ z)2%9^IvVeg>U>I}$Nh)h4?3>|Vcfx+1CdvoU8v2y!s$_>BaTcT`#?#)h*L&mu%Iu2 z|B2=RXx2QaHSY~*sK88D(1_-M(HA#=IcLyts{ec|r0nj`tfp@;M~v?QsM5gRJ+Cvzm@)kKs56 zB&l65snOYom{WVEQh4{1v-0n}o$3kspYQ(f!-MSicVjUCbM3zYiwNF=g2Rj9^JHUL z5Pg$0rQT(-YYB`Mt{cU-JDu z`F*R`v-A7&EMp)j>KwDWjDrZNad~M@W`Ny@?81M*dc`a04Al1jU^fCHd%gqUGgHe* z^HJ?Q|3U7;t1jr|{Ax_{>qU$vbTtW@t#ayobX0Qa_BR=OvL#0RlDnGEW%A*lLKNC8 z!-9?9U-o`^?*x`DqoyrRjdHWSN zml22#5v^l9BPuLK0rPWS;Uc@#p?YRg|5yZ;?FJxR2=12mBDWw{g{fNuNAn8Ysm`Dt zNju=MDO<-l05j_&lsE<&cx4S3IT1{4a6@>p%Pun5TR59`Ob?{H0j)fPW%HmFrT&Qb zg>`ZsX)N4xyGUAOf%LG6xMXe2rj_upJca`YNMg&iPilYV>_ea&_u1$|@EoKyLmFS5 zf6dv}u@zokQ9&=~-A~KdD(cZ&$*bA!Gu!TObyoU#Hcsfq&N%R68AlS&jL;NIMdA!s z)OkbOut5scucVG0dJ?Fso`{jahM4ufY0Ph&fPEltxUl=VyKMfd=$Kax0Er3;R+{=u z1bL%C0un9nIDmRUvrP|)OG{+5TQ19s58fUrAJazpPMBjori=*wf6{TlFX0Rj{0~qW H2+;opG>Raa literal 13490 zcmV;jG)>DqYhiR@Zebu{a${&|c4a*xbYXHLAaZ4FWnpt=Jt8tLFm^Q}AaieZa${vi zX>4UZB6DeNaBO8RYhiR@Zeb!Ic4cyNX>V>lA~G&8E-@}JFfcGPIU+s^ABzYG^k)=T z0{;N*eQR^vIFew0zF)!9#7;=FcB!iL?ipRIEw_6WYg-P>?Y6zKr+`RQ6ftt{T+f@8NxdIHh;HTa{Q~ueXPQ}l?-MxMJ z_s-6a{5jp--{0Gr|1_H)O!ubyI|uu_KTT)5yYro&jOkAg@bM`F#4vuMzI#_S_vPZY zc9PRzlJe&h`TWDh7Bnsag&*%cc)al|!M?X)z&q$+HwK!QM1^e0RL@ ze73hc*_j{B4i1y&-;Ot?lK=r5#tK;$bdNU}@!^Ky0*8Yq7_)c0#|?wY?monSUn6)! zO<==Y0b}oIdN|)tJ-sV^%KMwe{fUMfhInz~|NJk*_{UOA<-!Am_sk&4k3hV`-*SED z5|Y$wD?Sf;yz$S!{^?`(cN4puKwK95^>gs!BcD<5+cP8hNuf&-L)VDiW!~hY3x4@m zgaPD!M2?s*uzmjLY-4+%fnc9yN5XOVz+;JCyg}9yW}&&hZHF(#Bfi1p3c1VEfic)_ z)Mvw^J06nh69Qef9yG?iFb@9IH3@WhUnTueMmS!S{SXMOGuOUT^b>az>{{ny2YUxn z6QaoRY^d8?$zl>nvF$U2-CU2!7jb9v|GGH$J&v`Vz0CzDg6F{7io4DWqHNFDgKpg% zJ=*4 zgpEe{y3jB;&@|-Cc=^M4dA4)wqqS<8X@o;u65y@Q8DQ`eAP8LAkmkm79X;2ijTN-L z%#7bhFH++MG5)f_|D%S4VgLdSpF+z3)Ueukm^k;Ki57Rp%?fh%AqK-jFc`ka2MmGJwO0dQb1pQ2Yiy#00j>eEg;d)zEMMS5 zvg{=$7Vo+12i`KF)?nB02sXJ;$+JG6*I784c>TU40#-xB0zS@@6|$`i3ZW~e)Owi; zz+c#CnUyyLEmy3+4*rvavlEcfwr}5nJKC|A3Q_s2H=2Em1qU0Kwoi-<;7dEyH)5e?)E_DS$-W^i9(#XDy1kk2*@ioS{S+J?b=emp!6 z|4JCW>;N1pGSgT#Ow*#FqQxv}G1<$AlkHM@Qjj-I#9Gjzm-VPIC}dSH2f0;WqYA^t zI&`0Rfwal-J7v(LfxK}%pFsm~!Q?=)6k@QK&j;uVg+~Z?Dvx4ZVev2t=rj<(TmnjR znDjXRCnIJam0W2rNH~|B17TT8PF;t!M+IFQLue%s=It)F9s%GS+R$Vtz@xsMGZgAt z)IybkxA47BQ%eNp>CNql-XByhgTTV|?`qWe@(Zflc$H z^O0;>v(s0ay2YGRMqsOG)9wy-Nni?lJp$&tAS{QgHg71uC?{dbf)7N(_Ts@vnC@5? zx$Z_nZb-<}$$W23w44Xs8#xDZ`+?}0um`2*TzB6qJ@-p?d6M3HjMBNestL(?=p;&X zPUTd>#kL4o@-J36Yc#d-a(xCB)p2w>na=X0SmQA7e{e+;yogVsq4$b7obV0APa7s+ zm{4hjFg9;i(2c(pM@G8BH*UeZ6~6HbQO^c<5^&;pPAQgM!wA-mlH_F0<!qWJ|D%&8z4*iE2#&eC2XF)7g%6LYmE_)&xQJyqis<`gCUzJbAkVa(}Zxe`uc#0=rIVc@E7TPrYZ9N1W) zgUQ{bxDValort9s2Dfw!%(V7kjkGMt8cw6*R;NF{8J@+Km9x!0zrAIXhazu)Ad{V7$HOk<<=4BHr1e-2OyP<3Ya2#JBTb4 z87j0OAr(XXaCW*;CqiYoMhUs7-oM0*VW&xpn~dFQZ#J)QvVzjH`nc2+#8O zpN-(BM6~=Z2@e)dAeq1Sl8a^skgITkOM4BH=7G-dw>aHc+0Fj9^H&$A?=}o7>(s6F?_lo*N$t0ltfO4gAW_frS#Dj$ z^GsIoWSg!qquX>ky_n9z9}}NiI?e?J%>v6hzoT3zoCQ-UF|@0Y25+G$Gl?_#XUK6l zweUTv9)QSWxchwtNzxiH;o~&X0-1)5%^=Q18&I-?gvnf7g_Q}<*BYZa`Q=TS4ySlK z9$eI9TNG#5zQM${wwDlBK}f65{}HiKcvKVXT`On^M?9fiy8e<)`&b^ zAowGC!CysY7;ccRu))7Vd`o{P8^uy8-B{EM2?f(^7RagD!T#h(eCB0>iZ4FJJ~8?4 zZ$&ize3Ft)JqWM#=xX`cL!bCrB2AIAdP2I+H968C22SR0s)*lSvhAfDxyDIog>Oz> z6Fa;oSp}iV4o&Y|GYEQ44`r&&d2-G8m*y2%3hg8cSh3=V@(pcx0tfGdh8bY#=en@? zud?$X7&|?(^cT%$ib6zZ;6)FcP4yxqO|X1nVULM3K?){I9_s>pk13NwIAQ99_fw~8 z=HzIw-XXL+C$RJ@x9Pe_LMR^WWtF$0`W8vW6y=wTMjhd(6py)4S1DnMw0U7&3zL_1 z7G&wFGG@zr1YzT>4O-Qk@4UpmYpMEBw-l5B$u<04$kTH^LHK!riBktBpWmAWcIt9P zOK9;g7=QcHXJVm)gu-bip)emut%z(Qkdq~WmegERFw<>oh9;FAoiQj=n4^u@g135; zQF|OJmxE9BgE-qcoa5w#e@AQ;Pr5u|q_NdAQhAEZ8WuK7HsE-hVd?L4MZ`L?SGu2C z&bSEWlon@%ESouUeJI-`>qX`9|J}|iBsuL|)7w-njw9$N(khn`!GWQ!I{dx36=y&= zxt&*ig3A&``Ka3V z%|3QC-r22xM|MUa^NCAa(0PDjt^HqH+i0e5bkR8a(>d0xb#&D``qMmm(>-dmkG}Pf z>J6`*lR9D_9Q8z63%44M(iF=YaiETFEmiV{zD=|OEaq1jd%lo@U^q*QS`70q#&|^z31eW z14bDnjX<4w=O#fO%UNN3w-q#rtvATM;<)BZifr3=keg9BWCwQiUiOs^UC|Y=@QtFA z@XIFP6Hbt}2~j7N7NMUrhv_QedHuFXSeZwx_?DL9lNCF`8YYw%sVFH5QtKzW5=^Z% zr$*nG!kTp<)NL*JkDUEfrnNxnyHy;*i}CjOI&OY2)oqo@>zGbv+PxLhAT(76YKkC( z-}#QsNnNqYS38=YtF;3~2DTzOy@9K`NuMG-QrTmj_Mw1ja>nKx#Nt%^fRs$8qHKo=%Pq=ezU0>Cyb)V0yHxyRI^LOuDg=S(WrrS+vSEZQtTr=ZOqidxL1j z5-3*=SjeZ%+aVV*E<>a^tZ1#&YsFT4Qb;GS_5)gND6FzhMWVxX=9^0m(xRzEv%& zjP9((Ug<0z2$R8&&tJaYfByRA{>$gD_g}t#zW@69%l+3cpL5e9Vu-x0)~q&psh~=4D=oVHLP6$7Wi{a&750lgV~W=~WGb(rV?bR7L=HQJbq0 zs<(9*oy{k^`_sMMgT1}^?$J>ZyK2~Xb+8Y2CbRi$heJNt**Vys9yWpgtq%H5pbJb7 z_vXBdqrHO?%BbEnejL(~Ox7#iOnar2=hI$EV>*(8k`(0iK+PyYt;8u^&JJWgFhC3}A&Zcb}&RQa8)^?7wwsV}fo#VXiI?m@U zkuz^Q$DOuw+-W<9`=zAxCoXVY3Ecsi0fWs+W_;X59$9xJ)&G>EsQ9-)ftfUJRA z#C{r1Lm1+J>H$;bYpt*f(sz)Fd-T+js}BL9n!9D4uf#Pg884=$=ssR3JO))B=L2Tc-d`IXYeH<9`D3aF-Qhn7zob*I7*1K};q61zl@@z7g-BUEy z!R2ck16Gbo4P;h?#`vztWba)!Rw?A!t?fL_`TK|yMMhE9yS)yT2@1Kq^TbV{xt!L_ zE3DY6G;X%DGL-H@QyocXT;qGZYun|#l5?-%sdxrV-)idQX* za9X3{8V|flxJFpoavp@sZ7H z>zUEK&DKV0^Xw&LO{EGcV=szGtLWNKsw+HyZhU|aR}-iKY&*^hrm|G9yn#&wLCWeF zK^Yr)U^P53`M*r3v+3VO6FYb;P+}Y#r;)X9@+)LA^EpJN#9;hph`gUUzNP7Jb1MUp z(~RfGxd)}73vc8=nBw+Bu2Pi3bp&n^8AghK0kI1^QEC$jzc;YLiJ=Xk|ORq=`R>yGj8?3%N3)&2J3ZbaF~x zaJ`W-OwNeBt!cB+6R)bV z(HJt=zZ)eIkx%&zyoR7#LEA}d@h=k(FN|wLN6C2>eX7{Nv5}O-AV{7`Q+EMFx+@SInDHx znWbF;sZAZEHN*h3vbb~ac#g{9|S@Ubo9QIsdb z1-75^?~0DpJq<^yCrnClRjAOIxkh_b>Dc>9CF)`<(j;g=mfD__AXib}(jVRdTyE!A zG$G(7O4crGrfj&%UqaBrsW2_~3+Ou*S^$V}qys|7KfyP3m3KnZLs50H3s?EqiDWIm zSg7+f2a`v2Ye3r0wLWle=WY@mk^TTkrw-qUg~~S~{$UY+gXBGjL8i-y`v=9nhmp(V z9g9Qnqr2Vr(cO;7uJrSF$F*6SXWBcS%WI~D$PQ|z>{Qlm(u%N4g&|LN0}Xw;ceJk_ zT?MRJkFe%VVeykq8QNMQIVQ*v&0W#_aQv$GlHw%gx?!GXvy%&hx5Mjq-S@ahzPU9O zxalK$93%1}v{P?VXfL9BPbQOXIfn_F1`kpJA~g+WO&iR^23yAeJ~lRIlj$=f`fsc1 zVxW**2Hq~xqf0_)4LW0)t$!?{5QNT9=Hp&B z?saR}>pWy$Nr|H9zvHf@cS@KwZJyt<)BrkL+PWY&bg)Fm>r?lW%I?|=uC?@o2z3pC z10m}k4% z2-Q-iwAf0=iX!a|=DMpfZ(V*wxe{$Ls4AAxk6AWz5n#oofT>GDH04vfmm#wv z1aV`}d@mdDKA%?J^qIf^c(#U1J~LCQzvA;coKnV)lDa~*`lh}tj87Tj^-=8|eO0Sf za^GrlA8+;TZ6$U+RWXcLn8`)(>eoRWD>ADW-=w;>t6Jj;ce|=JxATp6wbt7>#=BYz zccoR-vF!8e*7xG3sEF^yqwoPsf6G~Zx7L)HX1^DC-i=sm4ZNESx}I%Km=tc>-u~M^ zL6X%eIt)WbMDS4XD?!UJPgc}}sCzpqV%MOFoKl1LrByum^G%RObK@0Q?TzNf8i@BwP> zat&!cH_SfujTSU?5iT@XzOb;zgv%>bKuf;hO~pLJob=#6Tosfu>`%3^pGDFdBu;U} z+SeC-exQHiY1xtH4zF0 zq^)6LN@r478^y*Sw0YCy-sV)Q()#)A2=ZzGP?9ynieRJhwrlWnxi-!67npd$0pDX-Q8xEhc!h5&bEPfqL zyI|yKu4+fkv*Sx?ZaQemO|F)rFD|Hf@ibp`Uqzi47qXgOMVWAQ%Ozx?jY+WJFR_R& z1=J_C>qygCg*eSp!tT6*G|eq$Ls1%^sn#w(XQKdZL{deu@{5I{@+nnUqMwPVdn$8lXrYTT?KTZyWYMAp+41>%q{HQMy{<^Vd-qK#1lcerDQ7~sOeSG zDWX|u0gXj0G%2atEWrpDLU}P=IqF=eIwcFsJ{e?f<%)nJ+xUOSnemhq{|ri}mM|5? zg7qUt2#8stqXGk|62|iW&eGDGS#+KW^1DG4J~M)PdmQc8kRqno3Bb-_A?QG<-iirRJF)4xIjQmN{eNeu5_``s%q`S%U(r&;y{jws{AWhN?KuO zB449(Yel6v^ms+cR*IDhU#%e$HRXf*K zZCO{fQ%%)&^;G+)rK(#;wUw)(c<^`tyRH{movb11lk*2r4eYo$2TL`1ecyINY?tGxipO(I zAi}avL;H7l9c@MR54V%6Ol5R=%g-u&4yW#^o0@*L&E-Jf=2D8I^+X#eX4Kg9lC!EP zOefi1YAh#D&Tw)L89z$9MyiB-m{{n>bB^MGvd2Lvbw+5F7*PVd0)a9vPh8joq8k13 z64~$|#!u0VYgpo5026a9lzLbekxbx(jpR{0sN)|rL_zYcTbi5kXE~QG2I$mNjJcssTb5vzURc2IWdWcvGt~)yOGM2E91W4z8 z9IceRRoDU#^b-sf`_meB!t5;SR~~zr0Ha?+B_#z!NG6@kK`gGyquoh>C>FoRB!&uE zso+UqS?71+9?i30mW_CFZGtv)vG)VYS5?8N{&bq^mCmthD%J9Fir2c0ptDr&L;k(6 zt|4KF!hnyoBw$1PaI|FFa<8^hn?e@l=h9dX#>S&xZdqQ_>LC7#?33bzuEI_jXoJ&Y z7LbAupp_EAZ>WxbqUjmy>5Er&@LpLusfOmSye|DplmOe^l?a~C z!u;U*!Q@DM_QN@9mL)00cRjYNYE|b(8zW8kY?8ur^E<5dZm(9KG8X6-S`|a8u1}qv z`WtYE{hULjRqZ~#Qk5T0&-I$+EB5gtfnGz6x|CJtqr8WYUveW&F&Ay zn%!;7x3;XU*t*JPm-5in`bj0mq>soGLRJfjHV{f_DXDg;S+6Gr z_ILGL<~hH#ZHI!=b(i+3)gOFwiNM1nZ#tRJ1JSoT?SRKRFrBU&X@}Hr7YiGC50B6e zNPIwAY$F*;Z&y(sz3?B^jcTt8B9-k2!ek;f-$ucl zLr6{+yReJcY}$V9G84E<8xBIDN1Yh`Xb3)Ur=VHTW2>{pYXogeS4mi$GwhwZ3vn6g zFw4{F0-M?6xxhwZau5v8=bi2Vnm;D-yAa71Z=gE}B6oMYAX3qKNJPFulnsK(gD!|X zcrp@~u6$9V^~{5AHlV&P8R7)HlmVB00Hf6HcJW%U0ytQK3sc~AJqYc=#;a)zRa~;y z_AXoPdu;o(`9Aik4kVTHvV4ry?-Ao7B{hna$c&N=!}8Y_h5RXs8*$i@XqjzJyEUo=ESfsE^wx8)#YA z_1onoO-qlm+M?dOQyIAoE(u@-e^Ar+yWC!`w+!!ZiCBJ-_zOwcJ?9*di($^| zRjwnt0o)4aegoZQiL&q@xa<}zGJQNe&WHR)#Fw5cf=fqv*$9^}Z>`0M%I>J-4{gX8 zd?jKShH?IO^8G$OOp2UQy22%)AP*E47UUF9=SPPfD6+Ov-?x_cm~$P@Nzf#26xqhFx69p?G2_T?`{# zVD)7rX&)MZs1I!PP2VI)*_}O%1xu9BfL52KY7SxTR;(LDpbS77)!Z)U2F$t8K3PHY zY81|E6c?|gUF%I)4QS&DS!%zRW5^@0)IKp(wkLLY=`YWNvXv*;W$>2iQv5Z7H|7es zF0=>PD&M(Xw#jC#hu2}my##7bNqosM(C)JcCir}*9>r}+)gXMaT z=zTH??iOAE>hWXC81mdh{8EsB@!4_T7Cztwve`iOE*;d#h|;k6+8qrJ;D8m z&`AADc^SsI<#eG%&jjXbba{2dp->^o-5^NZpLHutscb(aIa-K}vaw@Q?6qeN7P|Gk z6Kg-8JrU1TY?{_D#7+lvbv(IMsUq(o5&7K&fQ8jv5O$rRlHn{wgG-Tfx4<_Qzir{H zT@)kNB=RmyFlwru4)sFU4-TP&5$g>U!86?=-`c=fe+DN;6jI+4cfZr2E(`fi2zB(? zjy~JbXFK|AN1yFzLmz#%qtEs+>ngwk9zU4aBSo&uM&zw9)4!GzI*5$~ZLISSGzZWt z-R1Z;dg(eRYr|_u_}LOI-I1`n`ru11t$vtf_v!Q~_#7PU?;cL4(^rpn2 zao3NmoC)^Ck&@~aG_jF`7}a$KUHaw~WWxA0m`QVGV^qWNHm98kgdUNl`%tj!OseFI@~K0P{^?R6_BT>)YktgZ+I z)|md%1&80*dJD++a^1R~6K!&Iv?smkv%{m^_8zq^VCD_LtVLfKarrpCk9cIWk)WjilNiJ_$CV*Mek7q<%k<#>0CRzeo0u(F$%C!=3-H6JFk09-?P z)g_?}FgUtvJK!=5tfRp-aAYua{$M7-YmY!1Fcc8-pqL+qkk^9KYi#=t6a_d5g=SgI z;;0fd#i_(5!ej+~g2eUUqqsHJR7u4Y_xs9I?M8!Iv*a2Ka|!3POMvVUBg(~a*`nXisS98J!H-%4=G{*AI8TZm_)dfh>C z2t$y&1|(|9WXde;vo7+uIfS*#;#Hjd<*YN9lw22p-FSbv8yI z>e;}A7xLmj`s8)3iO3fbpV{tF`${2CPVagQ(;mnUJ(06< z7*VFL(h3Y;EP+oc0%MisPOjnrmp0${Mm!pwE7%NJi1iZRcF`XiHXqvM>6hNUp)zmU z!0`qw$^N|@g7IQOAsanRYupJNT@}xDl)=hK&iA?%aeGXjQxiGzg7d+mR>xcJ##`?C zCTkllAVUKg*Q5!hgErE%{jlnYhwZziK4}wZ`6je}ydTjrm!t;=?uf+h zabI^M61yN#a6h^pDY4^WII8|P;<4M#Pq9zTks7;U5e*m^^c`XG*0cRJ-=EiFe-9r0ynF^{-cjbS) z_T6HA#P-Xjw^(snhj#n?k~N2*xp3|5dFB494rtVi&(&{O2+nPZIHjMerCSh+YA++= z`V<69i20v|s6&+$u#tDc9$W&r*oE!6zgg=(IKRz8L>?8rg|M+jfV+hKGea*)v~6p6 zXk?G>mTjI|xug9i%s$R3cJQtCPSJn*z-1hNdK68TmtYWT-pwra?!zv1vv%{A?RF|L z)j#))DD971d)A@8jXXB;*vMl;soP=k>lb9{JJ4lRZ*TMnUJ^*@gCBin?T0`hfAM3{zfxvo;E%=^bb0odS$vwamPN4UoUsF#@^JaVF z<{%a_f&$wl9Z}cVxQG{v5o>jDPfVC#fGAz)mQrgWUf z;Ri^u?Uz<-8S&V`2~-w4qe`<8iBEw}0IgA<>e23tE>B(4_6w!f+v2nxUALv`PBh&O zUvIDpN@T)%@%CaNzIiQPc?mi9{M~p77nnffRT!z#60d#1T^rsZA(;FpKfBsRAH`ZR z?h$ceTuZbzYP>$0m7bkfrLj!wMc!NNB8Ev@^fheW6@kjH6kn7+{>Qe<53TYy@r!W@ zDE!C=cD(UHF2gxw;>HmAGJL)f4nF(shQUhO@W~-~11(XPOJMo-cw=XGcOojH?#?!h zyW@@L^Mn1#{@&rv?m@WF|L`zj@qLD#FD!U6dgyrLJ#m2htBo rZ8~Rk_2yQ5>+4 zhLL(9Rl!?9dAZ@o_*5+5$uDo>_1h*Gr&veT#EztJafeW*Gi1uAssLYHEYK~qDuz_U zZ-rS`vD?Lk1a<1JAVEs)L3!2}I{v$27Mvz?&)PA!M920GCbqTBhp-(Cqb;v@gSKYb z`M`V5)76etC#Ch`i~i{Y0x$Mv^R}344q_(S9 z>tKg$()^(fY3h*_HMrkbFfsPg$lv&aR`(Gvnifx^fJm3hWW-n-?jxHFvu zHxUI^x1Gc2&yEJOOiy*lk#&!B?I$WA9>L;<>9h&W;|EX=N?K2~SJ3wYU&jp(ruFZ; z5RmkZP8vO=8UzQx~t3Xr;G}|;Gr~Ub4|KMnUce=NCurr?>9M-QBC;1g#65y?n z`Mb<9i|<6%pbHdu)lS`j1>PW9ir&J4uefBU#~c6rEATM=`wg;|kOja0Yy>}7*uhKa zLhRFzQT5{Bn`hx0rqC*_Y^&D-9og3~SJ$&IeI$PP&c8O28#4+8l8d}oG3wxlhdtlR zcQ3eclg46_+IYY`+W1@h5Ov!5s*C8;9J#Fp2^#<>+n`Oi?!o0`0@G6 z*Za?3zubTM{Pq6J*U$G~KYzLZ`sH(OLPQLXx7C^t2U+Rss3l<;vk?wG$VPyhdHH50q3p` z&TKx_gY>P@h^myhA7sHLQ}ndj&ky%|TJOGAdpfRmX0@r1(z=UXenPES(`F66DfGu5 zW|eAG7DqnRS}bQeZHj$oI%~>p&UD_q$xh=YvuX1tv&Pe(HJ{6@`CR7B=Q3};F7tWg z>Cc@<`ljqNZFxPqsN2`ujJOL9ukvb_MGVFCqAVB1)RGKKq9 zVwHId$uc&_$Uo+h0VVt@756kd3@k9S*@29E;v`xU_cTp{o_;%jb#eNxKFL!&ln zt4z-kQsMmS@K0Cx=7n_)ToYPnf&QQJ2G++sg-tc$o~ZA<#J+2l!>_U6I*B*pJpuMGmW4u4m7Y8o{Av26vPaNRShdJ zx7GGvW8z1y1#fkxQK1E>mw-?4gRo3Fm@+xh-w|8IlPwF9YZ2NQ{rqYCjGyr{e#X!E g89(D^{EVORGk(U;_!&Rr=TUtAKj_8_a{zz>0B6=ozW@LL diff --git a/extras/usd/tutorials/exampleModelingVariantsKatana/exampleModelingVariants.katana b/extras/usd/tutorials/exampleModelingVariantsKatana/exampleModelingVariants.katana index 646d800e8cb33285c5ad2335f31fe93d01ee1bb6..4492d42a00749580512f6aa9730273789287c1ea 100644 GIT binary patch delta 5394 zcmb7nc%$YN1-pq@+4s{w{#WOv7?JkhODh9mf;pgG|-@Rs*#%GAa#r3JfHpF;B zJ2v%kUT#c9tlz)Ha{pWX%71 zM?R6wsD{- zI7W4ZiSa2TPc!Ulq2oU*cgVc?j#M|XkrJUc$tqqqLlTxdwf?N%#ZI&&W+J7~MTkchQJHlY_>Bbw}|&@=JC6W zkB=e|!QS!iydpyC50Z0adB;D&HthCArcVywc(=Yq%i{msW^%nFsL3X#)hA z;eC^jLYAUnU80HKbM4Q0L!}j&nw2)h(~`6~WKibJ=-cLuaTf$D5q?5G4*)^|H?~`n zO+D;dT`lnpTZ|yRaxCtH$au1jZ}1TKoD$Jqi+TOyZu>q;g3azZDaM1Oltl}t>$J6; z{*wftls7=ldB96e#-2Xxj*B@SiKyUQQq4*To)cr}lnx?PcEM`x3}r~KZYj&r3Sd+c za$NFNy(UwsrU}Kp$08G!0e+U7^#8N90)_vmYh$M0$?8GBJQ5{Zu?_U4mY+A{LVNqk z^VOkPpDe|;9xi4?6raK7wMHa{SV2YdM#EqzUZqchunjo7r-ONa;v*;ix)Yd-B(q#h znb#-XU8`eKCdQk4KuLWwDBz1T7K=xnl=6s)POw-3%7LR@wOCgwc zOvIGF((c*?KSX-s0X7ElAE0ltm*e8EIEV<6y&{I@%v*OXC*Kz;veD4As(G^&I^%_` z|2u{dGU7VRFs?n$`R)a0ud9+NHZepi2$L@D;kCevu0@MdYkwj$6z;6p651F+TX-Co5x9Bj=zdWlEwqjAM|1t;9zFCP9x?Q-Z>ht=D z>Se}>hAX(P0R*_{N4xT8Si0UkqA?Thf7*p%uLVTTuqHxPC#@)IzJd6W=L&fQ3n2`y zEPLF27v7HJcJo5Vo_HulXhsglh=<@y{+KZ-PjYlwdPYK@&dj7%H=zZ70Iih85NO8#pE@-VbhhncIJ!^nrtYzQKrDR$cFV%lS7)?706V4aYD|Ii! zzGw;(@ScKK1XJvP^_?3)^LW^A{Ym1A$Qag`=V7ng??TRbkDLS5qGlCUlFJ}d9z2?` zT!GTMapbGZjlVp&qbij>-xh!2j2xAlCH_L?e+Ui5TT8-kx$x2b^jTs?4)!*|=+N?(3MBsr-36~~B z)b@)z&gbQudqp1SG~Z`$2^9nq%oPBeW3evQa$ftfPp022E|6nYwtwcHlL$~p8cw$a z@%?LY72q>*KVQoEN$}`S6wiVrw?oVCndkoTrXugW%}?X2tVg75`p6o!p@1KTd8Zzl z?^KZ`wfSRIoBkw^(X5$8kt~!~pNBn!s@C6}>sE;yU#PvBEU1)c{%zncv`GoTmr|d* zLmJi^Gh9?`N7)$7Q~W^ga0G;4x9ygGxGtCmQ;&@%2uZ2U5BcFn2*b2VB0wJKGd%5W z+;df8=4HH+DsQG5jjHi`fj6TQ*PDL1R#M2uBZP!TPY97bv7!f*7{53ag!c#)n;ytl z0PCb9I6`ukF8NrytQR(FNP*hT1{p78vd!{>SXx}DLKVZ@Xtjuwa9?CTPv+mkW-0X- z&oKrgg;Tf+jK*u}`-3(f19h^V7UZ%#xN5y{m`6U}UZ;-=r`nS=E)%Eh%3ROx48>%YaWrX`vlMBXqfQ zibIUA?u#`Jlgn9w!38KrZhy**8#DjF^YgZ>t^E(?qwe_DeAL8*Od#6KIy6oCcBhH` z={&~y_8@KVX?Ya*)+}1KQd^Q2(ekjTd5J>bg{e@BJ7}LUOk4lpdTG;E@fB3cn2fv5 z^ktic+uL2*59aRf3e1&ZEAvo2Mf&2bTcULR7OEt5GusFzQai8n)zqZWN}{wkbYZDh z&0blgq1#kGO-Y{|L;T*J2GMvL-`LFX<=VqL%$MG?XsOq6n0qedq66CQ0TuZ*@!f%) zfkL7+@O-zQG}fH-zQuLS%aa2={f8b`Jm>aUM_t)=N}EEzloB{ z$mwSk0fVGGG~DW|Up{bRU}}aJ3AsIp+4RnBe4`aUR+vfXMj=9O2RIls*E^a#FN`GD(!KcdcoA7%c(fOm~D z;?o?a@FP%vy>wMB{)tSgpXra=cBd%O+UhPSS?;Mz=~KW_BB&w+@pA#Pt^K~XnsN!d zM>EL%E+W!Jg0;&dLc6+B*|q*Py>mvM(cmf9N8E1PipW-TFO_$*4IGLqLlB^`i!7q5 z#er{wW6MHYCJnva>K%q>l4NQE9#Rsd#VGH;*A!8r{4ZPi?_0U>W;o?=qY-qNT78go z6dad4AVW{N8T^%!&eF3}cFHtgwz;I9WWPwjHS|@o0ZJ-+*6S%3BP~PHVfVLLFxPQ# zN6I@aYf0*gUOUj{vOwPF-9CWAkgDe9(q2+ZT9NaO=bLYk%pVY9P}i26!{z~RRecEN zA^$ad4F>NVqi_`0b6A?aXw1j#tny-Nvb~*GiKtW-Gu&ORSYqbckm$TF=|(EimEi+2 z<%%EqjqI;1uiLkbBXxrPmJ3S`RJYsjp58nUzNgYYk=5Is1 zGynZLd>wFQ$Xs7&j=0B zD0mRrsZ{iMXZ4gG=N!_e8cG?!2Wv}GdJI@-iSnLELxqL4sk&2cpex=JROi(@6AApI zdsp{e3Rr9pJ9xih-4)^`6kO4$enhQVOlL4(0YR6XMiFEFl+kXan0Jrg_Kv{`DRFV* z{pIZuB4c~d0tFWDyAp^#P_DmG<|>$Rd_{1P;J|6+D40Pul%gv{&|GOWxk_3wsgqwQ zH`1c02Ep7WFW4t*dhvmC<$dFC7u}7b?y({Q=i^rXJqT-AusrZ)>gjOVnqOgi93MbehTLbQEt_ago*(u_hc%Z^!kQ7L6tD_02QGJ_7D3yr}1-)K35P=ww&3wL~e&Jyc++kzbRK0WOOTP9J?<(^WH(^8l45@Z94f|6J(_gCOp-|$ol zppvTerm+r^C)^Y7E2CM2SGl=26p{QS1R?sS)z=@Jq#$XtH9J^!Ipt{?(+|z|{zNUm zD$cLG_31zbd>Y6ODU*Iv6F^6-i4}CT?Tgy=^A9LNP&eH5>SAdG2xg{e6gw1QP;9I($|QRY*K#j`ezF1X+NM&IqyhU9)5 z!(a997Bu;}Rn714H%q01OlH#JS4u6fQ#ObhxxcNdENuA=+rtQ*&4>O}Zj4(F#=WnG zsN0aO2z`m@d%*z;Ug`bx&bH&>@>7Ruue5IDk`5Ad3(pM`B!QNwy^VH*IzZI`XH&v% zCw0~F<#8L-zPWGfqx7c(mN{0e&2&`mV4VS*2eu}?;aSh&(Cbo7rV^!0>lvsbUZ#&K zx7ohr2TMVi8C-hD3eL%E!RzH_TQBHysS#NgIcSZEv&y^@C*#P6_|huCfT-I*k2uSX z!E;QF)GXkOkSkex95huBT+9W&pRvGSIu2gs1>c-s`KviV6*-NxqdGzs&4oFw>+MFs zwfVoZkPCdrHCO@`wZ^GVEwh#BUrf}#(M9RSSdjYu*!m+pq$5$9HS?AxuRdR4XVuzM_%MgO-cs4{BeCY_ z5aq-WQx=>S>)^jq`UkXR7&#uk4}!WDs;336HQQdNOGx{EVryQPzacSnsUKFcqWc8= zy{CHwDWY8)5|S5#JzPrFh3y$4cXq#rvfVb)F}#+@RVVae^swb#6%`lfA6pC5|8L2U zH@f0H96c8-4dsQ#TF%!2&s02B$f}*SX;ePNR*J}uQTKYp8-R)ftw*uBE%DQ_wf;29 zj;wdl^!@UjvNed=?p79jr4!*WRYvDO1Uo>Q{#`K8o*+Co>L2<5SCt)BiF<(>EMo$( zr+D-9I>vkzenCgX&N5O}HZ^HGskM1-ve6N1?FA6E1e*1(c_VxQI}8LVHyAqLp~}{0yi=)X3Xuq$9V}0dl1R%(UEGe$FHe|vtoYxeu8<@1 z6Ak7vK-0tB4lIyqBd2Rvcr#qD3FfU++D%_d(f70XtdO=B5AB3QK`ZEk`;7tS3PCG4 z;g#+tMaakph$*7jyR9^Dau2`f<P(ppT&NXs~+B5 zVW!4#vFr;G%-ZeDCM>tU@-HpD4lQS>79sPIq&6mpLABt1Kk#LA9wMZ&#kD~&+x@Mx zURuL?A;FmH#RS&{@>MG1R!WT-D)&Oju4jRkC;xHRluLHUgOQyQ9B1y`>!r|4vj*}|b@Z^~^dYnUJ+u1}bJ0|L#A2pjtrV}dk69VA)$sVf zug196`OjXT(?ry2E@g{f$AY^Wt6keGlbx5hSkqFJP;!}@-UWemBc*nV9zQcGcbDAF z!VHbv=%)w6is{Vy!YqffdXU+gs>yHiVcMo!0)XhUq|rtEy3ZNWVCXVfS&6PaYSUMo zcS);sr62sWMv=7c^mQPjD>IzrzwaulfPPo76_KcGmM?NsOXrId?k* zMcQeLlfU}|o3kW(re^Yb=99?hms|P4HFHOv`EQgq!p}R0Zd49i{+@QK4ww+^e5Ehh z)B~_*mx3E4=iTHS8h0SeE>9I3LZI7K3El~f9tk3MryaVgg!#w0j3WmIN;)xwjtgbF q!ev*ay?Bf-efCpTO#C)NAmzP|D%<}j3>QD)tivvRG0{%Z(Ebmz?w88| literal 10602 zcmV-wDV5edYhiR@Zebu{a${&|c4a*xbYXHLAaZ4FWnpt=Jt8tLFm^Q}AaieZa${vi zX>4UZB4v1CZE$R5O>bmnY-w(1R$+2!VQzGDE^A?QVQyg}Aa-SPb7^mGJt8tLFfK7J zFfcGMGdUtY3LlFI2)$(#R|5Y4?LBLA+c=W*`F;h!Zn4u&K8yWj8Azgl0@2K~_wx-r&<+Q=A6G<+HSCYbuiM$ z>U1=mO!VF3`&S1qjfpxO8>7K^_xSUx15J&_f1s>w%L4AJgTN2Lf#RAQ+`128@Bw#t zpaitH%k=lH4erpwbikIhF&Z1={y6jWzVPYi>{C+lKp_PW{_Ecq<*zF;lDTL4xaR=) zc?d`uT*?hM*TBydTjOz{R|kLm>Gu!@e_22m(}x>GzkZDVT;UN#-(D!uUj$ra2llNU z+%qM0Rg1p-E5U&6UfCNmUegKjPyL|xl>mWZz(RuO?2%zf3f|e)3b3uYq2t7bQi$)M ze`C9=)31!ddQhK#eRQWFEkfT1E(_1N-xfG&Hvw+{)Lr;sgF7pjFBJF~G2DK9U|Q#{ zbI<7~?Izl_W@HEZU}i=Hw&uojz!_fb4({g{)3-6yNVNNc>Gc7EP8itG&4I9ck@jwA zgUMDO4o7K!d49xp2R-0cjns3(mF=RKb=4Yzi4X`bXge3s3q6*EOwT4LWNIAmYUIG7 zZKVT#XFDJnYc0^0xPck?Jp}FoNJ02+uVN0+Y|9M1_+dIdz1;i=%^EX|7{rxtdh1zW z27r>>wF6KNp4;TPAZ@IH<1r(?ND3n5&JJ*41^+KOWOKnW4B6cZ^HSel^|D0rd* zJRL}>|5-v`*_gos_qI~J9RRp<A(POH`C>j zn&)S@^Ec5*GmE47dLwjm>ZUE$qH1rShM`9|1!9W5^?m4ndF_~sn=dD8u($#KH8g$e z%Ljnx69qZQHa5nsyLv~!Kq*PnMs{oPA>oZ6edh!48GN|}9x#J1XEy17Pu@9;`1Xff(N=(uc2?@UYmTtHXxD=bQRBs3(Q3F%N>vBJccBl zvrju_D!@)n4CBe#b}R;Uz$L?}H8pz;A3OGnW2vPzX}C-fC&#qRhTE%6!`XvTHfb(S_C&2UOIA0WetBDvS}ee+&?E55=+ zPY|aNX;o^c2hW%96mYD$2>)bXUpB zZ2e=nmJ*>%!LkSG!t?Eo>0{nw-V>1UK_T#=^Dw=e8yMoDVjOQWRAqXeV*^WVfxi|I zG#-#;lg>=%JzU(JdolScKPrFlim>NH7`**GG@UEhHh^-FUzov~0ZdhU4Y*%xaQ#Bo zB?H)}RCrDoalD=m6l8xU2dx7o2=O^@7XR8U=%S-+ER<*|574qKprnSrtDz1Vw$Ur( z8+&|3hJ8gf8qY#{FARWUVg|GU{)(`= z#-B^z62XNqZbXkzSorXuAJJySU@@1YB%ro5?q|VHo(%t}&oJ<6no(8I?xZxS6z@g# z0r82RXr!CyWk>@v;DAMNVtOcaa=JZHU08hH{{^>}j&)<&ZX?A^ORza$$pS_mJO#k0 zWX?cFpOl;@VqujaR$NRK1;@O;_Q9=fGU~*QD|2WT?F#caD_jIu@CNL-GQV6Vl7 z@vaAo+vTeyxG#!Hm@dIbB4KCwXe5mK);!l;N63y0p(|(D3@7_*jA39HR0DVhW;n zv5_(%fDq67YE3R`?LZ+HD}i~_rmoaf92n_H!3O&G>i%A{y+0vSNt9<<(-f`p@Z$j= zc?aTJu16th4n^bTh`U~-dU6+-zOry^&!ZFWn3%fA^)}UElX2m>*Z|+mFK%3o!||Wd z;Fq<=zRV6iw(#rK71N-Px1r}kJFx|YB|$@Ud@&x;w?RZ4EG+9Gp_H1Q2PUwD9jt{0 zOW%DY#nUnOwNhC=Mv@QRphCvpnc3t8LzQ-`M&$N9SusTbgW43cHp-4XYhg?W+-r!n z<Ts%D;v%D~>&O<<>%2X0RgXKJF4nc4~+77@5 z9aOR)dp@3PEEC$hsK}ZyBqx-=AO6YoAo@#e(ii=Bp+tYl#dq}W=*2(8?5B_e1MZy_ z2O?tj&v^9wWG2&(!+3_tAp63HE3&}T z%7?n9y-@IfM>5Ss9uxB5Qw!Tm(_Ixg&JEO7fWL{={d1L)hPgL)ia zz5k`IeZ9ywuXhr0#$IgXG~d{0F~7AizBGNHdhV*`VCONDn^S|HhlV=a*&O{Inm(8h zbz|c-x*~R;}S8v~Re81!SQhZ<6RlOCyk6FlM{Jrpf z<6GhTdK-Ly*zx_2?{|FvS@C^sqUzID_`ar2zZ-d9`$qV_Hf@9N4?4cz@%@hPKQF#- zsMA*XzBW|H)9-}u){lRpqjz-@L-yeM| ze1F&m-#0qG-|_v9?>{TPKbfl2Q7e4kP>0_Q-~U$bb+uORb@h(#cYMF&`_GE+k0$E0 zjeFg}xUUY3?}hJwEBCsZ_`R+~oY{E6LO(bs;a2|_+!stRmwhMIE&++6nvK068w@)M z+UeRDh5I21zCw(Ox)#aV&Pcpv-(CcmpLv*rV3;c+?{l35X?ryxB1X=p2^b{B6Z z#4|od^@}LLcNCNW+$E2r$OJXr;eCKPzx9Gf)$_rUMAb?{hdTHT!lPM3ggZ>Yp@Yl2 zl*cbma`8dhiw-hu;3!%a8lE3NS(~@h3ViW55z3hD>#dM@V5e} z%ms;t8}Vtv#P=m2{@|$yOcyf!_G2s_U)WpICjluI_R?OE;1DD(#4eux3My;h12rnW zi>yGZ3B+cJs>P#YI!+@PGtzoWA#qtkBFQ@jc#4>hgg?+w6Hx>W{KbK$MOHal!_cu5 zJ8lU@F@qJKh(O9UAhCNf1KMCFlX$IU-Y5PSNxWg)Sn%I_6ha$#w=Y;#?lN`arS8!J z3FP@GxabFYYDpg{JU$jU^2%+1;Qj2KU}X!JMQMna|8y zP#S(LJ`86M!lbrBYAdvMuev%3H$KZ`Ug?pXRto*UcL#mP>a76meI(zqPxB>2y7FwM zr`9g-sKv#J+_uRkbPyRS?I&C=?X7gRw@JbR>6-BggAEQLTKNJ? zX@$_r%uVq_nsCJ==ORG*GaU!s0gE^rI)wRTvc=)Wf<@(Xk}=N08@vtj-(CpwVVaUFjO6; zphrfOV)J6_|BS3tw=xbA^p5=s%BVxFg%aYSD@JAO%&LI1x>ZZ{bApleh1SmN2KZv!{zG;`(Ln zWF2GwmaNarwp6(<`xyN`!gBUoHkpQ24ZUR}Qsp?17;%iqQwvE{vdLO{4c6wZolyru z*SRO(ZL3t0_-l`_za1akal2XQ0sjg@C&5^(#8zB1$EEB=9QO~?ahe4azp}9`{DGEF zIbU3ldSjuLc40SXfVLnKi;7ffpR*lK1KQs#1AW?2182Sq$=tWw{)USKTA$P&Q zYqQW8+)Bj~3&AWf7dP=$iW-+8(|&k#khuhzdrbLyeMS><>f%za>5$On)&1I; z(h|MWRC9;XdE|d=lICKuzCWSLB9-tSmGU0dSq18fLKPJ~QfZ469tIZrcuuphvg}4; z_&GSL$G&DO)a&(iXgk(>LMiWU6db$O33OtDuZG~7say|$Gkj72{uv$sRaaMcx?wBS zq;DTck$1Luy&h-KfwM$JD(eeH1?%-fC*uU;W(AWw(XzgrZ1GAB2D@)ige0xeA9})k z<5#)d#e1Ay+j076?W=_O=NY^Ri{~==7_REG2Z?-pY~7Nu9M*Z1#fz6wtGFjKt}Jww zjl#`q7`hg(k1|dV@cHr>d;`p>kPty=+Fq)iZjft%ti5hpCL6&noSbfI)Q@K7(wGTPuR zkPi5x9jwzq7axG7BeNvJ+x{~AnP?<$`ft+HY5F_Jz29c@m=if{nEotWo*6+bT1LeJ zSfllsLf5Mv>Fmx97VBi3$*+KUw>L&zD<5Qr2PLow4%3qxX$)c6y-AL(zr)br!|5T* z;ongh6XTXRja71UryZ4r31S8#PigxM-zZ@CEcS=O*pKj|vWVrOpCm40E9!zZ>+By! z!~KIvkH3K!IT+YxN>1FnjCz|e0Qrrlq~b2Io@XMIoM4G9hqJeR^$LekcaN(a zYjyTOyFtI)eLf=LFY35EGe=Gv*m^bT9=DoF&zVgUKY1bPkWKnmg6jctj(% zC6-%1#DfzR_`q@r7P}iD+i}8;?dGoBDoxz!h=~}(T#rVN#hWn~%w<|31UzxhrN*<- zB^XUZ%kwlSy>*V#3~@Ps$xR?3BIXK|B;`et4G8pHEJ)MZQID}Styf6Xaw|E<0VD30 zENc(<8_j#lI`^R$IxCbe_>5TF5(^-kNhuE)>k$taXd`vfA5A8jAPW_!{lYW_;Tq*fLO;lVKI55@` zp0m@@ScKLeQ-;=`rVy=v1t~f+iH{;n>vgwOL;=NX4cXVWV+Z%0MBQzx-?&7rKd?xx ze+`-X8{z<+WZkgT?wsPG zR9;z7Oa5yock9b@SRjxVUYYJMM{e+p(kbTlt4sH*H^0BAacOzshc4NC?#YdG-lv7W z%$Z^)lNwjtBfWn41?KUN^4_I(HCo#jm_=}xS!-nZNMtqBi~jt%6|>-Xq2okn3Ke;H zr-~a>69XOn=qW zdyj+S())|Jg854>#(amB>xgh;5xIae>;s`w3g+tj=ab^1E7oGDhNgnpNpqDLQacGMr zhfCm?Bv!{E0?sno%~iD*{fqYIUa~jyMF$%A=SWOONQR%ZdW->Fxh3Q05Hx`Jr+;5I zecZrH#PzV`Kr4xQ(P9G5_YX&bMatv2ObG(Sx~CI+mZK7)0RcWzJ%3}m6sQ?}qTWXO zgv?PpdeIn+A}s7ocFHk<%WbIi#|MH#O__U+GILZh8~SSqokKj@!*Y9?ShI3;q}WS^ z)~Q<187SikI#K{$v`T4@?p}vw#`@$M;_Y?;VkxsOCU;u?2gj%07@<30Wzeci;T5HQ zRAX0&7l{?(1ev3I!hsZvtB?r1g`sth-Mov*7;bxOp`HK46q;5Jad>ONLAy-4b7W?6xan1^t?pJckk#xCY zVloKPf-d3loSVxB@V#Q-|L$F{I9^vdkE=w>b8(H{NB7F{dpZBBEb704`&E(am0-x4 zqEIo#cT+0U>Fz>&@1}|gV#CI-5zvIuc6xUczZF!pWS zW=_gTukwY6IHx2mi;Gk*#)@E&9%om$evdhstu#1}7(eItb!=~<&D^wIfoL^mws=FF zUXV6+7eRu^rM1qWWiRc$)El)RcmtNU3uJnKZQeAP-3uSfP(+KKiYDy0FW%GHzB*B+J951X{Bx=wN}TblJHIWcRUd|Wy3{nf z+C`CiS*HIgvvPsSzzwAKh<0@*i(0T`%#y_*+EvJbRO$Siv%_SsMwv&!ekl>>SC{Mj zD(CnrZ@ixcRnlr63mU);4)<;6+`Y}WG$7$W0ec$sfKS4a5=O_lo8M1h18;YkYc$bX zE-*94VpSLJEmKX8P6=Z6t!P2AF2tFQM6E)Z0Ocm>1aXOqxe(_veFo4gi}O*g zA>p*S0L1p@d`V4k0K!8G5g_Y4&NGslOUM0A)M>vz7>*~?sW#U8#z=Ht@j_Zd8vNW| zutBN&!Za1@UQXQ;{L?pSxI;cdcr#~Oc8KKb*)A3jOovV1r3(@#UfX0J%jYhs3Wsae zp)fZ4hzx0FjiRLqjHf+!Z7+0)goFffIB_5JLN5;ly^dpw%`UGL zYBZ0&q$5=DfylSFIp}CC*d;zsR&kPDlOi_o)ss*;lKA0_cnT_)kPwMN2SaiYeTg2Y zzvBX5;&QpSU-H$X0$*~!lScBbMsIo3N)u>RVy|!%kA%tS&##|;`||5=pT2zh^|vpd ze*5*yZ@+%}^4q6hbHnlph`6rMsBn`7Ly%aIapFnbv>gv1O>Se^1Po$iiq1WzIQTs@ zoh!JP4kuHCT$(X;RJE5o2G98aG;f%+v63%$6;u-C0gZ{u6P7Q6^D&Y)NV>FqJCWbMdV)6tpwNXbrT;idw z^K!IPX2VoM6LqS6E|p}zvpKAgy*Bir#8hrHt=_C`G`-xchF{UBTd`lWqOR4gsMkb} zUU!Uo-7y+<$7s}@N5iOz9HZ_S`*p|IuRF$m-FfWy8*r_v*IfIq8$h)0S+QxKP;R|5j=7bf?>b3orfekJ zApaweo~?P|Jh|!WKY-v4`Zs)nZcJBAZTh$lE!5!+z4PHlICOzio}9d{HjB)fFbu`% zx5RD$Vl(T#TY%IZwa|~{AV2z622Ijp)BAgIo$v*Ad z7C>#yf0-$&Fuu?NW>yrr+_FsHYG=f;w~MGdUiupe4>s>dBO$p0HbY#o2*N?yEff7C zdnYK<3S;U%qh+WmXbXpwJa(wn5fb-wB&Q1(kq9k?_P7mDT9RmuL8?)7aVLS#cMddz zVswfb6qj5r6ko!$hM8jD<`_MZZ*!mVZSM0tPpWeSXzFw_(X{b+(w`7TjW*Q6(qrN^E4F(eu-e@A-SVmq}$D^?^m<|o1zQc|6IY_HcPw-?2hhD=!0NvD+1pco7 zm=9smW8G8dIrr3v2J0`%GA7pqx$}AGh6q^go|GCKa~SJ8Ua*#2p`fUyNFt>DW01$1 zvquuq10I7|pxZK3A?T!HTu&mDL}2=~O(Ok?g{czA8dERV3vWeG2+w_cWoIIhQR_6R zU>5{E81ctj8;NcUA{#=jq%ktJj1tooA!c5Qm7l#QffT(KQndDQ5>edui6gr=kE%`<0BP_YS zWwkWI7h{%&?))EeN?SJahkq&Jm%uBSIZZx%+z6 zK9_1SJHzh!UIE=CcGmfwb$(}^-&yB(*7==v{#UThFVVF}(GPOTNF*AFBI#V%iyKDa zRn!7M>O~xqj>`9$bMUY=1xs-_B%T!xuXIq_mPi7x3cH-hLjkwEg8uyjDuFpe5Sww< zJb2~6YY}IImd($~^+t=__&x~fk%T}z$j4xQ&$El?ppOvc`$|s&u97!045(rOd_aaVicu*aznKX{>W%3AJWMuLWJOg5l$^trU)-eFIC!W zWs0c^#imr6scNH!hN-5?#CyF&gvr6gvb@xsmpa)kO{_LjO3;5I1h9OqHCw+`u#igdJrFj$lDqaETO74dgig2Ej{H)tL19~Ji=wB3LRt6zN| z9W>uZ2Mv*3>ipLn*9)%WXsdXZb|BSjB#dO7NC%O$t_`Q7((FMZKBP_CGGyD5@F1;3 za!QaLnwz5e@z!gT)PJVy#`Yg_Czk+hzrK9ee2;tLn_I_lJBHh#`I}<6UUK^=7g<7d zO^b=Dx@`44-{d#YSl!bExv^hC5;EY_{e`FeYX#Rrn^b~2$wu-Rui1>$cJ-taRW|pO zN-nEwxJenqdTvs3_k*=FtRw?#_13s^l6sm>Qt50r_LFMTQs*bda3m&as8j;c8J6)m zc|&uKQo48!*|Sh0ajbZC3r6ttF`YWGSlzqzp zbi@mAArL&Ejo=n?p)EFHAX}eV)WocORh=DECZt8PfEMkBvycyHAaKNOH;{#N7z+_P ztPEix#&((QRDjnK4oQCsMg18UNbnrin=nYe*xq7J=42F4lNmDy1`O#%#Fh(qG;24e z39izPRXtf&rFE=IfK`>r`m;MbSgccaMStlDcSv4tX{_LiOaXawgM%fm!*4@lFiYKaUYId8& z!neJ2OSv!+O6(y|;O4q0rcP30Z-*IF9nTnx&kH|v!5Ix=pQtO*1Dx23MwFQ`fynJW zA`~<0LRbl8Z#KZPb8heLD1I6%eI&FlOtmI@qIxJ=FO{^R zAC>qa0S0Vs6vUeA(jH10C+*-4vQ7P%c|~7u=sNoez~hV4+`EWBrT~xEmz~mJ= zK&3X^RD**K|DF!y1=Hm}vfuy*fgj8INgK%(%HoEpFk1i@&>X|$fl7g)sG`A1UStZZ zROLc~ejXlWVVYIqcGpI>-W%Xl&w5fph?`i}&j|PzX;Ovb-GcP)gEe#&2Sbk()3uan z22i6dA$A5h_tN;*7M4Q;yaoM4)c~oEZda}#$4}+fon~Uk0(lTOO#q;iBFg_Oj~l!| z*SR58PXqLd)pBpQ0dOsW^9}Tl^TztZyH1a)V#LLGhUrJnen_zm$Ic_{NbMG2i}xDB@|j&yYOhVU>P#3YGf+&&Q4)^~RBy*Gz4npK z6C><3k|CB}QR<(n%Z2r;l!Ys`dBf24VFMQ~ktNbc#z!{&RDx36NWKNK_T zYF5ob)DGAbO}uCg*#x9n!C?hp?<0FI=ZeY25mBRXsMXb@@QrL-(#x%Kd9Pf4uC7gO zkl4!aY#(Jev(j7!X$;WHj6>2ZP% z#gSF|^%!3!LF1wBMHP`38JlTTSx5;jhe~P!Fk!Gl)@yHmBlWdGb)tKm`@vv|++7D6F@^+L1u?n*# z*OE0N%!tL7;hUQ-?Jcm%Z%TPyDutsiqvQF!P$boad;}Kwf8Q)f-dfiIM$GXgD>Psb zdJ!1HcJn#^mu9UAxxtkCrj*U)o{Q1LVzw?0p8&SfEK`q(FZ6qex$(Rpp_M4+8NUPxmlBj zDupH=`S71PS56Q3$OF+$MX%~gWC?H6ies(1ybDY}6S_+m=pj=3M1VNYy@|H< z)HosTYoy{$X)>6O49ze`Lrq|wFv+hW^%k)gA8jjh-`^LYi#Qw8sT(Z;Vq#x7@aLF+ z_lafREuZ<~guGoU-b%bxX6Sutxp~XSlS|qAeJATJ$qrhM#XgqrCz?JUjwSK%Wi`v35UKwfnNKPVkAOKOPN@sXpyb`=Y|#_nQQ`HgV`f zO&yP?`oQQLLtPu|EfGh5s%k@n%%ZMq!?q|xA5YaO`RM(@WH=rVJIbiYEG(THF5#h$O2p=|8I@Vzcq6H*2wl- zBhPP*48PL3ecRK@3S{yv)#@aFf9O8lr~7oD?$dp`Pxt9Q-KYC>pKs>#|E}iD(*TeG E0PpLfg#Z8m From 99b4f5f9bf540f063cc43f03b873e886ba1adb80 Mon Sep 17 00:00:00 2001 From: superfunc Date: Tue, 25 Oct 2016 14:14:38 -0700 Subject: [PATCH 298/380] [Usd] Add template clip behavior to value resolution. (Internal change: 1666308) --- pxr/usd/lib/usd/clip.cpp | 278 +++++++++++++++++++++++++++++++++++---- 1 file changed, 255 insertions(+), 23 deletions(-) diff --git a/pxr/usd/lib/usd/clip.cpp b/pxr/usd/lib/usd/clip.cpp index f6f8f52e74..137db45373 100644 --- a/pxr/usd/lib/usd/clip.cpp +++ b/pxr/usd/lib/usd/clip.cpp @@ -23,8 +23,10 @@ // #include "pxr/usd/usd/clip.h" -#include "pxr/usd/pcp/layerStack.h" +#include "pxr/usd/ar/resolver.h" +#include "pxr/usd/ar/resolverScopedCache.h" #include "pxr/usd/ar/resolverContextBinder.h" +#include "pxr/usd/pcp/layerStack.h" #include "pxr/usd/sdf/layer.h" #include "pxr/usd/sdf/layerUtils.h" #include "pxr/usd/sdf/path.h" @@ -144,18 +146,174 @@ _ApplyLayerOffsetToExternalTimes( static void _ClipDebugMsg(const PcpNodeRef& node, const SdfLayerRefPtr& layer, - const TfToken& metadataName) + const TfToken& metadataName, + const bool derived=false) { TF_DEBUG(USD_CLIPS).Msg( - "%s for prim <%s> found in LayerStack %s " + "%s for prim <%s> %s in LayerStack %s " "at spec @%s@<%s>\n", metadataName.GetText(), node.GetRootNode().GetPath().GetString().c_str(), + (derived? "derived" : "found"), TfStringify(node.GetLayerStack()).c_str(), layer->GetIdentifier().c_str(), node.GetPath().GetString().c_str()); } +template +static void +_ClipDerivationMsg(const TfToken& metadataName, + const PcpNodeRef& node, + const V& v) +{ + TF_DEBUG(USD_CLIPS).Msg( + "%s for prim <%s> derived: %s", + metadataName.GetText(), + node.GetRootNode().GetPath().GetText(), + TfStringify(v).c_str()); +} + +namespace { + struct _ClipTimeString { + std::string integerPortion; + std::string decimalPortion; + }; +} + +_ClipTimeString +_DeriveClipTimeString(const double currentClipTime, + const size_t numIntegerHashes, + const size_t numDecimalHashes) +{ + std::string integerPortion = ""; + std::string decimalPortion = ""; + + auto integerSpec = "%0" + TfStringify(numIntegerHashes) + "d"; + integerPortion = TfStringPrintf(integerSpec.c_str(), int(currentClipTime)); + + // If we are dealing with a subframe integer + // specification, such as foo.###.###.usd + if (numDecimalHashes != 0) { + auto decimalSpec = "%.0" + TfStringify(numDecimalHashes) + "f"; + std::string stringRep = TfStringPrintf(decimalSpec.c_str(), + currentClipTime); + auto splitAt = stringRep.find('.'); + + // We trim anything larger that the specified number of values + decimalPortion = stringRep.substr(splitAt+1); + } + + return { integerPortion, decimalPortion }; +} + +void +_DeriveClipInfo(const std::string& templateAssetPath, + const double stride, + const double startTimeCode, + const double endTimeCode, + boost::optional* clipTimes, + boost::optional* clipActive, + boost::optional>* clipAssetPaths, + const PcpNodeRef& node, + const SdfLayerHandle& layer, + const PcpLayerStackPtr& layerStack) +{ + auto path = TfGetPathName(templateAssetPath); + auto basename = TfGetBaseName(templateAssetPath); + auto tokenizedBasename = TfStringTokenize(basename, "."); + + size_t integerHashSectionIndex = std::numeric_limits::max(); + size_t decimalHashSectionIndex = std::numeric_limits::max(); + + size_t numIntegerHashes = 0; + size_t numDecimalHashes = 0; + + size_t matchingGroups = 0; + size_t tokenIndex = 0; + + // obtain our 'groups', meaning the hash sequences denoting + // how much padding the user is requesting in their template string + for (const auto& token : tokenizedBasename) { + if (std::all_of(token.begin(), token.end(), + [](const char& c) { return c == '#'; })) { + if (integerHashSectionIndex == std::numeric_limits::max()) { + numIntegerHashes = token.size(); + integerHashSectionIndex = tokenIndex; + } else { + numDecimalHashes = token.size(); + decimalHashSectionIndex = tokenIndex; + } + matchingGroups++; + } + tokenIndex++; + } + + if ((matchingGroups != 1 && matchingGroups != 2) + || (matchingGroups == 2 + && (integerHashSectionIndex != decimalHashSectionIndex - 1))) { + TF_WARN("Invalid template string specified %s, must be " + "of the form path/basename.###.usd or " + "path/basename.###.###.usd. Note that the number " + "of hash marks is variable in each group.", + templateAssetPath.c_str()); + return; + } + + if (startTimeCode > endTimeCode) { + TF_WARN("Invalid range specified in template clip metadata. " + "clipTemplateEndTime (%f) cannot be greater than " + "clipTemplateStartTime (%f).", + endTimeCode, + startTimeCode); + return; + } + + *clipTimes = VtVec2dArray(); + *clipActive = VtVec2dArray(); + *clipAssetPaths = VtArray(); + + const ArResolverContextBinder binder( + layerStack->GetIdentifier().pathResolverContext); + ArResolverScopedCache resolverScopedCache; + auto& resolver = ArGetResolver(); + + // XXX: We shift the value here into the integer range + // to ensure consistency when incrementing by a stride + // that is fractional. This does have the possibility of + // chopping of large values with fractional components. + const size_t promotion = 10000; + size_t clipActiveIndex = 0; + + for (double t = startTimeCode * promotion; + t <= endTimeCode*promotion; + t += stride*promotion) + { + double clipTime = t/(double)promotion; + auto timeString = _DeriveClipTimeString(clipTime, numIntegerHashes, + numDecimalHashes); + + tokenizedBasename[integerHashSectionIndex] = timeString.integerPortion; + + if (!timeString.decimalPortion.empty()) { + tokenizedBasename[decimalHashSectionIndex] = timeString.decimalPortion; + } + + auto filePath = SdfComputeAssetPathRelativeToLayer(layer, + path + TfStringJoin(tokenizedBasename, ".")); + + if (!resolver.Resolve(filePath).empty()) { + (*clipAssetPaths)->push_back(SdfAssetPath(filePath)); + (*clipTimes)->push_back(GfVec2d(clipTime, clipTime)); + (*clipActive)->push_back(GfVec2d(clipTime, clipActiveIndex)); + clipActiveIndex++; + } + } + + _ClipDerivationMsg(UsdTokens->clipAssetPaths, node, **clipAssetPaths); + _ClipDerivationMsg(UsdTokens->clipTimes, node, **clipTimes); + _ClipDerivationMsg(UsdTokens->clipActive, node, **clipActive); +} + void Usd_ResolveClipInfo( const PcpNodeRef& node, @@ -165,31 +323,60 @@ Usd_ResolveClipInfo( const PcpLayerStackPtr& layerStack = node.GetLayerStack(); const SdfLayerRefPtrVector& layers = layerStack->GetLayers(); + bool nontemplateMetadataSeen = false; + bool templateMetadataSeen = false; + + boost::optional templateStartTime; + boost::optional templateEndTime; + boost::optional templateStride; + boost::optional templateAssetPath; + for (size_t i = 0, j = layers.size(); i != j; ++i) { const SdfLayerRefPtr& layer = layers[i]; VtArray clipAssetPaths; if (layer->HasField(primPath, UsdTokens->clipAssetPaths, &clipAssetPaths)){ + nontemplateMetadataSeen = true; _ClipDebugMsg(node, layer, UsdTokens->clipAssetPaths); clipInfo->indexOfLayerWhereAssetPathsFound = i; clipInfo->clipAssetPaths = boost::in_place(); clipInfo->clipAssetPaths->swap(clipAssetPaths); break; } + + std::string clipTemplateAssetPath; + if (layer->HasField(primPath, UsdTokens->clipTemplateAssetPath, + &clipTemplateAssetPath)) { + templateMetadataSeen = true; + clipInfo->indexOfLayerWhereAssetPathsFound = i; + templateAssetPath = clipTemplateAssetPath; + break; + } + + if (templateMetadataSeen && nontemplateMetadataSeen) { + TF_WARN("Both template and non-template clip metadata are " + "authored for prim <%s> in layerStack %s " + "at spec @%s@<%s>", + primPath.GetText(), + TfStringify(layerStack).c_str(), + layer->GetIdentifier().c_str(), + node.GetPath().GetString().c_str()); + } } // we need not complete resolution if there are no clip // asset paths available, as they are a necessary component for clips. - if (not clipInfo->clipAssetPaths) { + if (!templateMetadataSeen && !nontemplateMetadataSeen) { return; } + // Compose the various pieces of clip metadata; iterate the LayerStack // from strong-to-weak and save the strongest opinion. for (size_t i = 0, j = layers.size(); i != j; ++i) { const SdfLayerRefPtr& layer = layers[i]; - if (not clipInfo->clipManifestAssetPath) { + if (!clipInfo->clipManifestAssetPath) { SdfAssetPath clipManifestAssetPath; if (layer->HasField(primPath, UsdTokens->clipManifestAssetPath, &clipManifestAssetPath)) { @@ -198,7 +385,7 @@ Usd_ResolveClipInfo( } } - if (not clipInfo->clipPrimPath) { + if (!clipInfo->clipPrimPath) { std::string clipPrimPath; if (layer->HasField(primPath, UsdTokens->clipPrimPath, &clipPrimPath)) { @@ -208,25 +395,70 @@ Usd_ResolveClipInfo( } } - if (not clipInfo->clipActive) { - VtVec2dArray clipActive; - if (layer->HasField(primPath, UsdTokens->clipActive, &clipActive)) { - _ClipDebugMsg(node, layer, UsdTokens->clipActive); - _ApplyLayerOffsetToExternalTimes( - _GetLayerOffsetToRoot(node, layer), &clipActive); - clipInfo->clipActive = boost::in_place(); - clipInfo->clipActive->swap(clipActive); + if (nontemplateMetadataSeen) { + if (!clipInfo->clipActive) { + VtVec2dArray clipActive; + if (layer->HasField(primPath, UsdTokens->clipActive, + &clipActive)) { + _ClipDebugMsg(node, layer, UsdTokens->clipActive); + _ApplyLayerOffsetToExternalTimes( + _GetLayerOffsetToRoot(node, layer), &clipActive); + clipInfo->clipActive = boost::in_place(); + clipInfo->clipActive->swap(clipActive); + } + } + + if (!clipInfo->clipTimes) { + VtVec2dArray clipTimes; + if (layer->HasField(primPath, UsdTokens->clipTimes, + &clipTimes)) { + _ClipDebugMsg(node, layer, UsdTokens->clipTimes); + _ApplyLayerOffsetToExternalTimes( + _GetLayerOffsetToRoot(node, layer), &clipTimes); + clipInfo->clipTimes = boost::in_place(); + clipInfo->clipTimes->swap(clipTimes); + } + } + } else { + if (!templateStride) { + double clipTemplateStride; + if (layer->HasField(primPath, UsdTokens->clipTemplateStride, + &clipTemplateStride)) { + _ClipDebugMsg(node, layer, UsdTokens->clipTemplateStride); + auto layerOffset = _GetLayerOffsetToRoot(node, layer); + layerOffset.SetOffset(0); + templateStride = layerOffset * clipTemplateStride; + } + } + + if (!templateStartTime) { + double clipTemplateStartTime; + if (layer->HasField(primPath, UsdTokens->clipTemplateStartTime, + &clipTemplateStartTime)) { + _ClipDebugMsg(node, layer, UsdTokens->clipTemplateStartTime); + auto layerOffset = _GetLayerOffsetToRoot(node, layer); + templateStartTime = layerOffset * clipTemplateStartTime; + } + } + + if (!templateEndTime) { + double clipTemplateEndTime; + if (layer->HasField(primPath, UsdTokens->clipTemplateEndTime, + &clipTemplateEndTime)) { + _ClipDebugMsg(node, layer, UsdTokens->clipTemplateEndTime); + auto layerOffset = _GetLayerOffsetToRoot(node, layer); + templateEndTime = layerOffset * clipTemplateEndTime; + } } - } - if (not clipInfo->clipTimes) { - VtVec2dArray clipTimes; - if (layer->HasField(primPath, UsdTokens->clipTimes, &clipTimes)) { - _ClipDebugMsg(node, layer, UsdTokens->clipTimes); - _ApplyLayerOffsetToExternalTimes( - _GetLayerOffsetToRoot(node, layer), &clipTimes); - clipInfo->clipTimes = boost::in_place(); - clipInfo->clipTimes->swap(clipTimes); + if (templateStride && templateStartTime && templateEndTime) { + _DeriveClipInfo(*templateAssetPath, *templateStride, + *templateStartTime, *templateEndTime, + &clipInfo->clipTimes, &clipInfo->clipActive, + &clipInfo->clipAssetPaths, node, + layers[clipInfo->indexOfLayerWhereAssetPathsFound], + layerStack); + break; } } } From d87a92b2decd3869360ac0b181142800025fb52d Mon Sep 17 00:00:00 2001 From: superfunc Date: Tue, 25 Oct 2016 14:14:43 -0700 Subject: [PATCH 299/380] [Usd] Small signed-vs-unsigned error in crate. (Internal change: 1666328) --- pxr/usd/lib/usd/crateFile.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pxr/usd/lib/usd/crateFile.cpp b/pxr/usd/lib/usd/crateFile.cpp index 6f1fd0bf0e..90605fde3d 100644 --- a/pxr/usd/lib/usd/crateFile.cpp +++ b/pxr/usd/lib/usd/crateFile.cpp @@ -502,7 +502,7 @@ class CrateFile::_BufferedOutput inline void _WriteToBuffer(void const *bytes, int64_t nBytes) { // Fill the buffer, update its size and update the write head. Client // guarantees no overrun. - size_t writeStart = (_filePos - _bufferPos); + int64_t writeStart = (_filePos - _bufferPos); if (writeStart + nBytes > _buffer.size) { _buffer.size = writeStart + nBytes; } From eb081e898a42a9024b2be26acaed946b5f29f50c Mon Sep 17 00:00:00 2001 From: takahito-tejima Date: Tue, 25 Oct 2016 14:14:48 -0700 Subject: [PATCH 300/380] [Hd] disable bindless buffer by default set HD_ENABLE_BINDLESS_BUFFER to false by default. this needs nvidia driver 367.44 or later to work correctly (nvidia bug 1723330) the caveat of this workaround is, with falling back to SSBO we can only have up to level 4 of instancing or so (depending how much instance primvars we need). (Internal change: 1666334) --- pxr/imaging/lib/hd/renderContextCaps.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pxr/imaging/lib/hd/renderContextCaps.cpp b/pxr/imaging/lib/hd/renderContextCaps.cpp index 9c7cf42285..b8ea140e5f 100644 --- a/pxr/imaging/lib/hd/renderContextCaps.cpp +++ b/pxr/imaging/lib/hd/renderContextCaps.cpp @@ -36,7 +36,7 @@ TF_INSTANTIATE_SINGLETON(HdRenderContextCaps); TF_DEFINE_ENV_SETTING(HD_ENABLE_SHADER_STORAGE_BUFFER, true, "Use GL shader storage buffer (OpenGL 4.3)"); -TF_DEFINE_ENV_SETTING(HD_ENABLE_BINDLESS_BUFFER, true, +TF_DEFINE_ENV_SETTING(HD_ENABLE_BINDLESS_BUFFER, false, "Use GL bindless buffer extention"); TF_DEFINE_ENV_SETTING(HD_ENABLE_BINDLESS_TEXTURE, false, "Use GL bindless texture extention"); From 9bba8e0983829c701ecb2d91ecfb4a4eccd52791 Mon Sep 17 00:00:00 2001 From: poljere Date: Tue, 25 Oct 2016 14:15:12 -0700 Subject: [PATCH 301/380] [Hd] The texture sampler will now take into account texture overrides. For instance, if the texture wants to use a specific wrap mode. Also, we now setup a default anisotropic filter and a default border color. (Internal change: 1666496) --- pxr/imaging/lib/hd/textureResource.cpp | 33 ++++++++++++++++++++++---- pxr/imaging/lib/hd/textureResource.h | 3 +++ 2 files changed, 32 insertions(+), 4 deletions(-) diff --git a/pxr/imaging/lib/hd/textureResource.cpp b/pxr/imaging/lib/hd/textureResource.cpp index ccabb38eee..a9cc2ee9c7 100644 --- a/pxr/imaging/lib/hd/textureResource.cpp +++ b/pxr/imaging/lib/hd/textureResource.cpp @@ -98,6 +98,8 @@ HdSimpleTextureResource::HdSimpleTextureResource( HdMinFilter minFilter, HdMagFilter magFilter) : _textureHandle(textureHandle) , _texture(textureHandle->GetTexture()) + , _borderColor(0.0,0.0,0.0,0.0) + , _maxAnisotropy(16.0) , _sampler(0) , _isPtex(isPtex) { @@ -108,11 +110,34 @@ HdSimpleTextureResource::HdSimpleTextureResource( // When we are not using Ptex we will use samplers, // that includes both, bindless textures and no-bindless textures if (not _isPtex) { + // It is possible the texture provides wrap modes itself, in that + // case we will use the wrap modes provided by the texture + GLenum fwrapS = HdConversions::GetWrap(wrapS); + GLenum fwrapT = HdConversions::GetWrap(wrapT); + VtDictionary txInfo = _texture->GetTextureInfo(); + if (VtDictionaryIsHolding(txInfo, "wrapModeS")) { + fwrapS = VtDictionaryGet(txInfo, "wrapModeS"); + } + if (VtDictionaryIsHolding(txInfo, "wrapModeT")) { + fwrapT = VtDictionaryGet(txInfo, "wrapModeT"); + } + + GLenum fminFilter = HdConversions::GetMinFilter(minFilter); + GLenum fmagFilter = HdConversions::GetMagFilter(magFilter); + if (not _texture->IsMinFilterSupported(fminFilter)) { + fminFilter = GL_NEAREST; + } + if (not _texture->IsMagFilterSupported(fmagFilter)) { + fmagFilter = GL_NEAREST; + } + glGenSamplers(1, &_sampler); - glSamplerParameteri(_sampler, GL_TEXTURE_WRAP_S, HdConversions::GetWrap(wrapS)); - glSamplerParameteri(_sampler, GL_TEXTURE_WRAP_T, HdConversions::GetWrap(wrapT)); - glSamplerParameteri(_sampler, GL_TEXTURE_MIN_FILTER, HdConversions::GetMinFilter(minFilter)); - glSamplerParameteri(_sampler, GL_TEXTURE_MAG_FILTER, HdConversions::GetMagFilter(magFilter)); + glSamplerParameteri(_sampler, GL_TEXTURE_WRAP_S, fwrapS); + glSamplerParameteri(_sampler, GL_TEXTURE_WRAP_T, fwrapT); + glSamplerParameteri(_sampler, GL_TEXTURE_MIN_FILTER, fminFilter); + glSamplerParameteri(_sampler, GL_TEXTURE_MAG_FILTER, fmagFilter); + glSamplerParameterf(_sampler, GL_TEXTURE_MAX_ANISOTROPY_EXT, _maxAnisotropy); + glSamplerParameterfv(_sampler, GL_TEXTURE_BORDER_COLOR, _borderColor.GetArray()); } bool bindlessTexture = diff --git a/pxr/imaging/lib/hd/textureResource.h b/pxr/imaging/lib/hd/textureResource.h index 12b0d02d4f..ef79ef3a36 100644 --- a/pxr/imaging/lib/hd/textureResource.h +++ b/pxr/imaging/lib/hd/textureResource.h @@ -27,6 +27,7 @@ #include "pxr/imaging/garch/gl.h" #include "pxr/base/tf/declarePtrs.h" #include "pxr/base/tf/token.h" +#include "pxr/base/gf/vec4f.h" #include "pxr/imaging/hd/enums.h" #include "pxr/imaging/glf/texture.h" @@ -78,6 +79,8 @@ class HdSimpleTextureResource : public HdTextureResource private: GlfTextureHandleRefPtr _textureHandle; GlfTextureRefPtr _texture; + GfVec4f _borderColor; + float _maxAnisotropy; GLuint _sampler; bool _isPtex; }; From 27b5232ef3754deb0dc0d752941c7be8c6713cae Mon Sep 17 00:00:00 2001 From: c64kernal Date: Tue, 25 Oct 2016 14:15:32 -0700 Subject: [PATCH 302/380] Remove references to our dependency on Qt (C++ only) as we no longer require it. (Internal change: 1666501) --- README.md | 4 ---- cmake/defaults/Packages.cmake | 7 ++----- pxr/usd/lib/usd/doxygen/externalOverview.dox | 4 ---- pxr/usdImaging/lib/usdviewq/CMakeLists.txt | 5 ----- 4 files changed, 2 insertions(+), 18 deletions(-) diff --git a/README.md b/README.md index 6f1fa20cca..30b539e13b 100644 --- a/README.md +++ b/README.md @@ -58,7 +58,6 @@ Dependencies | [GLEW](http://glew.sourceforge.net/) | 1.10.0 | | [OpenImageIO](https://sites.google.com/site/openimageio/home) | 1.5.11 | | [Ptex](http://ptex.us/) | 2.0.30 | -| [Qt](http://doc.qt.io/qt-4.8) | 4.8.0 | | [Pyside](http://wiki.qt.io/PySide) | 1.2.2 | @@ -90,7 +89,6 @@ cmake \ -DPTEX_INCLUDE_DIR=/path/to/ptex \ -DOIIO_BASE_DIR=/path/to/openimageio \ -DBOOST_ROOT=/path/to/boost \ --DQT_QMAKE_EXECUTABLE=/path/to/qmake \ .. make -j install @@ -111,7 +109,6 @@ cmake \ -DPTEX_INCLUDE_DIR=/path/to/ptex \ -DOIIO_BASE_DIR=/path/to/openimageio \ -DBOOST_ROOT=/path/to/boost/include \ --DQT_QMAKE_EXECUTABLE=/path/to/qmake \ .. make -j install @@ -132,7 +129,6 @@ C:\Program Files\CMake\bin\cmake.exe ^ -DPTEX_INCLUDE_DIR=C:\path\to\ptex ^ -DOIIO_BASE_DIR=C:\path\to\openimageio ^ -DBOOST_ROOT=C:\path\to\boost ^ - -DQT_QMAKE_EXECUTABLE=C:\path\to\qmak ^ --build .. --config Release --target install ``` diff --git a/cmake/defaults/Packages.cmake b/cmake/defaults/Packages.cmake index 2f3fd45ecd..b08af1fd2d 100644 --- a/cmake/defaults/Packages.cmake +++ b/cmake/defaults/Packages.cmake @@ -87,11 +87,8 @@ if (PXR_BUILD_IMAGING) find_package(PTex REQUIRED) # --X11 find_package(X11) - # --Qt - find_package(Qt4) - if (QT4_FOUND) - find_package(PySide REQUIRED) - endif() + # --PySide + find_package(PySide) endif() # Third Party Plugin Package Requirements diff --git a/pxr/usd/lib/usd/doxygen/externalOverview.dox b/pxr/usd/lib/usd/doxygen/externalOverview.dox index f85ef5b2a4..65620a0030 100644 --- a/pxr/usd/lib/usd/doxygen/externalOverview.dox +++ b/pxr/usd/lib/usd/doxygen/externalOverview.dox @@ -225,10 +225,6 @@ modules that layer on top of the core. In low-to-high order, the modules are: and glslfx files. It also provides some basic glsl shaders upon which Hd behaviors are built. -- \b Glfq : The Gl Qt Foundations module makes it easy to instrument your - QglWidget classes so that your application can be configured at runtime to - emit detailed OpenGL debugging output. - - \b CameraUtil The Camera Utilities module provides a small but important set of common camera-related computations that don't really belong in the core GfCamera class. diff --git a/pxr/usdImaging/lib/usdviewq/CMakeLists.txt b/pxr/usdImaging/lib/usdviewq/CMakeLists.txt index c7918e255e..c2ac8e1eb8 100644 --- a/pxr/usdImaging/lib/usdviewq/CMakeLists.txt +++ b/pxr/usdImaging/lib/usdviewq/CMakeLists.txt @@ -1,11 +1,6 @@ set(PXR_PREFIX pxr/usdImaging) set(PXR_PACKAGE usdviewq) -if (NOT QT4_FOUND) - message(WARNING "Not building ${PXR_PACKAGE} because of missing dependency: Qt4") - return() -endif() - if (NOT PYSIDE_FOUND) message(WARNING "Not building ${PXR_PACKAGE} because of missing dependency: PySide") return() From cde5dc9cd1ed080a80089be8bc68156124d8ee59 Mon Sep 17 00:00:00 2001 From: superfunc Date: Tue, 25 Oct 2016 14:15:40 -0700 Subject: [PATCH 303/380] [Usd] Doc update for clipTemplateAssetPath. (Internal change: 1666513) --- pxr/usd/lib/usd/clipsAPI.h | 35 +++++++++++++++++++++++++++++------ 1 file changed, 29 insertions(+), 6 deletions(-) diff --git a/pxr/usd/lib/usd/clipsAPI.h b/pxr/usd/lib/usd/clipsAPI.h index c98dd9c12d..c7c170d799 100644 --- a/pxr/usd/lib/usd/clipsAPI.h +++ b/pxr/usd/lib/usd/clipsAPI.h @@ -222,12 +222,35 @@ class UsdClipsAPI : public UsdSchemaBase bool SetClipManifestAssetPath(const SdfAssetPath& manifestAssetPath); /// A template string representing a set of assets. This string - /// can be of two forms: path/basename.###.usd and path/basename.##.##.usd. - /// In either case, the number of hash marks in each section is variable. - /// These control the amount of padding USD will supply when looking up - /// the assets. For instance, a value of 'foo.###.usd', - /// with clipTemplateStartTime=11, clipTemplateEndTime=15, and clipTemplateStride=1: - /// USD will look for: foo.011.usd, foo.012.usd, foo.013.usd, foo.014.usd and foo.015.usd. + /// can be of two forms: + /// + /// integer frames: path/basename.###.usd + /// + /// subinteger frames: path/basename.##.##.usd. + /// + /// For the integer portion of the specification, USD will take + /// a particular time, determined by the clipTemplateStartTime, + /// clipTemplateStride and clipTemplateEndTime, and pad it with + /// zeros up to the number of hashes provided so long as the number of hashes + /// is greater than the digits required to specify the integer value. + /// + /// For instance: + /// + /// time = 12, clipTemplateAssetPath = foo.##.usd => foo.12.usd + /// time = 12, clipTemplateAssetPath = foo.###.usd => foo.012.usd + /// time = 333, clipTemplateAssetPath = foo.#.usd => foo.333.usd + /// + /// In the case of subinteger portion of a specifications, USD requires the + /// specification to be exact. + /// + /// For instance: + /// + /// time = 1.15, clipTemplateAssetPath = foo.#.###.usd => foo.1.150.usd + /// time = 1.145, clipTemplateAssetPath = foo.#.##.usd => foo.1.15.usd + /// time = 1.1, clipTemplateAssetPath = foo.#.##.usd => foo.1.10.usd + /// + /// Note that USD requires that hash groups be adjacent in the string, + /// and that there only be one or two such groups. bool GetClipTemplateAssetPath(std::string* clipTemplateAssetPath) const; /// Set the clipTemplateAssetPath metadata for this prim. /// \sa GetClipTemplateAssetPath From ee17d4e2964bcda0ec7405e9d2d3d7eb8f1aab54 Mon Sep 17 00:00:00 2001 From: comand Date: Tue, 25 Oct 2016 14:15:46 -0700 Subject: [PATCH 304/380] Remove use of TfRealPath for plugin registration. Calling realpath too frequently can be a performance killer for network filers. This saves many stat calls per plugin discovered (one stat call for every element of the path at least, more if there are actually symlinks in the path). (Internal change: 1666553) --- pxr/base/lib/plug/CMakeLists.txt | 1 + pxr/base/lib/plug/info.cpp | 30 +++++----- pxr/base/lib/plug/plugin.cpp | 89 ++++++++---------------------- pxr/base/lib/plug/plugin.h | 40 +------------- pxr/base/lib/plug/registry.cpp | 10 +--- pxr/base/lib/plug/registry.h | 10 +--- pxr/base/lib/plug/thisPlugin.h | 38 +++++++++++++ pxr/base/lib/plug/wrapRegistry.cpp | 32 +---------- pxr/imaging/lib/glf/package.cpp | 3 +- pxr/imaging/lib/hd/package.cpp | 3 +- pxr/imaging/lib/hdx/package.cpp | 3 +- 11 files changed, 88 insertions(+), 171 deletions(-) create mode 100644 pxr/base/lib/plug/thisPlugin.h diff --git a/pxr/base/lib/plug/CMakeLists.txt b/pxr/base/lib/plug/CMakeLists.txt index 73cf286104..16af4291d4 100644 --- a/pxr/base/lib/plug/CMakeLists.txt +++ b/pxr/base/lib/plug/CMakeLists.txt @@ -30,6 +30,7 @@ pxr_shared_library(plug PUBLIC_HEADERS api.h + thisPlugin.h CPPFILES initConfig.cpp diff --git a/pxr/base/lib/plug/info.cpp b/pxr/base/lib/plug/info.cpp index 96c6f40481..2647383e22 100644 --- a/pxr/base/lib/plug/info.cpp +++ b/pxr/base/lib/plug/info.cpp @@ -89,7 +89,7 @@ _MergePaths( // Join dirname(ownerPathname) and subpathname. const std::string result = - TfNormPath(TfStringCatPaths(TfGetPathName(ownerPathname), subpathname)); + TfStringCatPaths(TfGetPathName(ownerPathname), subpathname); // Retain trailing slash if request and if any. return (keepTrailingSlash and *subpathname.rbegin() == '/') @@ -115,7 +115,7 @@ _AppendToRootPath( } // Join rootPathname and subpathname. - return TfNormPath(TfStringCatPaths(rootPathname, subpathname)); + return TfStringCatPaths(rootPathname, subpathname); } void @@ -322,26 +322,24 @@ _TraverseDirectory( const std::string& dirname, const std::shared_ptr dirRegex) { - const std::vector dirContents = TfListDir(dirname); + std::vector dirnames, filenames; + TfReadDir(dirname, &dirnames, &filenames, &filenames); // Traverse all files in the directory to see if we have a // match first so that we can terminate the recursive walk // if we find one. - for (const auto& path : dirContents) { - const bool isFilePath = (*path.rbegin() != '/'); - if (isFilePath and std::regex_match(path, *dirRegex)) { - context->taskArena.Run(boost::bind(_ReadPlugInfo, - context, path)); + for (const auto& f : filenames) { + const std::string path = TfStringCatPaths(dirname, f); + if (std::regex_match(path, *dirRegex)) { + context->taskArena.Run(boost::bind(_ReadPlugInfo, context, path)); return; } } - for (const auto& path : dirContents) { - const bool isDirPath = (*path.rbegin() == '/'); - if (isDirPath) { - context->taskArena.Run(boost::bind(_TraverseDirectory, - context, path, dirRegex)); - } + for (const auto& d : dirnames) { + const std::string path = TfStringCatPaths(dirname, d); + context->taskArena.Run( + boost::bind(_TraverseDirectory, context, path, dirRegex)); } } @@ -703,9 +701,7 @@ Plug_ReadPlugInfo( // don't end in "/" to be handled as directories. Includes in // plugInfo files must still explicitly append '/' to be handled // as directories. - if (not pathname.empty() and - *pathname.rbegin() != '/' and - TfIsDir(pathname)) { + if (not pathname.empty() and *pathname.rbegin() != '/') { context.taskArena.Run( boost::bind(_ReadPlugInfoWithWildcards, &context, pathname + "/")); diff --git a/pxr/base/lib/plug/plugin.cpp b/pxr/base/lib/plug/plugin.cpp index 3af22d8337..8d69ba4ff0 100644 --- a/pxr/base/lib/plug/plugin.cpp +++ b/pxr/base/lib/plug/plugin.cpp @@ -24,9 +24,6 @@ #include "pxr/base/plug/plugin.h" #include "pxr/base/plug/debugCodes.h" -#include "pxr/base/arch/attributes.h" -#include "pxr/base/arch/fileSystem.h" -#include "pxr/base/arch/symbols.h" #include "pxr/base/arch/threads.h" #include "pxr/base/js/value.h" #include "pxr/base/tf/diagnostic.h" @@ -39,23 +36,17 @@ #include "pxr/base/tf/pyInterpreter.h" #include "pxr/base/tf/pyLock.h" #include "pxr/base/tf/scopeDescription.h" -#include "pxr/base/tf/scriptModuleLoader.h" #include "pxr/base/tf/staticData.h" #include "pxr/base/tf/stl.h" #include "pxr/base/tf/stringUtils.h" #include "pxr/base/tf/type.h" #include "pxr/base/tracelite/trace.h" -#include - #include #include #include #include -#include -#include - using std::pair; using std::string; using std::vector; @@ -82,12 +73,10 @@ PlugPlugin::_NewDynamicLibraryPlugin(const std::string & path, const std::string & resourcePath, const JsObject & plugInfo) { - const string realPath = TfRealPath(path); - const string pluginPath = TfRealPath(dsoPath); { // Already registered? std::lock_guard lock(_allPluginsMutex); - _PluginMap::const_iterator it = _allPlugins->find(realPath); + _PluginMap::const_iterator it = _allPlugins->find(path); if (it != _allPlugins->end()) return std::make_pair(it->second, false); @@ -100,23 +89,23 @@ PlugPlugin::_NewDynamicLibraryPlugin(const std::string & path, // Go ahead and create a plugin. TF_DEBUG(PLUG_REGISTRATION).Msg("Registering dso plugin '%s' at '%s'.\n", - name.c_str(), pluginPath.c_str()); + name.c_str(), dsoPath.c_str()); PlugPluginRefPtr plugin = - TfCreateRefPtr(new PlugPlugin(pluginPath, name, resourcePath, + TfCreateRefPtr(new PlugPlugin(dsoPath, name, resourcePath, plugInfo, LibraryType)); pair result; { std::lock_guard lock(_allPluginsMutex); pair<_PluginMap::iterator, bool> iresult = - _allPlugins->insert(make_pair(realPath, plugin)); + _allPlugins->insert(make_pair(path, plugin)); result.first = iresult.first->second; result.second = iresult.second; // If successfully inserted, add to _allPluginsByDynamicLibraryName too. if (iresult.second) { (*_allPluginsByDynamicLibraryName)[name] = plugin; - (*_libraryPluginsByDsoPath)[pluginPath] = plugin; + (*_libraryPluginsByDsoPath)[dsoPath] = plugin; } } @@ -129,12 +118,11 @@ PlugPlugin::_NewPythonModulePlugin(const std::string & modulePath, const std::string & resourcePath, const JsObject & plugInfo) { - const string realPath = TfRealPath(modulePath); { // Already registered? std::lock_guard lock(_allPluginsMutex); - _PluginMap::const_iterator it = _allPlugins->find(realPath); + _PluginMap::const_iterator it = _allPlugins->find(modulePath); if (it != _allPlugins->end()) return std::make_pair(it->second, false); @@ -156,7 +144,7 @@ PlugPlugin::_NewPythonModulePlugin(const std::string & modulePath, { std::lock_guard lock(_allPluginsMutex); pair<_PluginMap::iterator, bool> iresult = - _allPlugins->insert(make_pair(realPath, plugin)); + _allPlugins->insert(make_pair(modulePath, plugin)); result.first = iresult.first->second; result.second = iresult.second; @@ -174,12 +162,11 @@ PlugPlugin::_NewResourcePlugin(const std::string & path, const std::string & resourcePath, const JsObject & plugInfo) { - const string realPath = TfRealPath(path); { // Already registered? std::lock_guard lock(_allPluginsMutex); - _PluginMap::const_iterator it = _allPlugins->find(realPath); + _PluginMap::const_iterator it = _allPlugins->find(path); if (it != _allPlugins->end()) return std::make_pair(it->second, false); @@ -201,7 +188,7 @@ PlugPlugin::_NewResourcePlugin(const std::string & path, { std::lock_guard lock(_allPluginsMutex); pair<_PluginMap::iterator, bool> iresult = - _allPlugins->insert(make_pair(realPath, plugin)); + _allPlugins->insert(make_pair(path, plugin)); result.first = iresult.first->second; result.second = iresult.second; @@ -268,7 +255,7 @@ PlugPlugin::_Load() _name.c_str(), _name.c_str()); isLoaded = false; } - } else { + } else if (not IsResource()) { string dsoError; _handle = TfDlopen(_path.c_str(), RTLD_NOW, &dsoError); if ( ! _handle ) { @@ -424,39 +411,30 @@ PlugPlugin::FindPluginResource(const std::string& path, bool verify) const //void PlugPlugin::_RegisterAllPlugins(); PlugPluginPtr -PlugPlugin::_GetPluginWithAddress(void* address) -{ - std::string path; - return ArchGetAddressInfo(address, &path, NULL, NULL, NULL) - ? _GetPluginWithPath(path) - : TfNullPtr; -} - -PlugPluginPtr -PlugPlugin::_GetPluginWithPath(const std::string& path) +PlugPlugin::_GetPluginWithName(const std::string& name) { - // Plugins are registered under their real paths. - const std::string realPath = TfRealPath(path); - - // Register all plugins first. We can't associate a plugin with a path + // Register all plugins first. We can't associate a plugin with a name // until it's registered. _RegisterAllPlugins(); std::lock_guard lock(_allPluginsMutex); - // Try DSO paths first. - _WeakPluginMap::const_iterator i = _libraryPluginsByDsoPath->find(realPath); - if (i != _libraryPluginsByDsoPath->end()) { - return i->second; + auto idso = _allPluginsByDynamicLibraryName->find(name); + if (idso != _allPluginsByDynamicLibraryName->end()) { + return idso->second; } - // Try plugin paths. - _PluginMap::const_iterator j = _allPlugins->find(realPath); - if (j != _allPlugins->end()) { - return j->second; + auto imod = _allPluginsByModuleName->find(name); + if (imod != _allPluginsByModuleName->end()) { + return imod->second; } - return TfNullPtr; + auto ires = _allPluginsByResourceName->find(name); + if (ires != _allPluginsByResourceName->end()) { + return ires->second; + } + + return nullptr; } PlugPluginPtrVector @@ -684,17 +662,6 @@ TF_REGISTRY_FUNCTION(TfType) TfType::Define(); } - -PlugThisPlugin::PlugThisPlugin() -{ - _plugin = PlugPlugin::_GetPluginWithAddress(this); -} - -PlugThisPlugin::~PlugThisPlugin() -{ - // Do nothing -} - std::string PlugFindPluginResource( const PlugPluginPtr& plugin, @@ -704,11 +671,3 @@ PlugFindPluginResource( return plugin ? plugin->FindPluginResource(path, verify) : std::string(); } -std::string -PlugFindPluginResource( - const PlugThisPlugin& plugin, - const std::string& path, - bool verify) -{ - return PlugFindPluginResource(plugin.Get(), path, verify); -} diff --git a/pxr/base/lib/plug/plugin.h b/pxr/base/lib/plug/plugin.h index 010cfd52fb..cb52f838ab 100644 --- a/pxr/base/lib/plug/plugin.h +++ b/pxr/base/lib/plug/plugin.h @@ -126,9 +126,7 @@ class PLUG_API PlugPlugin : public TfRefBase, public TfWeakBase { PLUG_LOCAL static void _RegisterAllPlugins(); PLUG_LOCAL - static PlugPluginPtr _GetPluginWithAddress(void* address); - PLUG_LOCAL - static PlugPluginPtr _GetPluginWithPath(const std::string& path); + static PlugPluginPtr _GetPluginWithName(const std::string& name); PLUG_LOCAL static PlugPluginPtrVector _GetAllPlugins(); @@ -183,33 +181,6 @@ class PLUG_API PlugPlugin : public TfRefBase, public TfWeakBase { _Type _type; friend class PlugRegistry; - friend class PlugThisPlugin; -}; - -/// \class PlugThisPlugin -/// -/// An object that refers to the plugin it's in. -/// -/// If you have a plugin that wants access to its own plugInfo metadata -/// (especially its resources) then make a \b static instance of this -/// variable somewhere in the plugin's code. It can be a static global, -/// a static variable in a function, a static member of a class defined -/// in the plugin, or a member of any of those. It must not be allocated -/// on the stack or the heap or \c Get() will return \c NULL. -/// -class PLUG_API PlugThisPlugin : boost::noncopyable { -public: - PlugThisPlugin(); - ~PlugThisPlugin(); - - /// Returns the plugin or \c NULL if not found. - const PlugPluginPtr& Get() const - { - return _plugin; - } - -private: - PlugPluginPtr _plugin; }; /// Find a plugin's resource by absolute or relative path optionally @@ -221,13 +192,4 @@ std::string PlugFindPluginResource(const PlugPluginPtr& plugin, const std::string& path, bool verify = true); -/// Find a plugin's resource by absolute or relative path optionally -/// verifying that file exists. If \c plugin.Get() is \c NULL or -/// verification fails an empty path is returned. Relative paths are -/// relative to the plugin's resource path. -PLUG_API -std::string -PlugFindPluginResource(const PlugThisPlugin& plugin, - const std::string& path, bool verify = true); - #endif // PLUG_PLUGIN_H diff --git a/pxr/base/lib/plug/registry.cpp b/pxr/base/lib/plug/registry.cpp index 50f033d653..1397cc5bda 100644 --- a/pxr/base/lib/plug/registry.cpp +++ b/pxr/base/lib/plug/registry.cpp @@ -178,15 +178,9 @@ PlugRegistry::GetAllPlugins() const } PlugPluginPtr -PlugRegistry::GetPluginWithAddress(void* address) const +PlugRegistry::GetPluginWithName(const string& name) const { - return PlugPlugin::_GetPluginWithAddress(address); -} - -PlugPluginPtr -PlugRegistry::GetPluginWithPath(const std::string& path) const -{ - return PlugPlugin::_GetPluginWithPath(path); + return PlugPlugin::_GetPluginWithName(name); } JsValue diff --git a/pxr/base/lib/plug/registry.h b/pxr/base/lib/plug/registry.h index 22d22f8030..ce28993c6d 100644 --- a/pxr/base/lib/plug/registry.h +++ b/pxr/base/lib/plug/registry.h @@ -407,14 +407,8 @@ class PLUG_API PlugRegistry : public TfWeakBase, boost::noncopyable { /// Returns all registered plug-ins. PlugPluginPtrVector GetAllPlugins() const; - /// Returns the plugin that contains the given address if any, - /// otherwise returns \c NULL. Naturally, this only works for - /// shared library plugins. - PlugPluginPtr GetPluginWithAddress(void* address) const; - - /// Returns the plugin at the given filesystem path if any, - /// otherwise returns \c NULL. - PlugPluginPtr GetPluginWithPath(const std::string& path) const; + /// Returns a plugin with the specified library name. + PlugPluginPtr GetPluginWithName(const std::string& name) const; /// Looks for a string associated with \a type and \a key and returns it, or /// an empty string if \a type or \a key are not found. diff --git a/pxr/base/lib/plug/thisPlugin.h b/pxr/base/lib/plug/thisPlugin.h new file mode 100644 index 0000000000..c03d288c53 --- /dev/null +++ b/pxr/base/lib/plug/thisPlugin.h @@ -0,0 +1,38 @@ +// +// 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 PLUG_THISPLUGIN_H +#define PLUG_THISPLUGIN_H + +#include "pxr/base/plug/registry.h" +#include + +/// Returns a plugin registered with the name of the current library (uses the +/// define for MFB_PACKAGE_NAME). Note that plugin registration occurs as a +/// side effect of using this macro, at the point in time the code at the +/// macro site is invoked. +#define PLUG_THIS_PLUGIN \ + PlugRegistry::GetInstance().GetPluginWithName(\ + BOOST_PP_STRINGIZE(MFB_PACKAGE_NAME)) + +#endif // PLUG_THISPLUGIN_H diff --git a/pxr/base/lib/plug/wrapRegistry.cpp b/pxr/base/lib/plug/wrapRegistry.cpp index cf05d363d7..97279a4509 100644 --- a/pxr/base/lib/plug/wrapRegistry.cpp +++ b/pxr/base/lib/plug/wrapRegistry.cpp @@ -191,34 +191,6 @@ void _LoadPluginsConcurrently(PluginPredicateFn pred, } } -PlugPluginPtr -_ThisPlugin() -{ - object sys = import("sys"); - if (sys) { - // The caller's frame. - object frame = sys.attr("_getframe")(0); - if (frame) { - // The caller's module name. - object name = frame.attr("f_locals")["__name__"]; - if (name) { - // The caller's package path. - object path = sys.attr("modules")[name].attr("__path__")[0]; - extract e(path); - if (e.check()) { - // XXX: This doesn't find a shared library plugin - // because the path is the Python package - // path and the plugin would be registered - // under the library's path. PlugRegistry - // should support lookup given this path. - return PlugRegistry::GetInstance().GetPluginWithPath(e()); - } - } - } - } - return TfNullPtr; -} - } // anon void wrapRegistry() @@ -234,7 +206,7 @@ void wrapRegistry() .def("RegisterPlugins", &::_RegisterPluginsList, return_value_policy()) .def("GetStringFromPluginMetaData", &::_GetStringFromPluginMetaData) - .def("GetPluginWithPath", &This::GetPluginWithPath) + .def("GetPluginWithName", &This::GetPluginWithName) .def("GetPluginForType", &::_GetPluginForType) .def("GetAllPlugins", &This::GetAllPlugins, return_value_policy()) @@ -261,6 +233,4 @@ void wrapRegistry() def("_LoadPluginsConcurrently", _LoadPluginsConcurrently, (arg("predicate"), arg("numThreads")=0, arg("verbose")=false)); - - def("ThisPlugin", _ThisPlugin); } diff --git a/pxr/imaging/lib/glf/package.cpp b/pxr/imaging/lib/glf/package.cpp index 728b18171d..904f286e21 100644 --- a/pxr/imaging/lib/glf/package.cpp +++ b/pxr/imaging/lib/glf/package.cpp @@ -26,6 +26,7 @@ #include "pxr/imaging/glf/package.h" #include "pxr/base/plug/plugin.h" +#include "pxr/base/plug/thisPlugin.h" #include "pxr/base/tf/diagnostic.h" #include "pxr/base/tf/fileUtils.h" #include "pxr/base/tf/stringUtils.h" @@ -33,7 +34,7 @@ static TfToken _GetShaderPath(char const * shader) { - static PlugThisPlugin plugin; + static PlugPluginPtr plugin = PLUG_THIS_PLUGIN; const std::string path = PlugFindPluginResource(plugin, TfStringCatPaths("shaders", shader)); TF_VERIFY(not path.empty(), "Could not find shader: %s\n", shader); diff --git a/pxr/imaging/lib/hd/package.cpp b/pxr/imaging/lib/hd/package.cpp index b890cba003..933d7bbecc 100644 --- a/pxr/imaging/lib/hd/package.cpp +++ b/pxr/imaging/lib/hd/package.cpp @@ -24,6 +24,7 @@ #include "pxr/imaging/hd/package.h" #include "pxr/base/plug/plugin.h" +#include "pxr/base/plug/thisPlugin.h" #include "pxr/base/tf/diagnostic.h" #include "pxr/base/tf/fileUtils.h" #include "pxr/base/tf/stringUtils.h" @@ -31,7 +32,7 @@ static TfToken _GetShaderPath(char const * shader) { - static PlugThisPlugin plugin; + static PlugPluginPtr plugin = PLUG_THIS_PLUGIN; const std::string path = PlugFindPluginResource(plugin, TfStringCatPaths("shaders", shader)); TF_VERIFY(not path.empty(), "Could not find shader: %s\n", shader); diff --git a/pxr/imaging/lib/hdx/package.cpp b/pxr/imaging/lib/hdx/package.cpp index 6ec5d49ce6..98eda3dcb6 100644 --- a/pxr/imaging/lib/hdx/package.cpp +++ b/pxr/imaging/lib/hdx/package.cpp @@ -24,6 +24,7 @@ #include "pxr/imaging/hdx/package.h" #include "pxr/base/plug/plugin.h" +#include "pxr/base/plug/thisPlugin.h" #include "pxr/base/tf/diagnostic.h" #include "pxr/base/tf/fileUtils.h" #include "pxr/base/tf/staticData.h" @@ -32,7 +33,7 @@ static TfToken _GetShaderPath(char const * shader) { - static PlugThisPlugin plugin; + static PlugPluginPtr plugin = PLUG_THIS_PLUGIN; const std::string path = PlugFindPluginResource(plugin, TfStringCatPaths("shaders", shader)); TF_VERIFY(not path.empty(), "Could not find shader: %s\n", shader); From f4e2606a1d06252b63f65eb4fb4cc541ff9bef09 Mon Sep 17 00:00:00 2001 From: sunyab Date: Tue, 25 Oct 2016 14:16:03 -0700 Subject: [PATCH 305/380] Use cross-platform GL headers in Maya plugin code (Internal change: 1666566) --- third_party/maya/lib/px_vp20/CMakeLists.txt | 1 + third_party/maya/lib/px_vp20/utils.cpp | 3 +-- third_party/maya/lib/pxrUsdMayaGL/CMakeLists.txt | 1 + third_party/maya/lib/pxrUsdMayaGL/batchRenderer.cpp | 3 +-- third_party/maya/lib/pxrUsdMayaGL/hdRenderer.cpp | 4 ++-- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/third_party/maya/lib/px_vp20/CMakeLists.txt b/third_party/maya/lib/px_vp20/CMakeLists.txt index 092778f7b3..d5e6f9bdfa 100644 --- a/third_party/maya/lib/px_vp20/CMakeLists.txt +++ b/third_party/maya/lib/px_vp20/CMakeLists.txt @@ -2,6 +2,7 @@ set(PXR_PACKAGE px_vp20) pxr_shared_library(${PXR_PACKAGE} LIBRARIES + garch gf ${MAYA_OpenMaya_LIBRARY} ${MAYA_OpenMayaUI_LIBRARY} diff --git a/third_party/maya/lib/px_vp20/utils.cpp b/third_party/maya/lib/px_vp20/utils.cpp index 4df57e9eb9..79104421d8 100644 --- a/third_party/maya/lib/px_vp20/utils.cpp +++ b/third_party/maya/lib/px_vp20/utils.cpp @@ -22,8 +22,7 @@ // language governing permissions and limitations under the Apache License. // #include "px_vp20/utils.h" - -#include +#include "pxr/imaging/garch/gl.h" bool px_vp20Utils::setupLightingGL( const MHWRender::MDrawContext& context) { diff --git a/third_party/maya/lib/pxrUsdMayaGL/CMakeLists.txt b/third_party/maya/lib/pxrUsdMayaGL/CMakeLists.txt index 2c6018f225..0b8d3b553c 100644 --- a/third_party/maya/lib/pxrUsdMayaGL/CMakeLists.txt +++ b/third_party/maya/lib/pxrUsdMayaGL/CMakeLists.txt @@ -3,6 +3,7 @@ set(PXR_PACKAGE pxrUsdMayaGL) pxr_shared_library(${PXR_PACKAGE} LIBRARIES arch + garch gf tf plug diff --git a/third_party/maya/lib/pxrUsdMayaGL/batchRenderer.cpp b/third_party/maya/lib/pxrUsdMayaGL/batchRenderer.cpp index 43bb1c5d28..bb3e3ce148 100644 --- a/third_party/maya/lib/pxrUsdMayaGL/batchRenderer.cpp +++ b/third_party/maya/lib/pxrUsdMayaGL/batchRenderer.cpp @@ -26,6 +26,7 @@ #include "pxr/usd/sdf/types.h" #include "pxr/imaging/glf/glew.h" +#include "pxr/imaging/garch/glut.h" #include "pxr/imaging/hd/version.h" #if defined(HD_API) && HD_API > 25 @@ -57,8 +58,6 @@ #include -#include - TF_DEFINE_PRIVATE_TOKENS( _tokens, (idRenderTask) diff --git a/third_party/maya/lib/pxrUsdMayaGL/hdRenderer.cpp b/third_party/maya/lib/pxrUsdMayaGL/hdRenderer.cpp index a703e830ef..c61f281bee 100644 --- a/third_party/maya/lib/pxrUsdMayaGL/hdRenderer.cpp +++ b/third_party/maya/lib/pxrUsdMayaGL/hdRenderer.cpp @@ -28,6 +28,8 @@ // Make sure to include glew first before any header that might include // gl.h #include "pxr/imaging/glf/glew.h" +#include "pxr/imaging/garch/glut.h" + #include "pxrUsdMayaGL/hdRenderer.h" #include "px_vp20/utils.h" #include "px_vp20/utils_legacy.h" @@ -43,8 +45,6 @@ #include #include -#include - void UsdMayaGLHdRenderer::CheckRendererSetup( const UsdPrim& usdPrim, From dff8611ae93318daa235000e5c3c8fc34a792f0f Mon Sep 17 00:00:00 2001 From: takahito-tejima Date: Tue, 25 Oct 2016 14:16:13 -0700 Subject: [PATCH 306/380] [usdviewq] remove QGLWidget.renderText usage QGLWidget.renderText requires GL fixed pipeline, thus it doesn't work on OSX with core profile enabled (needed for hydra). Instead we draw HUD contents to QImage using QPainter API, and copy it back to QGLWidget as a texture. There are two GLSL implementations to blit the textures back to QGLWidget, for GL 3.0 or higher (includes Core profile OSX) and for GL 2.1 (compatibility profile OSX). This change reduces ~3000 GL classic API calls for each frame. To even reduce the overhead of texture transfer, split the HUD into 4 regions (TopLeft, TopRight, BottomLeft, BottomRight). Also removed unused menu (VBO stats display). (Internal change: 1666598) --- pxr/usdImaging/lib/usdviewq/mainWindow.py | 8 - pxr/usdImaging/lib/usdviewq/mainWindowUI.ui | 1 - pxr/usdImaging/lib/usdviewq/stageView.py | 400 ++++++++++++++------ 3 files changed, 287 insertions(+), 122 deletions(-) diff --git a/pxr/usdImaging/lib/usdviewq/mainWindow.py b/pxr/usdImaging/lib/usdviewq/mainWindow.py index 50825a2029..fdbdc04cd7 100644 --- a/pxr/usdImaging/lib/usdviewq/mainWindow.py +++ b/pxr/usdImaging/lib/usdviewq/mainWindow.py @@ -875,10 +875,6 @@ def __init__(self, parent, parserData): QtCore.SIGNAL('triggered()'), self._updateHUDMenu) - QtCore.QObject.connect(self._ui.actionHUD_VBO, - QtCore.SIGNAL('triggered()'), - self._HUDMenuChanged) - QtCore.QObject.connect(self._ui.actionHUD_Complexity, QtCore.SIGNAL('triggered()'), self._HUDMenuChanged) @@ -1891,8 +1887,6 @@ def _resetSettings(self): # self._settings.get("actionHUD_Info", False) self._stageView.showHUD_Info = False self._ui.actionHUD_Info.setChecked(self._stageView.showHUD_Info) - self._stageView.showHUD_VBO = self._settings.get("actionHUD_VBO", True) - self._ui.actionHUD_VBO.setChecked(self._stageView.showHUD_VBO) self._stageView.showHUD_Complexity = \ self._settings.get("actionHUD_Complexity", True) self._ui.actionHUD_Complexity.setChecked( @@ -3448,7 +3442,6 @@ def _HUDMenuChanged(self): """called when a HUD menu item has changed that does not require info refresh""" self._stageView.showHUD = self._ui.actionHUD.isChecked() self._stageView.showHUD_Info = self._ui.actionHUD_Info.isChecked() - self._stageView.showHUD_VBO = self._ui.actionHUD_VBO.isChecked() self._stageView.showHUD_Complexity = \ self._ui.actionHUD_Complexity.isChecked() self._stageView.showHUD_Performance = \ @@ -3459,7 +3452,6 @@ def _HUDMenuChanged(self): self._settings.setAndSave(actionHUD=self._ui.actionHUD.isChecked()) self._settings.setAndSave(actionHUD_Info=self._ui.actionHUD_Info.isChecked()) - self._settings.setAndSave(actionHUD_VBO=self._ui.actionHUD_VBO.isChecked()) self._settings.setAndSave(actionHUD_Complexity=\ self._ui.actionHUD_Complexity.isChecked()) self._settings.setAndSave(actionHUD_Performance=\ diff --git a/pxr/usdImaging/lib/usdviewq/mainWindowUI.ui b/pxr/usdImaging/lib/usdviewq/mainWindowUI.ui index f7b7c6f2ce..3ace8c7725 100644 --- a/pxr/usdImaging/lib/usdviewq/mainWindowUI.ui +++ b/pxr/usdImaging/lib/usdviewq/mainWindowUI.ui @@ -1234,7 +1234,6 @@ - diff --git a/pxr/usdImaging/lib/usdviewq/stageView.py b/pxr/usdImaging/lib/usdviewq/stageView.py index 85185edeaa..da173cc99c 100644 --- a/pxr/usdImaging/lib/usdviewq/stageView.py +++ b/pxr/usdImaging/lib/usdviewq/stageView.py @@ -491,6 +491,200 @@ def overrideFar(self, value): """To remove the override, set to None""" self._overrideFar = value +class HUD(): + class Group(): + def __init__(self, name, w, h): + self.x = 0 + self.y = 0 + self.w = w + self.h = h + self.qimage = QtGui.QImage(w, h, QtGui.QImage.Format_ARGB32) + self.qimage.fill(QtGui.QColor(0, 0, 0, 0)) + self.painter = QtGui.QPainter() + + def __init__(self): + self._HUDLineSpacing = 15 + self._HUDFont = QtGui.QFont("Menv Mono Numeric", 9) + self._groups = {} + self._program = 0 + self._glMajorVersion = 0 + self._vao = 0 + + def compileProgram(self): + from OpenGL import GL + import ctypes + + # prep a quad vbo + self._vbo = GL.glGenBuffers(1) + GL.glBindBuffer(GL.GL_ARRAY_BUFFER, self._vbo) + st = [0, 0, 1, 0, 0, 1, 1, 1] + GL.glBufferData(GL.GL_ARRAY_BUFFER, len(st)*4, + (ctypes.c_float*len(st))(*st), GL.GL_STATIC_DRAW) + GL.glBindBuffer(GL.GL_ARRAY_BUFFER, 0) + + self._program = GL.glCreateProgram() + vertexShader = GL.glCreateShader(GL.GL_VERTEX_SHADER) + fragmentShader = GL.glCreateShader(GL.GL_FRAGMENT_SHADER) + + if (self._glMajorVersion >= 3): + # for OpenGL 3.1 or later + vsSource = """#version 140 + uniform vec4 rect; + in vec2 st; + out vec2 uv; + void main() { + gl_Position = vec4(rect.x + rect.z*st.x, + rect.y + rect.w*st.y, 0, 1); + uv = vec2(st.x, 1 - st.y); }""" + fsSource = """#version 140 + in vec2 uv; + out vec4 color; + uniform sampler2D tex; + void main() { color = texture(tex, uv); }""" + else: + # for OpenGL 2.1 (osx compatibility profile) + vsSource = """#version 120 + uniform vec4 rect; + attribute vec2 st; + varying vec2 uv; + void main() { + gl_Position = vec4(rect.x + rect.z*st.x, + rect.y + rect.w*st.y, 0, 1); + uv = vec2(st.x, 1 - st.y); }""" + fsSource = """#version 120 + varying vec2 uv; + uniform sampler2D tex; + void main() { gl_FragColor = texture2D(tex, uv); }""" + + GL.glShaderSource(vertexShader, vsSource) + GL.glCompileShader(vertexShader) + GL.glShaderSource(fragmentShader, fsSource) + GL.glCompileShader(fragmentShader) + GL.glAttachShader(self._program, vertexShader) + GL.glAttachShader(self._program, fragmentShader) + GL.glLinkProgram(self._program) + + if GL.glGetProgramiv(self._program, GL.GL_LINK_STATUS) == GL.GL_FALSE: + print GL.glGetShaderInfoLog(vertexShader) + print GL.glGetShaderInfoLog(fragmentShader) + print GL.glGetProgramInfoLog(self._program) + GL.glDeleteShader(vertexShader) + GL.glDeleteShader(fragmentShader) + GL.glDeleteProgram(self._program) + self._program = 0 + return False + + GL.glDeleteShader(vertexShader) + GL.glDeleteShader(fragmentShader) + + self._ulocRect = GL.glGetUniformLocation(self._program, "rect") + self._ulocTex = GL.glGetUniformLocation(self._program, "tex") + return True + + def addGroup(self, name, w, h): + self._groups[name] = self.Group(name, w, h) + + def updateGroup(self, name, x, y, col, dic, keys = None): + group = self._groups[name] + group.qimage.fill(QtGui.QColor(0, 0, 0, 0)) + group.x = x + group.y = y + painter = group.painter + painter.begin(group.qimage) + + from prettyPrint import prettyPrint + if keys is None: + keys = sorted(dic.keys()) + + # find the longest key so we know how far from the edge to print + # add [0] at the end so that max() never gets an empty sequence + longestKeyLen = max([len(k) for k in dic.iterkeys()]+[0]) + margin = int(longestKeyLen*1.4) + + painter.setFont(self._HUDFont) + color = QtGui.QColor() + yy = 10 + for key in keys: + if not dic.has_key(key): + continue + line = key.rjust(margin) + ": " + str(prettyPrint(dic[key])) + # Shadow of text + shadow = Gf.ConvertDisplayToLinear(Gf.Vec3f(.2, .2, .2)) + color.setRgbF(shadow[0], shadow[1], shadow[2]) + painter.setPen(color) + painter.drawText(1, yy+1, line) + + # Colored text + color.setRgbF(col[0], col[1], col[2]) + painter.setPen(color) + painter.drawText(0, yy, line) + + yy += self._HUDLineSpacing + + painter.end() + return y + self._HUDLineSpacing + + def draw(self, qglwidget): + from OpenGL import GL + + if (self._glMajorVersion == 0): + self._glMajorVersion = int(GL.glGetString(GL.GL_VERSION)[0]) + + if (self._program == 0): + if (not self.compileProgram()): + self._program = 0 + return + + GL.glUseProgram(self._program) + + width = float(qglwidget.width()) + height = float(qglwidget.height()) + + if (self._glMajorVersion >= 4): + GL.glDisable(GL.GL_SAMPLE_ALPHA_TO_COVERAGE) + GL.glDisable(GL.GL_DEPTH_TEST) + GL.glBlendFunc(GL.GL_SRC_ALPHA, GL.GL_ONE_MINUS_SRC_ALPHA) + GL.glEnable(GL.GL_BLEND) + + # requires PyOpenGL 3.0.2 or later for glGenVertexArrays. + if (self._glMajorVersion >= 3 and hasattr(GL, 'glGenVertexArrays')): + if (self._vao == 0): + self._vao = GL.glGenVertexArrays(1) + GL.glBindVertexArray(self._vao) + + # for some reason, we need to bind at least 1 vertex attrib (is OSX) + GL.glBindBuffer(GL.GL_ARRAY_BUFFER, self._vbo) + GL.glEnableVertexAttribArray(0) + GL.glVertexAttribPointer(0, 2, GL.GL_FLOAT, False, 0, None) + + # seems like a bug in Qt4.8/CoreProfile on OSX that GL_UNPACK_ROW_LENGTH has changed. + GL.glPixelStorei(GL.GL_UNPACK_ROW_LENGTH, 0) + + for name in self._groups: + group = self._groups[name] + + tex = qglwidget.bindTexture(group.qimage, GL.GL_TEXTURE_2D, GL.GL_RGBA, + QtOpenGL.QGLContext.NoBindOption) + GL.glUniform4f(self._ulocRect, + 2*group.x/width - 1, + 1 - 2*group.y/height - 2*group.h/height, + 2*group.w/width, + 2*group.h/height) + GL.glUniform1i(self._ulocTex, 0) + GL.glActiveTexture(GL.GL_TEXTURE0) + GL.glBindTexture(GL.GL_TEXTURE_2D, tex) + GL.glDrawArrays(GL.GL_TRIANGLE_STRIP, 0, 4) + + GL.glDeleteTextures(tex) + + GL.glBindTexture(GL.GL_TEXTURE_2D, 0) + GL.glBindBuffer(GL.GL_ARRAY_BUFFER, 0) + GL.glDisableVertexAttribArray(0) + + if (self._vao != 0): + GL.glBindVertexArray(0) + + GL.glUseProgram(0) class StageView(QtOpenGL.QGLWidget): ''' @@ -767,15 +961,22 @@ def __init__(self, parent=None, bboxCache=None, xformCache=None): if msaa == "1": glFormat.setSampleBuffers(True) glFormat.setSamples(4) + # XXX: for OSX (QT5 required) + # glFormat.setProfile(QtOpenGL.QGLFormat.CoreProfile) super(StageView, self).__init__(glFormat, parent) - + self._freeCamera = FreeCamera(True) self._lastComputedGfCamera = None self._complexity = 1.0 - - self._renderStats = {} - + + # prep HUD regions + self._hud = HUD() + self._hud.addGroup("TopLeft", 250, 160) # subtree + self._hud.addGroup("TopRight", 120, 16) # Hydra: Enabled + self._hud.addGroup("BottomLeft", 250, 160) # GPU stats + self._hud.addGroup("BottomRight", 200, 32) # Camera, Complexity + self._stage = None self._stageIsZup = True self._cameraIsZup = True @@ -846,12 +1047,9 @@ def __init__(self, parent=None, bboxCache=None, xformCache=None): # HUD properties self._showHUD = False self.showHUD_Info = False - self.showHUD_VBO = False self.showHUD_Complexity = False self.showHUD_Performance = False self.showHUD_GPUstats = False - self._HUDFont = QtGui.QFont("Menv Mono Numeric", 9) - self._HUDLineSpacing = 15 self._fpsHUDInfo = dict() self._fpsHUDKeys = [] self._upperHUDInfo = dict() @@ -1133,9 +1331,6 @@ def renderSinglePass(self, renderMode, renderSelHighlights): if not self._stage or not self._renderer: return - # delete old render stats - self._renderStats = {} - # update rendering parameters self._renderParams.frame = self._currentFrame self._renderParams.complexity = self.complexity @@ -1272,7 +1467,7 @@ def drawWireframeCube(self, size): def paintGL(self): if not self._stage or not self._renderer: return - + from OpenGL import GL from OpenGL import GLU @@ -1506,113 +1701,94 @@ def paintGL(self): # ### DRAW HUD ### # if self.showHUD: - # compute the time it took to render this frame, - # so we can display it in the HUD - ms = self._renderTime * 1000. - fps = float("inf") - if not self._renderTime == 0: - fps = 1./self._renderTime - # put the result in the HUD string - self.fpsHUDInfo['Render'] = "%.2f ms (%.2f FPS)" % (ms, fps) - - GL.glPushMatrix() - GL.glLoadIdentity() - - yPos = 14 - col = Gf.ConvertDisplayToLinear(Gf.Vec3f(.733,.604,.333)) - - # the subtree info does not update while animating, grey it out - if not self.playing: - subtreeCol = col - else: - subtreeCol = Gf.ConvertDisplayToLinear(Gf.Vec3f(.6,.6,.6)) - - # Subtree Info - if self.showHUD_Info: - yPos = self.printDict(-10, yPos, subtreeCol, - self.upperHUDInfo, - self.HUDStatKeys) - - # VBO Info - if self.showHUD_VBO: - self.printDict(-10, yPos, col, self._renderStats) - - # Complexity - if self.showHUD_Complexity: - # Camera name - camName = "Free" - if self._cameraPrim: - camName = self._cameraPrim.GetName() - - toPrint = {"Complexity" : self.complexity, - "Camera" : camName} - self.printDict(self.width()-200, self.height()-21, col, toPrint) - - # Hydra Enabled - toPrint = {"Hydra": - "Enabled" if UsdImagingGL.GL.IsEnabledHydra() - else "Disabled"} - self.printDict(self.width()-140, 14, col, toPrint) - - # Playback Rate - if self.showHUD_Performance: - self.printDict(-10, self.height()-24, col, - self.fpsHUDInfo, - self.fpsHUDKeys) - # GPU stats (TimeElapsed is in nano seconds) - if self.showHUD_GPUstats: - allocInfo = self._renderer.GetResourceAllocation() - gpuMemTotal = 0 - texMem = 0 - if "gpuMemoryUsed" in allocInfo: - gpuMemTotal = allocInfo["gpuMemoryUsed"] - if "textureMemoryUsed" in allocInfo: - texMem = allocInfo["textureMemoryUsed"] - gpuMemTotal += texMem - - from collections import OrderedDict - toPrint = OrderedDict() - toPrint["GL prims "] = self._glPrimitiveGeneratedQuery.GetResult() - toPrint["GPU time "] = "%.2f ms " % (self._glTimeElapsedQuery.GetResult() / 1000000.0) - toPrint["GPU mem "] = gpuMemTotal - toPrint[" primvar "] = allocInfo["primVar"] if "primVar" in allocInfo else "N/A" - toPrint[" topology"] = allocInfo["topology"] if "topology" in allocInfo else "N/A" - toPrint[" shader "] = allocInfo["drawingShader"] if "drawingShader" in allocInfo else "N/A" - toPrint[" texture "] = texMem - - self.printDict(-10, self.height()-30-(15*len(toPrint)), col, toPrint, toPrint.keys()) - - GL.glPopMatrix() + self.drawHUD() GL.glDisable(GL_FRAMEBUFFER_SRGB_EXT) if (not self.playing) & (not self._renderer.IsConverged()): QtCore.QTimer.singleShot(5, self.update) - - def printDict(self, x, y, col, dic, keys = None): - from prettyPrint import prettyPrint - from OpenGL import GL - if keys is None: - keys = sorted(dic.keys()) - # find the longest key so we know how far from the edge to print - # add [0] at the end so that max() never gets an empty sequence - longestKeyLen = max([len(k) for k in dic.iterkeys()]+[0]) - margin = int(longestKeyLen*1.4) + def drawHUD(self): + # compute the time it took to render this frame, + # so we can display it in the HUD + ms = self._renderTime * 1000. + fps = float("inf") + if not self._renderTime == 0: + fps = 1./self._renderTime + # put the result in the HUD string + self.fpsHUDInfo['Render'] = "%.2f ms (%.2f FPS)" % (ms, fps) - for key in keys: - if not dic.has_key(key): - continue - line = key.rjust(margin) + ": " + str(prettyPrint(dic[key])) - # Shadow of text - GL.glColor3f(*(Gf.ConvertDisplayToLinear(Gf.Vec3f(.2, .2, .2)))) - self.renderText(x+1, y+1, line, self._HUDFont) - # Colored text - GL.glColor3f(*col) - self.renderText(x, y, line, self._HUDFont) + col = Gf.ConvertDisplayToLinear(Gf.Vec3f(.733,.604,.333)) - y += self._HUDLineSpacing - return y + self._HUDLineSpacing + # the subtree info does not update while animating, grey it out + if not self.playing: + subtreeCol = col + else: + subtreeCol = Gf.ConvertDisplayToLinear(Gf.Vec3f(.6,.6,.6)) + + # Subtree Info + if self.showHUD_Info: + self._hud.updateGroup("TopLeft", 0, 14, subtreeCol, + self.upperHUDInfo, + self.HUDStatKeys) + else: + self._hud.updateGroup("TopLeft", 0, 0, subtreeCol, {}) + + # Complexity + if self.showHUD_Complexity: + # Camera name + camName = "Free" + if self._cameraPrim: + camName = self._cameraPrim.GetName() + + toPrint = {"Complexity" : self.complexity, + "Camera" : camName} + self._hud.updateGroup("BottomRight", + self.width()-200, self.height()-self._hud._HUDLineSpacing*2, + col, toPrint) + else: + self._hud.updateGroup("BottomRight", 0, 0, col, {}) + + # Hydra Enabled (Top Right) + toPrint = {"Hydra": + "Enabled" if UsdImagingGL.GL.IsEnabledHydra() + else "Disabled"} + self._hud.updateGroup("TopRight", self.width()-140, 14, col, toPrint) + + # bottom left + from collections import OrderedDict + toPrint = OrderedDict() + + # GPU stats (TimeElapsed is in nano seconds) + if self.showHUD_GPUstats: + allocInfo = self._renderer.GetResourceAllocation() + gpuMemTotal = 0 + texMem = 0 + if "gpuMemoryUsed" in allocInfo: + gpuMemTotal = allocInfo["gpuMemoryUsed"] + if "textureMemoryUsed" in allocInfo: + texMem = allocInfo["textureMemoryUsed"] + gpuMemTotal += texMem + + toPrint["GL prims "] = self._glPrimitiveGeneratedQuery.GetResult() + toPrint["GPU time "] = "%.2f ms " % (self._glTimeElapsedQuery.GetResult() / 1000000.0) + toPrint["GPU mem "] = gpuMemTotal + toPrint[" primvar "] = allocInfo["primVar"] if "primVar" in allocInfo else "N/A" + toPrint[" topology"] = allocInfo["topology"] if "topology" in allocInfo else "N/A" + toPrint[" shader "] = allocInfo["drawingShader"] if "drawingShader" in allocInfo else "N/A" + toPrint[" texture "] = texMem + + # Playback Rate + if self.showHUD_Performance: + for key in self.fpsHUDKeys: + toPrint[key] = self.fpsHUDInfo[key] + if len(toPrint) > 0: + self._hud.updateGroup("BottomLeft", + 0, self.height()-len(toPrint)*self._hud._HUDLineSpacing, + col, toPrint, toPrint.keys()) + + # draw HUD + self._hud.draw(self) def sizeHint(self): return QtCore.QSize(460, 460) @@ -1770,9 +1946,6 @@ def pick(self, pickFrustum): # Need a correct OpenGL Rendering context for FBOs self.makeCurrent() - # delete old render stats - self._renderStats = {} - # update rendering parameters self._renderParams.frame = self._currentFrame self._renderParams.complexity = self.complexity @@ -1936,3 +2109,4 @@ def ExportSession(self, stagePath, defcamName='usdviewCam', sdfLayer.subLayerPaths.append( os.path.abspath(self._stage.GetRootLayer().realPath)) sdfLayer.Save() + From 3724f06b72d31d5822aee051dc86b5359ae9044a Mon Sep 17 00:00:00 2001 From: takahito-tejima Date: Tue, 25 Oct 2016 14:17:44 -0700 Subject: [PATCH 307/380] [Hd] fix renderContextCap to not use GLEW_VERSION_* checkling GL version using GLEW_VERSION can be problematic when glewExperimental is set to detect extensions for core profile context. This fix instead takes a standard way of GL_VERSION and GL_SHADING_LANGUAGE_VERSION parsing to determine the GL version. (Internal change: 1666745) --- pxr/imaging/lib/hd/renderContextCaps.cpp | 56 +++++++++++++++++------- pxr/imaging/lib/hd/renderContextCaps.h | 5 ++- 2 files changed, 43 insertions(+), 18 deletions(-) diff --git a/pxr/imaging/lib/hd/renderContextCaps.cpp b/pxr/imaging/lib/hd/renderContextCaps.cpp index b8ea140e5f..027b8a5197 100644 --- a/pxr/imaging/lib/hd/renderContextCaps.cpp +++ b/pxr/imaging/lib/hd/renderContextCaps.cpp @@ -26,6 +26,7 @@ #include "pxr/imaging/hd/debugCodes.h" #include "pxr/imaging/glf/glew.h" +#include "pxr/base/tf/diagnostic.h" #include "pxr/base/tf/envSetting.h" #include "pxr/base/tf/instantiateSingleton.h" @@ -52,7 +53,8 @@ TF_DEFINE_ENV_SETTING(HD_GLSL_VERSION, 0, // Initialize members to ensure a sane starting state. HdRenderContextCaps::HdRenderContextCaps() - : maxUniformBlockSize(0) + : glVersion(0) + , maxUniformBlockSize(0) , maxShaderStorageBlockSize(0) , maxTextureBufferSize(0) , uniformBufferOffsetAlignment(0) @@ -93,8 +95,7 @@ bool HdRenderContextCaps::SupportsHydra() const { // Minimum OpenGL version to run Hydra. Currently, OpenGL 4.0. - // also need GLEW initialized - if (GLEW_VERSION_4_0) { + if (glVersion >= 400) { return true; } return false; @@ -120,8 +121,36 @@ HdRenderContextCaps::_LoadCaps() maxTextureBufferSize = 64*1024; // GL spec minimum uniformBufferOffsetAlignment = 0; + const char *glVersionStr = (const char*)glGetString(GL_VERSION); + + // GL hasn't been initialized yet. + if (glVersionStr == NULL) return; + + const char *dot = strchr(glVersionStr, '.'); + if (TF_VERIFY((dot and dot != glVersionStr), + "Can't parse GL_VERSION %s", glVersionStr)) { + // GL_VERSION = "4.5.0 " + // "4.1 " + // "4.1 " + int major = std::max(0, std::min(9, *(dot-1) - '0')); + int minor = std::max(0, std::min(9, *(dot+1) - '0')); + glVersion = major * 100 + minor * 10; + } + const char *glslVersionStr = + (const char*)glGetString(GL_SHADING_LANGUAGE_VERSION); + dot = strchr(glslVersionStr, '.'); + if (TF_VERIFY((dot and dot != glslVersionStr), + "Can't parse GL_SHADING_LANGUAGE_VERSION %s", + glslVersionStr)) { + // GL_SHADING_LANGUAGE_VERSION = "4.10" + // "4.50 " + int major = std::max(0, std::min(9, *(dot-1) - '0')); + int minor = std::max(0, std::min(9, *(dot+1) - '0')); + glslVersion = major * 100 + minor * 10; + } + // initialize by Core versions - if (GLEW_VERSION_3_1) { + if (glVersion >= 310) { glGetIntegerv(GL_MAX_UNIFORM_BLOCK_SIZE, &maxUniformBlockSize); glGetIntegerv(GL_MAX_TEXTURE_BUFFER_SIZE, @@ -129,31 +158,22 @@ HdRenderContextCaps::_LoadCaps() glGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &uniformBufferOffsetAlignment); } - if (GLEW_VERSION_4_1) { - glslVersion = 410; - } - if (GLEW_VERSION_4_2) { - glslVersion = 420; + if (glVersion >= 420) { shadingLanguage420pack = true; } - if (GLEW_VERSION_4_3) { - glslVersion = 430; + if (glVersion >= 430) { shaderStorageBufferEnabled = true; explicitUniformLocation = true; glGetIntegerv(GL_MAX_SHADER_STORAGE_BLOCK_SIZE, &maxShaderStorageBlockSize); } - if (GLEW_VERSION_4_4) { - glslVersion = 440; + if (glVersion >= 440) { bufferStorageEnabled = true; } -#if defined(GLEW_VERSION_4_5) // glew 1.11 or newer (usd requirement is 1.10) - if (GLEW_VERSION_4_5) { - glslVersion = 450; + if (glVersion >= 450) { multiDrawIndirectEnabled = true; directStateAccessEnabled = true; } -#endif // initialize by individual exntention. if (GLEW_ARB_bindless_texture and glMakeTextureHandleResidentNV) { @@ -219,6 +239,8 @@ HdRenderContextCaps::_LoadCaps() if (TfDebug::IsEnabled(HD_RENDER_CONTEXT_CAPS)) { std::cout << "HdRenderContextCaps: \n" + << " GL version = " + << glVersion << "\n" << " GLSL version = " << glslVersion << "\n" diff --git a/pxr/imaging/lib/hd/renderContextCaps.h b/pxr/imaging/lib/hd/renderContextCaps.h index 8b7a22585c..39e3c43de5 100644 --- a/pxr/imaging/lib/hd/renderContextCaps.h +++ b/pxr/imaging/lib/hd/renderContextCaps.h @@ -55,6 +55,9 @@ class HdRenderContextCaps : boost::noncopyable { /// Note that glew needs to be initialized too. bool SupportsHydra() const; + // GL version + int glVersion; // 400 (4.0), 410 (4.1), ... + // Max constants int maxUniformBlockSize; int maxShaderStorageBlockSize; @@ -71,7 +74,7 @@ class HdRenderContextCaps : boost::noncopyable { bool bindlessBufferEnabled; // NV_shader_buffer_load // GLSL version and extensions - int glslVersion; + int glslVersion; // 400, 410, ... bool explicitUniformLocation; // ARB_explicit_uniform_location (4.3) bool shadingLanguage420pack; // ARB_shading_language_420pack (4.2) From 8a2bd10f60c7ad8f7a24b2f0b0c08416b18a5212 Mon Sep 17 00:00:00 2001 From: sdao Date: Tue, 25 Oct 2016 14:17:57 -0700 Subject: [PATCH 308/380] Add object representing user-tagged attribute to be exported from Maya (Internal change: 1666835) --- third_party/maya/lib/usdMaya/CMakeLists.txt | 3 + .../maya/lib/usdMaya/UserTaggedAttribute.cpp | 205 ++++++++++++++++++ .../maya/lib/usdMaya/UserTaggedAttribute.h | 87 ++++++++ third_party/maya/lib/usdMaya/module.cpp | 1 + .../lib/usdMaya/wrapUserTaggedAttribute.cpp | 83 +++++++ third_party/maya/lib/usdMaya/writeUtil.cpp | 136 +----------- 6 files changed, 391 insertions(+), 124 deletions(-) create mode 100644 third_party/maya/lib/usdMaya/UserTaggedAttribute.cpp create mode 100644 third_party/maya/lib/usdMaya/UserTaggedAttribute.h create mode 100644 third_party/maya/lib/usdMaya/wrapUserTaggedAttribute.cpp diff --git a/third_party/maya/lib/usdMaya/CMakeLists.txt b/third_party/maya/lib/usdMaya/CMakeLists.txt index 373ac8fd53..bdcda4007c 100644 --- a/third_party/maya/lib/usdMaya/CMakeLists.txt +++ b/third_party/maya/lib/usdMaya/CMakeLists.txt @@ -73,6 +73,8 @@ pxr_shared_library(${PXR_PACKAGE} AttributeConverter AttributeConverterRegistry + UserTaggedAttribute + PRIVATE_CLASSES registryHelper MayaCameraWriter @@ -108,6 +110,7 @@ pxr_shared_library(${PXR_PACKAGE} wrapEditUtil.cpp wrapQuery.cpp wrapStageCache.cpp + wrapUserTaggedAttribute.cpp PYTHON_FILES __init__.py diff --git a/third_party/maya/lib/usdMaya/UserTaggedAttribute.cpp b/third_party/maya/lib/usdMaya/UserTaggedAttribute.cpp new file mode 100644 index 0000000000..450f08008a --- /dev/null +++ b/third_party/maya/lib/usdMaya/UserTaggedAttribute.cpp @@ -0,0 +1,205 @@ +// +// 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. +// +#include "usdMaya/UserTaggedAttribute.h" + +#include "pxr/base/js/json.h" +#include "pxr/base/js/value.h" +#include "pxr/base/tf/staticTokens.h" +#include "pxr/base/tf/stringUtils.h" +#include "pxr/usd/usdGeom/tokens.h" + +#include +#include + +#include + +TF_DEFINE_PUBLIC_TOKENS(PxrUsdMayaUserTaggedAttributeTokens, + PXRUSDMAYA_ATTR_TOKENS); + +TF_DEFINE_PRIVATE_TOKENS( + _tokens, + (USD_UserExportedAttributesJson) + (usdAttrName) + (usdAttrType) + ((UserPropertiesNamespace, "userProperties:")) +); + +PxrUsdMayaUserTaggedAttribute::PxrUsdMayaUserTaggedAttribute( + const MPlug plug, + const std::string& name, + const TfToken& type, + const TfToken& interpolation) + : _plug(plug), _name(name), _type(type), _interpolation(interpolation) +{ +} + +MPlug +PxrUsdMayaUserTaggedAttribute::GetMayaPlug() const +{ + return _plug; +} + +std::string +PxrUsdMayaUserTaggedAttribute::GetMayaName() const +{ + MString name = _plug.partialName(); + return std::string(name.asChar()); +} + +std::string +PxrUsdMayaUserTaggedAttribute::GetUsdName() const +{ + return _name; +} + +TfToken +PxrUsdMayaUserTaggedAttribute::GetUsdType() const +{ + return _type; +} + +TfToken +PxrUsdMayaUserTaggedAttribute::GetUsdInterpolation() const +{ + return _interpolation; +} + +static std::string +_GetExportAttributeMetadata( + const JsObject& attrMetadata, + const TfToken& keyToken) +{ + std::string value; + JsObject::const_iterator attrMetadataIter = attrMetadata.find(keyToken); + if (attrMetadataIter != attrMetadata.end()) { + value = attrMetadataIter->second.GetString(); + } + + return value; +} + +/* static */ +std::vector +PxrUsdMayaUserTaggedAttribute::GetUserTaggedAttributesForNode( + const MDagPath& dagPath) +{ + MStatus status; + MFnDependencyNode depFn(dagPath.node()); + std::vector result; + std::set processedAttributeNames; + + MPlug exportedAttrsJsonPlug = depFn.findPlug( + _tokens->USD_UserExportedAttributesJson.GetText(), true, &status); + if (status != MS::kSuccess || exportedAttrsJsonPlug.isNull()) { + // No attributes specified for export on this node. + return result; + } + + std::string exportedAttrsJsonString( + exportedAttrsJsonPlug.asString().asChar()); + if (exportedAttrsJsonString.empty()) { + return result; + } + + JsParseError jsError; + JsValue jsValue = JsParseString(exportedAttrsJsonString, &jsError); + if (not jsValue) { + MString errorMsg(TfStringPrintf( + "Failed to parse USD exported attributes JSON on node at" + " dagPath '%s' at line %d, column %d: %s", + dagPath.fullPathName().asChar(), + jsError.line, jsError.column, jsError.reason.c_str()).c_str()); + MGlobal::displayError(errorMsg); + return result; + } + + // If an attribute is multiply-defined, we'll use the first tag encountered + // and issue warnings for the subsequent definitions. JsObject is really + // just a std::map, so we'll be considering attributes in sorted order. + const JsObject& exportedAttrs = jsValue.GetJsObject(); + for (JsObject::const_iterator iter = exportedAttrs.begin(); + iter != exportedAttrs.end(); + ++iter) { + const std::string mayaAttrName = iter->first; + + const MPlug attrPlug = depFn.findPlug( + mayaAttrName.c_str(), true, &status); + if (status != MS::kSuccess || attrPlug.isNull()) { + MString errorMsg(TfStringPrintf( + "Could not find attribute '%s' for USD export on node at" + " dagPath '%s'", + mayaAttrName.c_str(), dagPath.fullPathName().asChar()).c_str()); + MGlobal::displayError(errorMsg); + continue; + } + + const JsObject& attrMetadata = iter->second.GetJsObject(); + + // Check if this is a particular type of attribute (e.g. primvar or + // usdRi attribute). If we don't recognize the type specified, we'll + // fall back to a regular USD attribute. + TfToken usdAttrType( + _GetExportAttributeMetadata(attrMetadata, _tokens->usdAttrType)); + + // Check whether an interpolation type was specified. This is only + // relevant for primvars. + TfToken interpolation( + _GetExportAttributeMetadata(attrMetadata, + UsdGeomTokens->interpolation)); + + // Check whether the USD attribute name should be different than the + // Maya attribute name. + std::string usdAttrName = + _GetExportAttributeMetadata(attrMetadata, _tokens->usdAttrName); + if (usdAttrName.empty()) { + const auto& tokens = PxrUsdMayaUserTaggedAttributeTokens; + if (usdAttrType == tokens->USDAttrTypePrimvar or + usdAttrType == tokens->USDAttrTypeUsdRi) { + // Primvars and UsdRi attributes will be given a type-specific + // namespace, so just use the Maya attribute name. + usdAttrName = mayaAttrName; + } else { + // For regular USD attributes, when no name was specified we + // prepend the userProperties namespace to the Maya attribute + // name to get the USD attribute name. + usdAttrName = _tokens->UserPropertiesNamespace.GetString() + + mayaAttrName; + } + } + + const auto& insertIter = processedAttributeNames.emplace(usdAttrName); + if (not insertIter.second) { + MString errorMsg(TfStringPrintf( + "Ignoring duplicate USD export tag for attribute '%s' on node" + " at dagPath '%s'", + usdAttrName.c_str(), dagPath.fullPathName().asChar()).c_str()); + MGlobal::displayError(errorMsg); + continue; + } + + result.emplace_back(attrPlug, usdAttrName, usdAttrType, interpolation); + } + + return result; +} diff --git a/third_party/maya/lib/usdMaya/UserTaggedAttribute.h b/third_party/maya/lib/usdMaya/UserTaggedAttribute.h new file mode 100644 index 0000000000..319072cd2b --- /dev/null +++ b/third_party/maya/lib/usdMaya/UserTaggedAttribute.h @@ -0,0 +1,87 @@ +// +// 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. +// + +/// \file UserTaggedAttribute.h + +#ifndef PXRUSDMAYA_USERTAGGEDATTRIBUTE_H +#define PXRUSDMAYA_USERTAGGEDATTRIBUTE_H + +#include "pxr/base/tf/iterator.h" +#include "pxr/base/tf/token.h" +#include "pxr/base/tf/staticTokens.h" + +#include +#include + +#include +#include +#include + +#define PXRUSDMAYA_ATTR_TOKENS \ + ((USDAttrTypePrimvar, "primvar")) \ + ((USDAttrTypeUsdRi, "usdRi")) + +TF_DECLARE_PUBLIC_TOKENS(PxrUsdMayaUserTaggedAttributeTokens, + PXRUSDMAYA_ATTR_TOKENS); + +/// \brief Represents a single attribute tagged for USD export, and describes +/// how it will be exported. +class PxrUsdMayaUserTaggedAttribute { +private: + MPlug _plug; + const std::string _name; + const TfToken _type; + const TfToken _interpolation; + +public: + PxrUsdMayaUserTaggedAttribute( + MPlug plug, + const std::string& name, + const TfToken& type, + const TfToken& interpolation); + + /// \brief Gets all of the exported attributes for the given node. + static std::vector + GetUserTaggedAttributesForNode(const MDagPath& dagPath); + + /// \brief Gets the plug for the Maya attribute to be exported. + MPlug GetMayaPlug() const; + + /// \brief Gets the name of the Maya attribute that will be exported; + /// the name will not contain the name of the node. + std::string GetMayaName() const; + + /// \brief Gets the name of the USD attribute to which the Maya attribute + /// will be exported. + std::string GetUsdName() const; + + /// \brief Gets the type of the USD attribute to export: whether it is a + /// regular attribute, primvar, etc. + TfToken GetUsdType() const; + + /// \brief Gets the interpolation for primvars. + TfToken GetUsdInterpolation() const; +}; + +#endif // PXRUSDMAYA_USERTAGGEDATTRIBUTE_H diff --git a/third_party/maya/lib/usdMaya/module.cpp b/third_party/maya/lib/usdMaya/module.cpp index 7c21afacf2..5a12accc3b 100644 --- a/third_party/maya/lib/usdMaya/module.cpp +++ b/third_party/maya/lib/usdMaya/module.cpp @@ -28,4 +28,5 @@ TF_WRAP_MODULE { TF_WRAP(EditUtil); TF_WRAP(Query); TF_WRAP(StageCache); + TF_WRAP(UserTaggedAttribute); } diff --git a/third_party/maya/lib/usdMaya/wrapUserTaggedAttribute.cpp b/third_party/maya/lib/usdMaya/wrapUserTaggedAttribute.cpp new file mode 100644 index 0000000000..5f30714c11 --- /dev/null +++ b/third_party/maya/lib/usdMaya/wrapUserTaggedAttribute.cpp @@ -0,0 +1,83 @@ +// +// 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. +// +#include "usdMaya/UserTaggedAttribute.h" + +#include "pxr/base/tf/pyContainerConversions.h" +#include "pxr/base/tf/pyResultConversions.h" +#include "pxr/base/tf/pyStaticTokens.h" +#include "pxr/base/tf/token.h" + +#include +#include +#include + +#include +#include + +#include + +static std::vector +_GetUserTaggedAttributesForNode( + const std::string& dagString) +{ + MStatus status; + std::vector wrappedAttrs; + + MSelectionList selList; + status = selList.add(MString(dagString.c_str())); + CHECK_MSTATUS_AND_RETURN(status, wrappedAttrs); + + MDagPath dagPath; + status = selList.getDagPath(0, dagPath); + CHECK_MSTATUS_AND_RETURN(status, wrappedAttrs); + + return PxrUsdMayaUserTaggedAttribute::GetUserTaggedAttributesForNode( + dagPath); +} + +void wrapUserTaggedAttribute() { + using namespace boost::python; + + TF_PY_WRAP_PUBLIC_TOKENS("UserTaggedAttributeTokens", + PxrUsdMayaUserTaggedAttributeTokens, + PXRUSDMAYA_ATTR_TOKENS); + + TfPyContainerConversions::from_python_sequence< + std::set, + TfPyContainerConversions::set_policy >(); + + class_("UserTaggedAttribute", + "Attribute tagged for USD export", + no_init) + .def("GetMayaName", &PxrUsdMayaUserTaggedAttribute::GetMayaName) + .def("GetUsdName", &PxrUsdMayaUserTaggedAttribute::GetUsdName) + .def("GetUsdType", &PxrUsdMayaUserTaggedAttribute::GetUsdType) + .def("GetUsdInterpolation", + &PxrUsdMayaUserTaggedAttribute::GetUsdInterpolation) + .def("GetUserTaggedAttributesForNode", + _GetUserTaggedAttributesForNode, + return_value_policy()) + .staticmethod("GetUserTaggedAttributesForNode") + ; +} diff --git a/third_party/maya/lib/usdMaya/writeUtil.cpp b/third_party/maya/lib/usdMaya/writeUtil.cpp index 619a5fc380..4cbbdbbe6e 100644 --- a/third_party/maya/lib/usdMaya/writeUtil.cpp +++ b/third_party/maya/lib/usdMaya/writeUtil.cpp @@ -22,11 +22,9 @@ // language governing permissions and limitations under the Apache License. // #include "usdMaya/writeUtil.h" +#include "usdMaya/UserTaggedAttribute.h" #include "pxr/base/gf/gamma.h" -#include "pxr/base/js/json.h" -#include "pxr/base/js/value.h" -#include "pxr/base/tf/staticTokens.h" #include "pxr/base/tf/stringUtils.h" #include "pxr/base/tf/token.h" #include "pxr/base/vt/types.h" @@ -64,22 +62,9 @@ #include #include -#include #include #include - -TF_DEFINE_PRIVATE_TOKENS( - _tokens, - (USD_UserExportedAttributesJson) - (usdAttrName) - (usdAttrType) - ((USDAttrTypePrimvar, "primvar")) - ((USDAttrTypeUsdRi, "usdRi")) - ((UserPropertiesNamespace, "userProperties:")) -); - - SdfValueTypeName PxrUsdMayaWriteUtil::GetUsdTypeName( const MPlug& plg) { @@ -560,21 +545,6 @@ PxrUsdMayaWriteUtil::SetUsdAttr( return true; } -static -std::string -_GetExportAttributeMetadata( - const JsObject& attrMetadata, - const TfToken& keyToken) -{ - std::string value; - JsObject::const_iterator attrMetadataIter = attrMetadata.find(keyToken); - if (attrMetadataIter != attrMetadata.end()) { - value = attrMetadataIter->second.GetString(); - } - - return value; -} - // This method inspects the JSON blob stored in the 'USD_UserExportedAttributesJson' // attribute on the Maya node at dagPath and exports any attributes specified // there onto usdPrim at time usdTime. The JSON should contain an object that @@ -613,100 +583,17 @@ PxrUsdMayaWriteUtil::WriteUserExportedAttributes( const UsdPrim& usdPrim, const UsdTimeCode& usdTime) { - MStatus status; - MFnDependencyNode depFn(dagPath.node()); - - MPlug exportedAttrsJsonPlug = depFn.findPlug( - _tokens->USD_UserExportedAttributesJson.GetText(), true, &status); - if (status != MS::kSuccess || exportedAttrsJsonPlug.isNull()) { - // No attributes specified for export on this node. - return false; - } - - std::string exportedAttrsJsonString(exportedAttrsJsonPlug.asString().asChar()); - if (exportedAttrsJsonString.empty()) { - return false; - } - - JsParseError jsError; - JsValue jsValue = JsParseString(exportedAttrsJsonString, &jsError); - if (not jsValue) { - MString errorMsg(TfStringPrintf( - "Failed to parse USD exported attributes JSON on node at dagPath '%s'" - " at line %d, column %d: %s", - dagPath.fullPathName().asChar(), - jsError.line, jsError.column, jsError.reason.c_str()).c_str()); - MGlobal::displayError(errorMsg); - return false; - } - - // Maintain a set of USD attribute names that have been processed. If an - // attribute is multiply-defined, we'll use the first tag encountered and - // issue warnings for the subsequent definitions. JsObject is really just a - // std::map, so we'll be considering attributes in sorted order. - std::set exportedUsdAttrNames; - - const JsObject& exportedAttrs = jsValue.GetJsObject(); - for (JsObject::const_iterator iter = exportedAttrs.begin(); - iter != exportedAttrs.end(); - ++iter) { - const std::string mayaAttrName = iter->first; - - const MPlug attrPlug = depFn.findPlug(mayaAttrName.c_str(), true, &status); - if (status != MS::kSuccess || attrPlug.isNull()) { - MString errorMsg(TfStringPrintf( - "Could not find attribute '%s' for USD export on node at dagPath '%s'", - mayaAttrName.c_str(), dagPath.fullPathName().asChar()).c_str()); - MGlobal::displayError(errorMsg); - continue; - } - - const JsObject& attrMetadata = iter->second.GetJsObject(); - - // Check if this is a particular type of attribute (e.g. primvar or - // usdRi attribute). If we don't recognize the type specified, we'll - // fall back to a regular USD attribute. - TfToken usdAttrType( - _GetExportAttributeMetadata(attrMetadata, _tokens->usdAttrType)); - - // Check whether an interpolation type was specified. This is only - // relevant for primvars. - TfToken interpolation( - _GetExportAttributeMetadata(attrMetadata, - UsdGeomTokens->interpolation)); - - // Check whether the USD attribute name should be different than the - // Maya attribute name. - std::string usdAttrName = - _GetExportAttributeMetadata(attrMetadata, _tokens->usdAttrName); - if (usdAttrName.empty()) { - if (usdAttrType == _tokens->USDAttrTypePrimvar or - usdAttrType == _tokens->USDAttrTypeUsdRi) { - // Primvars and UsdRi attributes will be given a type-specific - // namespace, so just use the Maya attribute name. - usdAttrName = mayaAttrName; - } else { - // For regular USD attributes, when no name was specified we - // prepend the userProperties namespace to the Maya attribute - // name to get the USD attribute name. - usdAttrName = _tokens->UserPropertiesNamespace.GetString() + - mayaAttrName; - } - } - - const auto& insertIter = exportedUsdAttrNames.insert(usdAttrName); - - if (not insertIter.second) { - MString errorMsg(TfStringPrintf( - "Ignoring duplicate USD export tag for attribute '%s' on node at dagPath '%s'", - usdAttrName.c_str(), dagPath.fullPathName().asChar()).c_str()); - MGlobal::displayError(errorMsg); - continue; - } - + std::vector exportedAttributes = + PxrUsdMayaUserTaggedAttribute::GetUserTaggedAttributesForNode(dagPath); + for (const PxrUsdMayaUserTaggedAttribute& attr : exportedAttributes) { + const std::string& usdAttrName = attr.GetUsdName(); + const TfToken& usdAttrType = attr.GetUsdType(); + const TfToken& interpolation = attr.GetUsdInterpolation(); + const MPlug& attrPlug = attr.GetMayaPlug(); UsdAttribute usdAttr; - if (usdAttrType == _tokens->USDAttrTypePrimvar) { + if (usdAttrType == + PxrUsdMayaUserTaggedAttributeTokens->USDAttrTypePrimvar) { UsdGeomImageable imageable(usdPrim); if (not imageable) { MGlobal::displayError( @@ -725,7 +612,8 @@ PxrUsdMayaWriteUtil::WriteUserExportedAttributes( if (primvar) { usdAttr = primvar.GetAttr(); } - } else if (usdAttrType == _tokens->USDAttrTypeUsdRi) { + } else if (usdAttrType == + PxrUsdMayaUserTaggedAttributeTokens->USDAttrTypeUsdRi) { usdAttr = PxrUsdMayaWriteUtil::GetOrCreateUsdRiAttribute(attrPlug, usdPrim, From f65ab2538a550de5bd6245ad91f10e9604707fff Mon Sep 17 00:00:00 2001 From: pixar-oss Date: Tue, 25 Oct 2016 14:20:36 -0700 Subject: [PATCH 309/380] Remove no longer needed "infer st" logic in readMesh. (Internal change: 1666850) --- third_party/katana/lib/usdKatana/readMesh.cpp | 128 ------------------ 1 file changed, 128 deletions(-) diff --git a/third_party/katana/lib/usdKatana/readMesh.cpp b/third_party/katana/lib/usdKatana/readMesh.cpp index 1bdd249b67..4921e81e22 100644 --- a/third_party/katana/lib/usdKatana/readMesh.cpp +++ b/third_party/katana/lib/usdKatana/readMesh.cpp @@ -246,126 +246,6 @@ _promoteToVertex( } -// Infer ST (if it doesn't exist) from u_map1 and v_map1 -FnKat::GroupAttribute _inferSt( - FnKat::GroupAttribute& primvarGroup, - FnKat::GroupAttribute& polyAttr, - double currentTime) -{ - FnKat::GroupBuilder arbBuilder; - - // Grab relevant attributes - FnKat::Attribute st = primvarGroup.getChildByName("st"); - FnKat::Attribute s = primvarGroup.getChildByName("s"); - FnKat::Attribute t = primvarGroup.getChildByName("t"); - FnKat::GroupAttribute u = primvarGroup.getChildByName("u_map1"); - FnKat::GroupAttribute v = primvarGroup.getChildByName("v_map1"); - - // If we don't have u_map1 and v_map1, don't do anything - // If st or s,t exist, don't override what is already there - if (!u.isValid() - || !v.isValid() - || st.isValid() - || s.isValid() - || t.isValid()) { - return FnKat::GroupAttribute(); - } - - // Check attribute scope - FnKat::StringAttribute uScopeAttr = u.getChildByName("scope"); - FnKat::StringAttribute vScopeAttr = v.getChildByName("scope"); - std::string uScope = uScopeAttr.getValue(); - std::string vScope = vScopeAttr.getValue(); - - // Things we'll use to build st - std::string scope; - FnKat::StringAttribute interpolationType; - FnKat::FloatAttribute uAttrMatched, vAttrMatched; - - // Grab the u_map1 and v_map1 values - FnKat::FloatAttribute uAttr = u.getChildByName("value"); - FnKat::FloatAttribute vAttr = v.getChildByName("value"); - - // Don't do anything for matching face or primitive scopes - // (uniform or constant details in usd/rib) - if ((uScope == "face" || uScope == "primitive") - && (vScope == "face" || vScope == "primitive")) { - return FnKat::GroupAttribute(); - } - - if (uScope == vScope) { - // Scopes match - interleave without promoting to vertex/facevarying - scope = uScope; - uAttrMatched = uAttr; - vAttrMatched = vAttr; - - // If the interpolationTypes exist and match, use those as well - FnKat::StringAttribute uInterpAttr = u.getChildByName( - "interpolationType"); - FnKat::StringAttribute vInterpAttr = v.getChildByName( - "interpolationType"); - if (uInterpAttr.isValid() && vInterpAttr.isValid() - && uInterpAttr.getValue() == vInterpAttr.getValue()) { - interpolationType = uInterpAttr; - } - } else { - // If the scopes don't match, promote everything to vertex/facevarying - scope = "vertex"; - // This could be optimized by not creating an intermediate array, - // but I feel that this is a little cleaner - uAttrMatched = _promoteToVertex(uAttr, uScope, polyAttr, currentTime); - vAttrMatched = _promoteToVertex(vAttr, vScope, polyAttr, currentTime); - } - - bool stBuilt = false; - if (uAttrMatched.isValid() && vAttrMatched.isValid()) { - // If we have valid matched arrays, then interleave them - FnKat::FloatConstVector uArray = uAttrMatched.getNearestSample( - currentTime); - FnKat::FloatConstVector vArray = vAttrMatched.getNearestSample( - currentTime); - if (uArray.size() == vArray.size()) { - std::vector stArray; - stArray.reserve(uArray.size()*2); - for (size_t i = 0; i < uArray.size(); ++i) { - stArray.push_back(uArray[i]); - stArray.push_back(vArray[i]); - } - - // Build into ST - FnKat::GroupBuilder attrBuilder; - FnKat::FloatBuilder vecBuilder(/* tupleSize = */ 2); - vecBuilder.set(stArray); - attrBuilder.set("scope", FnKat::StringAttribute(scope)); - attrBuilder.set("inputType", - FnKat::StringAttribute("point2")); - attrBuilder.set("value", vecBuilder.build()); - if (interpolationType.isValid()) { - attrBuilder.set("interpolationType", interpolationType); - } - arbBuilder.set("st", attrBuilder.build()); - stBuilt = true; - } else { - FnLogWarn("u_map1 and v_map1 promoted to vertex, but are" - << "different sizes."); - } - } - - if (!stBuilt && u.isValid() && v.isValid()) { - // If we couldn't promote the arrays to vertex, store S,T separately - // as a fallback. RenderMan will combine s,t into st at render time. - FnLogDebug("Unablo to interleave/promote to vertex: " - << "u_map1 scope (" << uScope << ") " - << "v_map1 scope (" << vScope << "). " - << "Storing S, T separately."); - arbBuilder.set("s", u); - arbBuilder.set("t", v); - } - - return arbBuilder.build(); -} - - void PxrUsdKatanaReadMesh( const UsdGeomMesh& mesh, @@ -449,14 +329,6 @@ PxrUsdKatanaReadMesh( if (primvarGroup.isValid()) { - // Infer ST if it doesn't exist. - // Remove this later when ST is built through in USD. - FnKat::Attribute stAttrib = _inferSt(primvarGroup, polyAttr, currentTime); - if (stAttrib.isValid()) - { - arbBuilder.update(stAttrib); - } - arbBuilder.update(primvarGroup); } From 42839243907dae53e9cc47d3b2c183ae63082792 Mon Sep 17 00:00:00 2001 From: pixar-oss Date: Tue, 25 Oct 2016 14:21:05 -0700 Subject: [PATCH 310/380] Process primvars for all UsdGeomImageable prims. (Internal change: 1666851) --- .../katana/lib/usdKatana/readBasisCurves.cpp | 50 +++------- .../katana/lib/usdKatana/readGprim.cpp | 74 --------------- third_party/katana/lib/usdKatana/readGprim.h | 5 - third_party/katana/lib/usdKatana/readMesh.cpp | 65 +++++-------- .../katana/lib/usdKatana/readNurbsPatch.cpp | 34 ++----- .../katana/lib/usdKatana/readPoints.cpp | 23 +---- third_party/katana/lib/usdKatana/readPrim.cpp | 91 +++++++++++++++++++ third_party/katana/lib/usdKatana/readPrim.h | 6 ++ 8 files changed, 146 insertions(+), 202 deletions(-) diff --git a/third_party/katana/lib/usdKatana/readBasisCurves.cpp b/third_party/katana/lib/usdKatana/readBasisCurves.cpp index 3f96088fa5..6923cdd6f1 100644 --- a/third_party/katana/lib/usdKatana/readBasisCurves.cpp +++ b/third_party/katana/lib/usdKatana/readBasisCurves.cpp @@ -33,8 +33,9 @@ FnLogSetup("PxrUsdKatanaReadBasisCurves"); -static FnKat::GroupAttribute -_GetCurveAttrs(const UsdGeomBasisCurves& basisCurves, double currentTime) +static void +_SetCurveAttrs(PxrUsdKatanaAttrMap& attrs, + const UsdGeomBasisCurves& basisCurves, double currentTime) { VtIntArray vtxCts; basisCurves.GetCurveVertexCountsAttr().Get(&vtxCts, currentTime); @@ -44,15 +45,14 @@ _GetCurveAttrs(const UsdGeomBasisCurves& basisCurves, double currentTime) std::vector &numVerts = numVertsBuilder.get(); numVerts = ctsVec; - FnKat::GroupBuilder curveBuilder; - curveBuilder.set("numVertices", numVertsBuilder.build()); + attrs.set("geometry.numVertices", numVertsBuilder.build()); VtFloatArray widths; basisCurves.GetWidthsAttr().Get(&widths, currentTime); size_t numWidths = widths.size(); if (numWidths == 1) { - curveBuilder.set("constantWidth", + attrs.set("geometry.constantWidth", FnKat::FloatAttribute(widths[0])); } else if (numWidths > 1) @@ -60,15 +60,13 @@ _GetCurveAttrs(const UsdGeomBasisCurves& basisCurves, double currentTime) FnKat::FloatBuilder widthsBuilder(1); widthsBuilder.set( std::vector(widths.begin(), widths.end())); - curveBuilder.set("point.width", widthsBuilder.build()); + attrs.set("geometry.point.width", widthsBuilder.build()); } TfToken curveType; basisCurves.GetTypeAttr().Get(&curveType, currentTime); - curveBuilder.set("degree", + attrs.set("geometry.degree", FnKat::IntAttribute(curveType == UsdGeomTokens->linear ? 1 : 3)); - - return curveBuilder.build(); } void @@ -139,17 +137,10 @@ PxrUsdKatanaReadBasisCurves( // Construct the 'geometry' attribute. // - FnKat::GroupBuilder geometryBuilder; - - FnKat::GroupAttribute curveAttr = _GetCurveAttrs( - basisCurves, data.GetUsdInArgs()->GetCurrentTime()); - - if (curveAttr.isValid()) { - geometryBuilder.update(curveAttr); - } + _SetCurveAttrs(attrs, basisCurves, data.GetUsdInArgs()->GetCurrentTime()); // position - geometryBuilder.set("point.P", + attrs.set("geometry.point.P", PxrUsdKatanaGeomGetPAttr(basisCurves, data)); // normals @@ -163,7 +154,7 @@ PxrUsdKatanaReadBasisCurves( if (interp == UsdGeomTokens->faceVarying || interp == UsdGeomTokens->varying || interp == UsdGeomTokens->vertex) { - geometryBuilder.set("point.N", normalsAttr); + attrs.set("geometry.point.N", normalsAttr); } } @@ -172,23 +163,10 @@ PxrUsdKatanaReadBasisCurves( PxrUsdKatanaGeomGetVelocityAttr(basisCurves, data); if (velocityAttr.isValid()) { - geometryBuilder.set("point.v", velocityAttr); - } - - // Construct the 'geometry.arbitrary' attribute. - - FnKat::GroupBuilder arbBuilder; - - arbBuilder.set("SPT_HwColor", - PxrUsdKatanaGeomGetDisplayColorAttr(basisCurves, data)); - - FnKat::Attribute primvarGroup = - PxrUsdKatanaGeomGetPrimvarGroup(basisCurves, data); - if (primvarGroup.isValid()) - { - arbBuilder.update(primvarGroup); + attrs.set("geometry.point.v", velocityAttr); } - geometryBuilder.set("arbitrary", arbBuilder.build()); - attrs.set("geometry", geometryBuilder.build()); + // Add SPT_HwColor primvar + attrs.set("geometry.arbitrary.SPT_HwColor", + PxrUsdKatanaGeomGetDisplayColorAttr(basisCurves, data)); } diff --git a/third_party/katana/lib/usdKatana/readGprim.cpp b/third_party/katana/lib/usdKatana/readGprim.cpp index 2c339df983..b668d77b33 100644 --- a/third_party/katana/lib/usdKatana/readGprim.cpp +++ b/third_party/katana/lib/usdKatana/readGprim.cpp @@ -81,80 +81,6 @@ PxrUsdKatanaGeomGetDisplayColorAttr( return groupBuilder.build(); } -FnKat::Attribute -PxrUsdKatanaGeomGetPrimvarGroup( - const UsdGeomGprim& gprim, - const PxrUsdKatanaUsdInPrivateData& data) -{ - // Usd primvars -> Primvar attributes - FnKat::GroupBuilder gdBuilder; - - std::vector primvarAttrs = gprim.GetPrimvars(); - TF_FOR_ALL(primvar, primvarAttrs) { - TfToken name, interpolation; - SdfValueTypeName typeName; - int elementSize; - - primvar->GetDeclarationInfo(&name, &typeName, - &interpolation, &elementSize); - - // Name: this will eventually want to be GetBaseName() to strip - // off prefixes - std::string gdName = name; - - // Convert interpolation -> scope - FnKat::StringAttribute scopeAttr; - const bool isCurve = gprim.GetPrim().IsA(); - if (isCurve && interpolation == UsdGeomTokens->vertex) { - // it's a curve, so "vertex" == "vertex" - scopeAttr = FnKat::StringAttribute("vertex"); - } else { - scopeAttr = FnKat::StringAttribute( - (interpolation == UsdGeomTokens->faceVarying)? "vertex" : - (interpolation == UsdGeomTokens->varying) ? "point" : - (interpolation == UsdGeomTokens->vertex) ? "point" /*see below*/ : - (interpolation == UsdGeomTokens->uniform) ? "face" : - "primitive" ); - } - - // Resolve the value - VtValue vtValue; - if (not primvar->ComputeFlattened( - &vtValue, data.GetUsdInArgs()->GetCurrentTime())) - { - continue; - } - - // Convert value to the required Katana attributes to describe it. - FnKat::Attribute valueAttr, inputTypeAttr, elementSizeAttr; - PxrUsdKatanaUtils::ConvertVtValueToKatCustomGeomAttr( - vtValue, elementSize, typeName.GetRole(), - &valueAttr, &inputTypeAttr, &elementSizeAttr); - - // Bundle them into a group attribute - FnKat::GroupBuilder attrBuilder; - attrBuilder.set("scope", scopeAttr); - attrBuilder.set("inputType", inputTypeAttr); - if (elementSizeAttr.isValid()) { - attrBuilder.set("elementSize", elementSizeAttr); - } - attrBuilder.set("value", valueAttr); - // Note that 'varying' vs 'vertex' require special handling, as in - // Katana they are both expressed as 'point' scope above. To get - // 'vertex' interpolation we must set an additional - // 'interpolationType' attribute. So we will flag that here. - const bool vertexInterpolationType = - (interpolation == UsdGeomTokens->vertex); - if (vertexInterpolationType) { - attrBuilder.set("interpolationType", - FnKat::StringAttribute("subdiv")); - } - gdBuilder.set(gdName, attrBuilder.build()); - } - - return gdBuilder.build(); -} - Foundry::Katana::Attribute PxrUsdKatanaGeomGetWindingOrderAttr( const UsdGeomGprim& gprim, diff --git a/third_party/katana/lib/usdKatana/readGprim.h b/third_party/katana/lib/usdKatana/readGprim.h index e9fd6f5246..5dcabb562b 100644 --- a/third_party/katana/lib/usdKatana/readGprim.h +++ b/third_party/katana/lib/usdKatana/readGprim.h @@ -36,11 +36,6 @@ PxrUsdKatanaReadGprim( const PxrUsdKatanaUsdInPrivateData& data, PxrUsdKatanaAttrMap& attrs); -Foundry::Katana::Attribute -PxrUsdKatanaGeomGetPrimvarGroup( - const UsdGeomGprim& gprim, - const PxrUsdKatanaUsdInPrivateData& data); - Foundry::Katana::Attribute PxrUsdKatanaGeomGetDisplayColorAttr( const UsdGeomGprim& gprim, diff --git a/third_party/katana/lib/usdKatana/readMesh.cpp b/third_party/katana/lib/usdKatana/readMesh.cpp index 4921e81e22..36f4d4d8a1 100644 --- a/third_party/katana/lib/usdKatana/readMesh.cpp +++ b/third_party/katana/lib/usdKatana/readMesh.cpp @@ -69,13 +69,12 @@ _GetPolyAttr(const UsdGeomMesh &mesh, double time) return polyBuilder.build(); } -static FnKat::Attribute -_GetSubdivTagsGroup(const UsdGeomMesh &mesh, bool hierarchical, double time) +static void +_SetSubdivTagsGroup(PxrUsdKatanaAttrMap& attrs, + const UsdGeomMesh &mesh, bool hierarchical, double time) { std::string err; - FnKat::GroupBuilder builder; - TfToken interpolateBoundary; if (mesh.GetInterpolateBoundaryAttr().Get(&interpolateBoundary, time)){ if (interpolateBoundary != UsdGeomTokens->none) { // See bug/90360 @@ -84,7 +83,7 @@ _GetSubdivTagsGroup(const UsdGeomMesh &mesh, bool hierarchical, double time) Msg("\tinterpolateBoundary = %s (%d)\n", interpolateBoundary.GetText(), UsdRiConvertToRManInterpolateBoundary(interpolateBoundary)); - builder.set("interpolateBoundary", + attrs.set("geometry.interpolateBoundary", FnKat::IntAttribute( UsdRiConvertToRManInterpolateBoundary(interpolateBoundary))); } @@ -113,7 +112,7 @@ _GetSubdivTagsGroup(const UsdGeomMesh &mesh, bool hierarchical, double time) fvInterpolateBoundary.GetText(), UsdRiConvertToRManFaceVaryingLinearInterpolation(fvInterpolateBoundary)); - builder.set("facevaryinginterpolateboundary", + attrs.set("geometry.facevaryinginterpolateboundary", FnKat::IntAttribute( UsdRiConvertToRManFaceVaryingLinearInterpolation(fvInterpolateBoundary))); } @@ -130,7 +129,7 @@ _GetSubdivTagsGroup(const UsdGeomMesh &mesh, bool hierarchical, double time) FnKat::IntBuilder holeIndicesBuilder(1); holeIndicesBuilder.set(std::vector(holeIndices.begin(), holeIndices.end())); - builder.set("holePolyIndices", holeIndicesBuilder.build()); + attrs.set("geometry.holePolyIndices", holeIndicesBuilder.build()); } // Creases @@ -140,7 +139,7 @@ _GetSubdivTagsGroup(const UsdGeomMesh &mesh, bool hierarchical, double time) FnKat::IntBuilder creasesBuilder(1); creasesBuilder.set(std::vector(creaseIndices.begin(), creaseIndices.end())); - builder.set("creaseIndices", creasesBuilder.build()); + attrs.set("geometry.creaseIndices", creasesBuilder.build()); VtIntArray creaseLengths; if (mesh.GetCreaseLengthsAttr().Get(&creaseLengths, time) @@ -148,7 +147,7 @@ _GetSubdivTagsGroup(const UsdGeomMesh &mesh, bool hierarchical, double time) FnKat::IntBuilder creaseLengthsBuilder(1); creaseLengthsBuilder.set(std::vector(creaseLengths.begin(), creaseLengths.end())); - builder.set("creaseLengths", creaseLengthsBuilder.build()); + attrs.set("geometry.creaseLengths", creaseLengthsBuilder.build()); } VtFloatArray creaseSharpness; if (mesh.GetCreaseSharpnessesAttr().Get(&creaseSharpness, time) @@ -171,8 +170,8 @@ _GetSubdivTagsGroup(const UsdGeomMesh &mesh, bool hierarchical, double time) } creaseSharpnessLengthsBuilder.set(numSharpnesses); - builder.set("creaseSharpness", creaseSharpnessBuilder.build()); - builder.set("creaseSharpnessLengths", + attrs.set("geometry.creaseSharpness", creaseSharpnessBuilder.build()); + attrs.set("geometry.creaseSharpnessLengths", creaseSharpnessLengthsBuilder.build()); } } @@ -184,7 +183,7 @@ _GetSubdivTagsGroup(const UsdGeomMesh &mesh, bool hierarchical, double time) FnKat::IntBuilder cornersBuilder(1); cornersBuilder.set(std::vector(cornerIndices.begin(), cornerIndices.end())); - builder.set("cornerIndices", cornersBuilder.build()); + attrs.set("geometry.cornerIndices", cornersBuilder.build()); } VtFloatArray cornerSharpness; if (mesh.GetCornerSharpnessesAttr().Get(&cornerSharpness, time) @@ -192,10 +191,8 @@ _GetSubdivTagsGroup(const UsdGeomMesh &mesh, bool hierarchical, double time) FnKat::FloatBuilder cornerSharpnessBuilder(1); cornerSharpnessBuilder.set(std::vector(cornerSharpness.begin(), cornerSharpness.end())); - builder.set("cornerSharpness", cornerSharpnessBuilder.build()); + attrs.set("geometry.cornerSharpness", cornerSharpnessBuilder.build()); } - - return builder.build(); } @@ -274,10 +271,8 @@ PxrUsdKatanaReadMesh( // Construct the 'geometry' attribute. // - FnKat::GroupBuilder geometryBuilder; - // position - geometryBuilder.set("point.P", PxrUsdKatanaGeomGetPAttr(mesh, data)); + attrs.set("geometry.point.P", PxrUsdKatanaGeomGetPAttr(mesh, data)); /// Only use custom normals if the object is a polymesh. if (not isSubd){ @@ -289,10 +284,10 @@ PxrUsdKatanaReadMesh( TfToken interp = mesh.GetNormalsInterpolation(); if (interp == UsdGeomTokens->varying || interp == UsdGeomTokens->vertex) { - geometryBuilder.set("point.N", normalsAttr); + attrs.set("geometry.point.N", normalsAttr); } else if (interp == UsdGeomTokens->faceVarying) { - geometryBuilder.set("vertex.N", normalsAttr); + attrs.set("geometry.vertex.N", normalsAttr); } } } @@ -301,39 +296,21 @@ PxrUsdKatanaReadMesh( FnKat::Attribute velocityAttr = PxrUsdKatanaGeomGetVelocityAttr(mesh, data); if (velocityAttr.isValid()) { - geometryBuilder.set("point.v", velocityAttr); + attrs.set("geometry.point.v", velocityAttr); } FnKat::GroupAttribute polyAttr = _GetPolyAttr(mesh, currentTime); - geometryBuilder.set("poly", polyAttr); + attrs.set("geometry.poly", polyAttr); if (isSubd) { - FnKat::Attribute subdivTagsGroup = - _GetSubdivTagsGroup(mesh, /* hierarchical=*/ false, currentTime); - - if (subdivTagsGroup.isValid()) - { - geometryBuilder.update( subdivTagsGroup ); - } - } - - FnKat::GroupBuilder arbBuilder; - - arbBuilder.set("SPT_HwColor", - PxrUsdKatanaGeomGetDisplayColorAttr(mesh, data)); - - FnKat::GroupAttribute primvarGroup = - PxrUsdKatanaGeomGetPrimvarGroup(mesh, data); - - if (primvarGroup.isValid()) - { - arbBuilder.update(primvarGroup); + _SetSubdivTagsGroup(attrs, mesh, /* hierarchical=*/ false, currentTime); } - geometryBuilder.set("arbitrary", arbBuilder.build()); - attrs.set("geometry", geometryBuilder.build()); + // SPT_HwColor primvar + attrs.set("geometry.arbitrary.SPT_HwColor", + PxrUsdKatanaGeomGetDisplayColorAttr(mesh, data)); attrs.set( "viewer.default.drawOptions.windingOrder", diff --git a/third_party/katana/lib/usdKatana/readNurbsPatch.cpp b/third_party/katana/lib/usdKatana/readNurbsPatch.cpp index 1f37cfcc2e..17233bca5e 100644 --- a/third_party/katana/lib/usdKatana/readNurbsPatch.cpp +++ b/third_party/katana/lib/usdKatana/readNurbsPatch.cpp @@ -324,17 +324,15 @@ PxrUsdKatanaReadNurbsPatch( // Construct the 'geometry' attribute. // - FnKat::GroupBuilder geometryBuilder; - - geometryBuilder.set("point.Pw", _GetPwAttr( + attrs.set("geometry.point.Pw", _GetPwAttr( nurbsPatch, currentTime, motionSampleTimes, data.GetUsdInArgs()->IsMotionBackward())); - geometryBuilder.set("u", _GetUAttr(nurbsPatch, currentTime)); - geometryBuilder.set("v", _GetVAttr(nurbsPatch, currentTime)); - geometryBuilder.set("uSize", _GetUSizeAttr(nurbsPatch, currentTime)); - geometryBuilder.set("vSize", _GetVSizeAttr(nurbsPatch, currentTime)); - geometryBuilder.set("uClosed", _GetUClosedAttr(nurbsPatch, currentTime)); - geometryBuilder.set("vClosed", _GetVClosedAttr(nurbsPatch, currentTime)); - geometryBuilder.set("trimCurves", _GetTrimCurvesAttr(nurbsPatch, currentTime)); + attrs.set("geometry.u", _GetUAttr(nurbsPatch, currentTime)); + attrs.set("geometry.v", _GetVAttr(nurbsPatch, currentTime)); + attrs.set("geometry.uSize", _GetUSizeAttr(nurbsPatch, currentTime)); + attrs.set("geometry.vSize", _GetVSizeAttr(nurbsPatch, currentTime)); + attrs.set("geometry.uClosed", _GetUClosedAttr(nurbsPatch, currentTime)); + attrs.set("geometry.vClosed", _GetVClosedAttr(nurbsPatch, currentTime)); + attrs.set("geometry.trimCurves", _GetTrimCurvesAttr(nurbsPatch, currentTime)); // normals FnKat::Attribute normalsAttr = PxrUsdKatanaGeomGetNormalAttr(nurbsPatch, data); @@ -344,7 +342,7 @@ PxrUsdKatanaReadNurbsPatch( // normals for nuPatches. TfToken interp = nurbsPatch.GetNormalsInterpolation(); if (interp == UsdGeomTokens->vertex) { - geometryBuilder.set("point.N", normalsAttr); + attrs.set("geometry.point.N", normalsAttr); } } @@ -352,21 +350,9 @@ PxrUsdKatanaReadNurbsPatch( FnKat::Attribute velocityAttr = PxrUsdKatanaGeomGetVelocityAttr(nurbsPatch, data); if (velocityAttr.isValid()) { - geometryBuilder.set("point.v", velocityAttr); + attrs.set("geometry.point.v", velocityAttr); } - FnKat::GroupBuilder arbBuilder; - - FnKat::GroupAttribute primvarGroup = PxrUsdKatanaGeomGetPrimvarGroup(nurbsPatch, data); - - if (primvarGroup.isValid()) - { - arbBuilder.update(primvarGroup); - } - - geometryBuilder.set("arbitrary", arbBuilder.build()); - attrs.set("geometry", geometryBuilder.build()); - // // Set the 'windingOrder' viewer attribute. // diff --git a/third_party/katana/lib/usdKatana/readPoints.cpp b/third_party/katana/lib/usdKatana/readPoints.cpp index ae931d3b22..1e475dae08 100644 --- a/third_party/katana/lib/usdKatana/readPoints.cpp +++ b/third_party/katana/lib/usdKatana/readPoints.cpp @@ -69,17 +69,15 @@ PxrUsdKatanaReadPoints( // Construct the 'geometry' attribute. // - FnKat::GroupBuilder geometryBuilder; - // position - geometryBuilder.set("point.P", PxrUsdKatanaGeomGetPAttr(points, data)); + attrs.set("geometry.point.P", PxrUsdKatanaGeomGetPAttr(points, data)); // velocity FnKat::Attribute velocitiesAttr = PxrUsdKatanaGeomGetVelocityAttr(points, data); if (velocitiesAttr.isValid()) { - geometryBuilder.set("point.v", velocitiesAttr); + attrs.set("geometry.point.v", velocitiesAttr); } // normals @@ -91,7 +89,7 @@ PxrUsdKatanaReadPoints( if (interp == UsdGeomTokens->faceVarying || interp == UsdGeomTokens->varying || interp == UsdGeomTokens->vertex) { - geometryBuilder.set("point.N", normalsAttr); + attrs.set("geometry.point.N", normalsAttr); } } @@ -99,19 +97,6 @@ PxrUsdKatanaReadPoints( FnKat::Attribute widthsAttr = _GetWidthAttr(points, currentTime); if (widthsAttr.isValid()) { - geometryBuilder.set("point.width", widthsAttr); - } - - - FnKat::GroupBuilder arbBuilder; - - // other primvars - FnKat::Attribute primvarGroup = PxrUsdKatanaGeomGetPrimvarGroup(points, data); - if (primvarGroup.isValid()) - { - arbBuilder.update(primvarGroup); + attrs.set("geometry.point.width", widthsAttr); } - - geometryBuilder.set("arbitrary", arbBuilder.build()); - attrs.set("geometry", geometryBuilder.build()); } diff --git a/third_party/katana/lib/usdKatana/readPrim.cpp b/third_party/katana/lib/usdKatana/readPrim.cpp index 6f45318775..03572782d3 100644 --- a/third_party/katana/lib/usdKatana/readPrim.cpp +++ b/third_party/katana/lib/usdKatana/readPrim.cpp @@ -38,6 +38,7 @@ #include "pxr/usd/usdGeom/gprim.h" #include "pxr/usd/usdGeom/imageable.h" #include "pxr/usd/usdGeom/mesh.h" +#include "pxr/usd/usdGeom/curves.h" #include "pxr/usd/usdGeom/scope.h" #include "pxr/usd/usdGeom/xform.h" @@ -504,6 +505,80 @@ _AddCustomProperties( return foundCustomProperties; } +FnKat::Attribute +PxrUsdKatanaGeomGetPrimvarGroup( + const UsdGeomImageable& imageable, + const PxrUsdKatanaUsdInPrivateData& data) +{ + // Usd primvars -> Primvar attributes + FnKat::GroupBuilder gdBuilder; + + std::vector primvarAttrs = imageable.GetPrimvars(); + TF_FOR_ALL(primvar, primvarAttrs) { + TfToken name, interpolation; + SdfValueTypeName typeName; + int elementSize; + + primvar->GetDeclarationInfo(&name, &typeName, + &interpolation, &elementSize); + + // Name: this will eventually want to be GetBaseName() to strip + // off prefixes + std::string gdName = name; + + // Convert interpolation -> scope + FnKat::StringAttribute scopeAttr; + const bool isCurve = imageable.GetPrim().IsA(); + if (isCurve && interpolation == UsdGeomTokens->vertex) { + // it's a curve, so "vertex" == "vertex" + scopeAttr = FnKat::StringAttribute("vertex"); + } else { + scopeAttr = FnKat::StringAttribute( + (interpolation == UsdGeomTokens->faceVarying)? "vertex" : + (interpolation == UsdGeomTokens->varying) ? "point" : + (interpolation == UsdGeomTokens->vertex) ? "point" /*see below*/ : + (interpolation == UsdGeomTokens->uniform) ? "face" : + "primitive" ); + } + + // Resolve the value + VtValue vtValue; + if (not primvar->ComputeFlattened( + &vtValue, data.GetUsdInArgs()->GetCurrentTime())) + { + continue; + } + + // Convert value to the required Katana attributes to describe it. + FnKat::Attribute valueAttr, inputTypeAttr, elementSizeAttr; + PxrUsdKatanaUtils::ConvertVtValueToKatCustomGeomAttr( + vtValue, elementSize, typeName.GetRole(), + &valueAttr, &inputTypeAttr, &elementSizeAttr); + + // Bundle them into a group attribute + FnKat::GroupBuilder attrBuilder; + attrBuilder.set("scope", scopeAttr); + attrBuilder.set("inputType", inputTypeAttr); + if (elementSizeAttr.isValid()) { + attrBuilder.set("elementSize", elementSizeAttr); + } + attrBuilder.set("value", valueAttr); + // Note that 'varying' vs 'vertex' require special handling, as in + // Katana they are both expressed as 'point' scope above. To get + // 'vertex' interpolation we must set an additional + // 'interpolationType' attribute. So we will flag that here. + const bool vertexInterpolationType = + (interpolation == UsdGeomTokens->vertex); + if (vertexInterpolationType) { + attrBuilder.set("interpolationType", + FnKat::StringAttribute("subdiv")); + } + gdBuilder.set(gdName, attrBuilder.build()); + } + + return gdBuilder.build(); +} + void PxrUsdKatanaReadPrim( const UsdPrim& prim, @@ -575,6 +650,22 @@ PxrUsdKatanaReadPrim( } } + // + // Set the primvar attributes + // + + if (imageable) + { + FnKat::GroupAttribute primvarGroup = PxrUsdKatanaGeomGetPrimvarGroup(imageable, data); + + if (primvarGroup.isValid()) + { + FnKat::GroupBuilder arbBuilder; + arbBuilder.update(primvarGroup); + attrs.set("geometry.arbitrary", arbBuilder.build()); + } + } + // // Set the 'relativeScopedCoordinateSystems' attribute if such coordinate // systems are found in the children of this prim. diff --git a/third_party/katana/lib/usdKatana/readPrim.h b/third_party/katana/lib/usdKatana/readPrim.h index b53f29a301..62a7d8f2c0 100644 --- a/third_party/katana/lib/usdKatana/readPrim.h +++ b/third_party/katana/lib/usdKatana/readPrim.h @@ -27,6 +27,7 @@ class PxrUsdKatanaAttrMap; class PxrUsdKatanaUsdInPrivateData; class UsdPrim; +class UsdGeomImageable; /// \brief read \p prim into \p attrs. void @@ -41,5 +42,10 @@ PxrUsdKatanaReadPrimPrmanStatements( double currentTime, Foundry::Katana::GroupBuilder& statementBuilder); +Foundry::Katana::Attribute +PxrUsdKatanaGeomGetPrimvarGroup( + const UsdGeomImageable& imageable, + const PxrUsdKatanaUsdInPrivateData& data); + #endif // PXRUSDKATANA_REAGPRIM_H From fb374865cd024f1dda69a9b443eb23bec45a64ac Mon Sep 17 00:00:00 2001 From: takahito-tejima Date: Tue, 25 Oct 2016 14:21:15 -0700 Subject: [PATCH 311/380] [Glf, UsdImagingGL, usdviewq] update lighting parameter plumbing Add another way of passing lighting parameters (GlfSimpleLight, GlfSimpleMaterial) in usdview. we no longer need to push the parameters in GL fixed pipeline state and suck them back. RefEngine takes those parameters and calls corresponding GL calls for compatibility. SetLightingStateFromOpenGL is still being used in the third party plugins and dress group. They should be updated in the same way then that function can be removed. (Internal change: 1666888) --- pxr/imaging/lib/glf/CMakeLists.txt | 2 + pxr/imaging/lib/glf/module.cpp | 2 + pxr/imaging/lib/glf/wrapSimpleLight.cpp | 121 ++++++++++++++++++ pxr/imaging/lib/glf/wrapSimpleMaterial.cpp | 62 +++++++++ pxr/usdImaging/lib/usdImagingGL/engine.cpp | 10 ++ pxr/usdImaging/lib/usdImagingGL/engine.h | 9 ++ pxr/usdImaging/lib/usdImagingGL/gl.cpp | 10 ++ pxr/usdImaging/lib/usdImagingGL/gl.h | 5 + pxr/usdImaging/lib/usdImagingGL/hdEngine.cpp | 23 ++++ pxr/usdImaging/lib/usdImagingGL/hdEngine.h | 4 + pxr/usdImaging/lib/usdImagingGL/refEngine.cpp | 38 ++++++ pxr/usdImaging/lib/usdImagingGL/refEngine.h | 5 + pxr/usdImaging/lib/usdImagingGL/wrapGL.cpp | 12 ++ pxr/usdImaging/lib/usdviewq/stageView.py | 84 ++++++------ 14 files changed, 343 insertions(+), 44 deletions(-) create mode 100644 pxr/imaging/lib/glf/wrapSimpleLight.cpp create mode 100644 pxr/imaging/lib/glf/wrapSimpleMaterial.cpp diff --git a/pxr/imaging/lib/glf/CMakeLists.txt b/pxr/imaging/lib/glf/CMakeLists.txt index 6aff7c7c33..b5bcf33f29 100644 --- a/pxr/imaging/lib/glf/CMakeLists.txt +++ b/pxr/imaging/lib/glf/CMakeLists.txt @@ -82,6 +82,8 @@ pxr_shared_library(glf wrapDiagnostic.cpp wrapDrawTarget.cpp wrapGlew.cpp + wrapSimpleLight.cpp + wrapSimpleMaterial.cpp wrapTexture.cpp wrapTextureRegistry.cpp wrapUVTexture.cpp diff --git a/pxr/imaging/lib/glf/module.cpp b/pxr/imaging/lib/glf/module.cpp index e5dce3ef14..b8e652c21a 100644 --- a/pxr/imaging/lib/glf/module.cpp +++ b/pxr/imaging/lib/glf/module.cpp @@ -33,4 +33,6 @@ TF_WRAP_MODULE TF_WRAP( UVTexture ); TF_WRAP( UVTextureStorage ); TF_WRAP( Glew ); + TF_WRAP( SimpleLight ); + TF_WRAP( SimpleMaterial ); } diff --git a/pxr/imaging/lib/glf/wrapSimpleLight.cpp b/pxr/imaging/lib/glf/wrapSimpleLight.cpp new file mode 100644 index 0000000000..f5e0d0ca9d --- /dev/null +++ b/pxr/imaging/lib/glf/wrapSimpleLight.cpp @@ -0,0 +1,121 @@ +// +// 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. +// +#include "pxr/imaging/glf/simpleLight.h" + +#include + +using namespace boost::python; + +void wrapSimpleLight() +{ + typedef GlfSimpleLight This; + + class_ ("SimpleLight", init<>() ) + .add_property("transform", + make_function( + &This::GetTransform, + return_value_policy()), + &This::SetTransform) + .add_property("ambient", + make_function( + &This::GetAmbient, + return_value_policy()), + &This::SetAmbient) + .add_property("diffuse", + make_function( + &This::GetDiffuse, + return_value_policy()), + &This::SetDiffuse) + .add_property("specular", + make_function( + &This::GetSpecular, + return_value_policy()), + &This::SetSpecular) + .add_property("position", + make_function( + &This::GetPosition, + return_value_policy()), + &This::SetPosition) + .add_property("spotDirection", + make_function( + &This::GetSpotDirection, + return_value_policy()), + &This::SetSpotDirection) + .add_property("spotCutoff", + make_function( + &This::GetSpotCutoff, + return_value_policy()), + &This::SetSpotCutoff) + .add_property("spotFalloff", + make_function( + &This::GetSpotFalloff, + return_value_policy()), + &This::SetSpotFalloff) + .add_property("attenuation", + make_function( + &This::GetAttenuation, + return_value_policy()), + &This::SetAttenuation) + .add_property("shadowMatrix", + make_function( + &This::GetShadowMatrix, + return_value_policy()), + &This::SetShadowMatrix) + .add_property("shadowResolution", + make_function( + &This::GetShadowResolution, + return_value_policy()), + &This::SetShadowResolution) + .add_property("shadowBias", + make_function( + &This::GetShadowBias, + return_value_policy()), + &This::SetShadowBias) + .add_property("shadowBlur", + make_function( + &This::GetShadowBlur, + return_value_policy()), + &This::SetShadowBlur) + .add_property("shadowIndex", + make_function( + &This::GetShadowIndex, + return_value_policy()), + &This::SetShadowIndex) + .add_property("hasShadow", + make_function( + &This::HasShadow, + return_value_policy()), + &This::SetHasShadow) + .add_property("isCameraSpaceLight", + make_function( + &This::IsCameraSpaceLight, + return_value_policy()), + &This::SetIsCameraSpaceLight) + .add_property("id", + make_function( + &This::GetID, + return_value_policy()), + &This::SetID) + ; +} diff --git a/pxr/imaging/lib/glf/wrapSimpleMaterial.cpp b/pxr/imaging/lib/glf/wrapSimpleMaterial.cpp new file mode 100644 index 0000000000..c9a6a15e38 --- /dev/null +++ b/pxr/imaging/lib/glf/wrapSimpleMaterial.cpp @@ -0,0 +1,62 @@ +// +// 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. +// +#include "pxr/imaging/glf/simpleMaterial.h" + +#include + +using namespace boost::python; + +void wrapSimpleMaterial() +{ + typedef GlfSimpleMaterial This; + + class_ ("SimpleMaterial", init<>()) + .add_property("ambient", + make_function( + &This::GetAmbient, + return_value_policy()), + &This::SetAmbient) + .add_property("diffuse", + make_function( + &This::GetDiffuse, + return_value_policy()), + &This::SetDiffuse) + .add_property("specular", + make_function( + &This::GetSpecular, + return_value_policy()), + &This::SetSpecular) + .add_property("emission", + make_function( + &This::GetEmission, + return_value_policy()), + &This::SetEmission) + .add_property("shininess", + make_function( + &This::GetShininess, + return_value_policy()), + &This::SetShininess) + ; +} + diff --git a/pxr/usdImaging/lib/usdImagingGL/engine.cpp b/pxr/usdImaging/lib/usdImagingGL/engine.cpp index 7de94ab422..e612c06746 100644 --- a/pxr/usdImaging/lib/usdImagingGL/engine.cpp +++ b/pxr/usdImaging/lib/usdImagingGL/engine.cpp @@ -81,6 +81,16 @@ UsdImagingGLEngine::SetLightingState(GlfSimpleLightingContextPtr const &src) // By default, do nothing. } +/* virtual */ +void +UsdImagingGLEngine::SetLightingState(GlfSimpleLightVector const &lights, + GlfSimpleMaterial const &material, + GfVec4f const &sceneAmbient) +{ + // By default, do nothing. +} + + /* virtual */ void UsdImagingGLEngine::SetRootTransform(GfMatrix4d const& xf) diff --git a/pxr/usdImaging/lib/usdImagingGL/engine.h b/pxr/usdImaging/lib/usdImagingGL/engine.h index 155a0b57f8..7e3be5dcc4 100644 --- a/pxr/usdImaging/lib/usdImagingGL/engine.h +++ b/pxr/usdImaging/lib/usdImagingGL/engine.h @@ -28,6 +28,9 @@ #include "pxr/usdImaging/usdImaging/version.h" +#include "pxr/imaging/glf/simpleLight.h" +#include "pxr/imaging/glf/simpleMaterial.h" + #include "pxr/base/tf/declarePtrs.h" #include "pxr/base/tf/type.h" #include "pxr/usd/sdf/path.h" @@ -36,6 +39,7 @@ #include "pxr/base/gf/frustum.h" #include "pxr/base/gf/matrix4d.h" #include "pxr/base/gf/vec4d.h" +#include "pxr/base/gf/vec4f.h" #include "pxr/base/gf/vec4i.h" #include "pxr/base/vt/dictionary.h" @@ -178,6 +182,11 @@ class UsdImagingGLEngine : private boost::noncopyable { /// Copy lighting state from another lighting context. virtual void SetLightingState(GlfSimpleLightingContextPtr const &src); + /// Set lighting state + virtual void SetLightingState(GlfSimpleLightVector const &lights, + GlfSimpleMaterial const &material, + GfVec4f const &sceneAmbient); + /// Sets the root transform. virtual void SetRootTransform(GfMatrix4d const& xf); diff --git a/pxr/usdImaging/lib/usdImagingGL/gl.cpp b/pxr/usdImaging/lib/usdImagingGL/gl.cpp index 61b718925e..4335d5d50e 100644 --- a/pxr/usdImaging/lib/usdImagingGL/gl.cpp +++ b/pxr/usdImaging/lib/usdImagingGL/gl.cpp @@ -222,6 +222,16 @@ UsdImagingGL::SetLightingStateFromOpenGL() _engine->SetLightingStateFromOpenGL(); } +/* virtual */ +void +UsdImagingGL::SetLightingState(GlfSimpleLightVector const &lights, + GlfSimpleMaterial const &material, + GfVec4f const &sceneAmbient) +{ + _engine->SetLightingState(lights, material, sceneAmbient); +} + + /* virtual */ void UsdImagingGL::SetLightingState(GlfSimpleLightingContextPtr const &src) diff --git a/pxr/usdImaging/lib/usdImagingGL/gl.h b/pxr/usdImaging/lib/usdImagingGL/gl.h index 5f8527e7bd..a553df4776 100644 --- a/pxr/usdImaging/lib/usdImagingGL/gl.h +++ b/pxr/usdImaging/lib/usdImagingGL/gl.h @@ -114,6 +114,11 @@ class UsdImagingGL : public UsdImagingGLEngine { /// Copy lighting state from another lighting context. virtual void SetLightingState(GlfSimpleLightingContextPtr const &src); + /// Set lighting state + virtual void SetLightingState(GlfSimpleLightVector const &lights, + GlfSimpleMaterial const &material, + GfVec4f const &sceneAmbient); + virtual void SetRootTransform(GfMatrix4d const& xf); virtual void SetRootVisibility(bool isVisible); diff --git a/pxr/usdImaging/lib/usdImagingGL/hdEngine.cpp b/pxr/usdImaging/lib/usdImagingGL/hdEngine.cpp index 5a65ce3b96..7b7bd11b28 100644 --- a/pxr/usdImaging/lib/usdImagingGL/hdEngine.cpp +++ b/pxr/usdImaging/lib/usdImagingGL/hdEngine.cpp @@ -605,6 +605,29 @@ UsdImagingGLHdEngine::SetLightingStateFromOpenGL() _lightingContextForOpenGLState); } +/* virtual */ +void +UsdImagingGLHdEngine::SetLightingState(GlfSimpleLightVector const &lights, + GlfSimpleMaterial const &material, + GfVec4f const &sceneAmbient) +{ + // we still use _lightingContextForOpenGLState for convenience, but + // set the values directly. + if (not _lightingContextForOpenGLState) { + _lightingContextForOpenGLState = GlfSimpleLightingContext::New(); + } + _lightingContextForOpenGLState->SetLights(lights); + _lightingContextForOpenGLState->SetMaterial(material); + _lightingContextForOpenGLState->SetSceneAmbient(sceneAmbient); + _lightingContextForOpenGLState->SetUseLighting(lights.size() > 0); + + _defaultTaskDelegate->SetLightingState(_lightingContextForOpenGLState); + + if (_currentPluginTaskDelegate) + _currentPluginTaskDelegate->SetLightingState( + _lightingContextForOpenGLState); +} + /* virtual */ void UsdImagingGLHdEngine::SetLightingState(GlfSimpleLightingContextPtr const &src) diff --git a/pxr/usdImaging/lib/usdImagingGL/hdEngine.h b/pxr/usdImaging/lib/usdImagingGL/hdEngine.h index 8f46109196..4c52d1bb25 100644 --- a/pxr/usdImaging/lib/usdImagingGL/hdEngine.h +++ b/pxr/usdImaging/lib/usdImagingGL/hdEngine.h @@ -88,6 +88,10 @@ class UsdImagingGLHdEngine : public UsdImagingGLEngine virtual void SetLightingState(GlfSimpleLightingContextPtr const &src); + virtual void SetLightingState(GlfSimpleLightVector const &lights, + GlfSimpleMaterial const &material, + GfVec4f const &sceneAmbient); + virtual void SetRootTransform(GfMatrix4d const& xf); virtual void SetRootVisibility(bool isVisible); diff --git a/pxr/usdImaging/lib/usdImagingGL/refEngine.cpp b/pxr/usdImaging/lib/usdImagingGL/refEngine.cpp index 97c4c5a9e9..ff81566b6e 100644 --- a/pxr/usdImaging/lib/usdImagingGL/refEngine.cpp +++ b/pxr/usdImaging/lib/usdImagingGL/refEngine.cpp @@ -474,6 +474,44 @@ UsdImagingGLRefEngine::SetCameraState(const GfMatrix4d& viewMatrix, glLoadMatrixd(viewMatrix.GetArray()); } +void +UsdImagingGLRefEngine::SetLightingState(GlfSimpleLightVector const &lights, + GlfSimpleMaterial const &material, + GfVec4f const &sceneAmbient) +{ + if (lights.empty()) { + glDisable(GL_LIGHTING); + } else { + glEnable(GL_LIGHTING); + + static int maxLights = 0; + if (maxLights == 0) { + glGetIntegerv(GL_MAX_LIGHTS, &maxLights); + } + + for (size_t i = 0; i < maxLights; ++i) { + if (i < (int)lights.size()) { + glEnable(GL_LIGHT0+i); + GlfSimpleLight const &light = lights[i]; + + glLightfv(GL_LIGHT0+i, GL_POSITION, light.GetPosition().data()); + glLightfv(GL_LIGHT0+i, GL_AMBIENT, light.GetAmbient().data()); + glLightfv(GL_LIGHT0+i, GL_DIFFUSE, light.GetDiffuse().data()); + glLightfv(GL_LIGHT0+i, GL_SPECULAR, light.GetSpecular().data()); + // omit spot parameters. + } else { + glDisable(GL_LIGHT0+i); + } + } + glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, + material.GetAmbient().data()); + glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, + material.GetSpecular().data()); + glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, + material.GetShininess()); + } +} + void UsdImagingGLRefEngine::_OnObjectsChanged(UsdNotice::ObjectsChanged const& notice, UsdStageWeakPtr const& sender) diff --git a/pxr/usdImaging/lib/usdImagingGL/refEngine.h b/pxr/usdImaging/lib/usdImagingGL/refEngine.h index 063e44be1d..b9c3cd69b3 100644 --- a/pxr/usdImaging/lib/usdImagingGL/refEngine.h +++ b/pxr/usdImaging/lib/usdImagingGL/refEngine.h @@ -53,6 +53,11 @@ class UsdImagingGLRefEngine : public UsdImagingGLEngine, public TfWeakBase { const GfMatrix4d& projectionMatrix, const GfVec4d& viewport); + /// Set lighting state + virtual void SetLightingState(GlfSimpleLightVector const &lights, + GlfSimpleMaterial const &material, + GfVec4f const &sceneAmbient); + virtual void InvalidateBuffers(); virtual SdfPath GetPrimPathFromPrimIdColor( diff --git a/pxr/usdImaging/lib/usdImagingGL/wrapGL.cpp b/pxr/usdImaging/lib/usdImagingGL/wrapGL.cpp index 7ae5ebf872..41eaad1997 100644 --- a/pxr/usdImaging/lib/usdImagingGL/wrapGL.cpp +++ b/pxr/usdImaging/lib/usdImagingGL/wrapGL.cpp @@ -32,6 +32,7 @@ #include "pxr/usdImaging/usdImaging/delegate.h" #include "pxr/usd/usd/prim.h" +#include "pxr/base/tf/pyContainerConversions.h" #include "pxr/base/tf/pyEnum.h" #include "pxr/base/tf/pyResultConversions.h" @@ -80,6 +81,13 @@ _GetPrimPathFromInstanceIndex( return boost::python::make_tuple(path, absoluteInstanceIndex); } +static void +_SetLightingState(UsdImagingGL &self, GlfSimpleLightVector const &lights, + GlfSimpleMaterial const &material, GfVec4f const &sceneAmbient) +{ + self.SetLightingState(lights, material, sceneAmbient); +} + void wrapGL() { { @@ -92,6 +100,7 @@ void wrapGL() .def("SetCameraState", &UsdImagingGL::SetCameraState) .def("SetLightingStateFromOpenGL", &UsdImagingGL::SetLightingStateFromOpenGL) + .def("SetLightingState", &_SetLightingState) .def("SetCameraStateFromOpenGL", &UsdImagingGL::SetCameraStateFromOpenGL) .def("SetSelected", &UsdImagingGL::SetSelected) .def("ClearSelected", &UsdImagingGL::ClearSelected) @@ -155,5 +164,8 @@ void wrapGL() .def_readwrite("enableHardwareShading", &Params::enableHardwareShading) ; + TfPyContainerConversions::from_python_sequence< + std::vector, + TfPyContainerConversions::variable_capacity_policy>(); } } diff --git a/pxr/usdImaging/lib/usdviewq/stageView.py b/pxr/usdImaging/lib/usdviewq/stageView.py index da173cc99c..7c2a86971f 100644 --- a/pxr/usdImaging/lib/usdviewq/stageView.py +++ b/pxr/usdImaging/lib/usdviewq/stageView.py @@ -1485,7 +1485,6 @@ def paintGL(self): GL.glEnable(GL_FRAMEBUFFER_SRGB_EXT) GL.glClearColor(*(Gf.ConvertDisplayToLinear(Gf.Vec4f(self._clearColor)))) - GL.glShadeModel(GL.GL_SMOOTH) GL.glEnable(GL.GL_DEPTH_TEST) GL.glDepthFunc(GL.GL_LESS) @@ -1516,58 +1515,54 @@ def paintGL(self): gfCamera.clippingPlanes] if self._nodes: - self.setupOpenGLViewMatricesForFrustum(frustum) - - GL.glColor3f(1.0,1.0,1.0) - # for renderModes that need lights if self.renderMode in ("Flat Shaded", "Smooth Shaded", "WireframeOnSurface", "Geom Smooth", "Geom Flat"): - GL.glEnable(GL.GL_LIGHTING) + stagePos = Gf.Vec3d(self._bbcenter[0], self._bbcenter[1], self._bbcenter[2]) stageDir = (stagePos - cam_pos).GetNormalized() + lights = [] # ambient light located at the camera if self.ambientLightOnly: - GL.glEnable(GL.GL_LIGHT0) - GL.glLightfv(GL.GL_LIGHT0, GL.GL_POSITION, - (cam_pos[0], cam_pos[1], cam_pos[2], 1)) + l = Glf.SimpleLight() + l.ambient = (0, 0, 0, 0) + l.position = (cam_pos[0], cam_pos[1], cam_pos[2], 1) + lights.append(l) # three-point lighting else: - GL.glDisable(GL.GL_LIGHT0) - if self.keyLightEnabled: # 45 degree horizontal viewing angle, 20 degree vertical keyHorz = -1 / tan(rad(45)) * cam_right keyVert = 1 / tan(rad(70)) * cam_up keyPos = cam_pos + (keyVert + keyHorz) * self._dist keyColor = (.8, .8, .8, 1.0) - - GL.glLightfv(GL.GL_LIGHT1, GL.GL_AMBIENT,(0,0,0,0)) - GL.glLightfv(GL.GL_LIGHT1, GL.GL_DIFFUSE, keyColor) - GL.glLightfv(GL.GL_LIGHT1, GL.GL_SPECULAR, keyColor) - GL.glLightfv(GL.GL_LIGHT1, GL.GL_POSITION, - (keyPos[0], keyPos[1], keyPos[2], 1)) - GL.glEnable(GL.GL_LIGHT1) - + + l = Glf.SimpleLight() + l.ambient = (0, 0, 0, 0) + l.diffuse = keyColor + l.specular = keyColor + l.position = (keyPos[0], keyPos[1], keyPos[2], 1) + lights.append(l) + if self.fillLightEnabled: # 60 degree horizontal viewing angle, 45 degree vertical fillHorz = 1 / tan(rad(30)) * cam_right fillVert = 1 / tan(rad(45)) * cam_up fillPos = cam_pos + (fillVert + fillHorz) * self._dist fillColor = (.6, .6, .6, 1.0) - - GL.glLightfv(GL.GL_LIGHT2, GL.GL_AMBIENT, (0,0,0,0)) - GL.glLightfv(GL.GL_LIGHT2, GL.GL_DIFFUSE, fillColor) - GL.glLightfv(GL.GL_LIGHT2, GL.GL_SPECULAR, fillColor) - GL.glLightfv(GL.GL_LIGHT2, GL.GL_POSITION, - (fillPos[0], fillPos[1], fillPos[2], 1)) - GL.glEnable(GL.GL_LIGHT2) - + + l = Glf.SimpleLight() + l.ambient = (0, 0, 0, 0) + l.diffuse = fillColor + l.specular = fillColor + l.position = (fillPos[0], fillPos[1], fillPos[2], 1) + lights.append(l) + if self.backLightEnabled: # back light base is camera position refelcted over origin # 30 degree horizontal viewing angle, 30 degree vertical @@ -1576,23 +1571,21 @@ def paintGL(self): backVert = -1 / tan(rad(60)) * cam_up backPos += (backHorz + backVert) * self._dist backColor = (.6, .6, .6, 1.0) - - GL.glLightfv(GL.GL_LIGHT2, GL.GL_AMBIENT, (0,0,0,0)) - GL.glLightfv(GL.GL_LIGHT3, GL.GL_DIFFUSE, backColor) - GL.glLightfv(GL.GL_LIGHT3, GL.GL_SPECULAR, backColor) - GL.glLightfv(GL.GL_LIGHT3, GL.GL_POSITION, - (backPos[0], backPos[1], backPos[2], 1)) - GL.glEnable(GL.GL_LIGHT3) - - GL.glMaterialfv(GL.GL_FRONT_AND_BACK, GL.GL_AMBIENT, - (0.2, 0.2, 0.2, 1.0)) - GL.glMaterialfv(GL.GL_FRONT_AND_BACK, GL.GL_SPECULAR, - (0.5, 0.5, 0.5, 1.0)) - GL.glMaterialfv(GL.GL_FRONT_AND_BACK, GL.GL_SHININESS, 32.0) - - # XXX continue to set lighting state via OpenGL - # for compatibility w/ and w/o hydra enabled - self._renderer.SetLightingStateFromOpenGL() + + l = Glf.SimpleLight() + l.ambient = (0, 0, 0, 0) + l.diffuse = backColor + l.specular = backColor + l.position = (backPos[0], backPos[1], backPos[2], 1) + lights.append(l) + + material = Glf.SimpleMaterial() + material.ambient = (0.2, 0.2, 0.2, 1.0) + material.specular = (0.5, 0.5, 0.5, 1.0) + material.shininess = 32.0 + sceneAmbient = (0.2, 0.2, 0.2, 1.0) + + self._renderer.SetLightingState(lights, material, sceneAmbient) if self.renderMode == "Hidden Surface Wireframe": GL.glEnable( GL.GL_POLYGON_OFFSET_FILL ) @@ -1609,6 +1602,9 @@ def paintGL(self): self.renderSinglePass(self._renderModeDict[self.renderMode], self.drawSelHighlights) + # Axis bbox drawing + self.setupOpenGLViewMatricesForFrustum(frustum) + # lights interfere with the correct coloring of bbox and axes GL.glDisable(GL.GL_LIGHTING) GL.glDisable(GL.GL_LIGHT0) From 6775defef08030a822f705294968e3bf16cc3cc2 Mon Sep 17 00:00:00 2001 From: dakrunch Date: Tue, 25 Oct 2016 14:21:37 -0700 Subject: [PATCH 312/380] Read usd collections (Internal change: 1667080) --- third_party/katana/lib/usdKatana/readPrim.cpp | 52 ++++++++++++++++++- 1 file changed, 50 insertions(+), 2 deletions(-) diff --git a/third_party/katana/lib/usdKatana/readPrim.cpp b/third_party/katana/lib/usdKatana/readPrim.cpp index 03572782d3..7ea20bccd8 100644 --- a/third_party/katana/lib/usdKatana/readPrim.cpp +++ b/third_party/katana/lib/usdKatana/readPrim.cpp @@ -41,6 +41,7 @@ #include "pxr/usd/usdGeom/curves.h" #include "pxr/usd/usdGeom/scope.h" #include "pxr/usd/usdGeom/xform.h" +#include "pxr/usd/usdGeom/collectionAPI.h" #include "pxr/usd/usdShade/pShaderUtils.h" #include "pxr/usd/usdShade/look.h" @@ -326,19 +327,55 @@ _BuildScopedCoordinateSystems( return foundCoordSys; } +static bool +_BuildCollections( + const UsdPrim& prim, + FnKat::GroupBuilder& collectionsBuilder) +{ + std::vector collections = + UsdGeomCollectionAPI::GetCollections(prim); + + std::string prefix = prim.GetPath().GetString(); + int prefixLength = prefix.length(); + + SdfPathVector targets; + for (int iCollection = 0; iCollection < collections.size(); ++iCollection) + { + FnKat::StringBuilder collectionBuilder; + UsdGeomCollectionAPI &collection = collections[iCollection]; + TfToken name = collection.GetCollectionName(); + collection.GetTargets(&targets); + for (int iTarget = 0; iTarget < targets.size(); ++iTarget) + { + std::string relativePath = + targets[iTarget].GetString().substr(prefixLength); + + collectionBuilder.push_back(relativePath); + } + + collectionsBuilder.set(name.GetString() + ".baked", + collectionBuilder.build()); + } + + return (collections.size() > 0); +} + + static void _AddExtraAttributesOrNamespaces( const UsdPrim& prim, const PxrUsdKatanaUsdInPrivateData& data, PxrUsdKatanaAttrMap& attrs) { - const std::string& rootLocation = data.GetUsdInArgs()->GetRootLocationPath(); + const std::string& rootLocation = + data.GetUsdInArgs()->GetRootLocationPath(); const double currentTime = data.GetUsdInArgs()->GetCurrentTime(); const PxrUsdKatanaUsdInArgs::StringListMap& extraAttributesOrNamespaces = data.GetUsdInArgs()->GetExtraAttributesOrNamespaces(); - PxrUsdKatanaUsdInArgs::StringListMap::const_iterator I = extraAttributesOrNamespaces.begin(); + PxrUsdKatanaUsdInArgs::StringListMap::const_iterator I = + extraAttributesOrNamespaces.begin(); for (; I != extraAttributesOrNamespaces.end(); ++I) { const std::string& name = (*I).first; @@ -677,6 +714,17 @@ PxrUsdKatanaReadPrim( attrs.set("relativeScopedCoordinateSystems", coordSysBuilder.build()); } + // + // Set the 'collections' attribute if any found + // + + FnKat::GroupBuilder collectionsBuilder; + if (_BuildCollections(prim, collectionsBuilder)) + { + attrs.set("collections", collectionsBuilder.build()); + } + + // // Set the 'customProperties' attribute (if enabled by env variable). // From f5d73aa1e1b61e0a16e8d2db8663db292760fbf1 Mon Sep 17 00:00:00 2001 From: sunyab Date: Tue, 25 Oct 2016 14:21:46 -0700 Subject: [PATCH 313/380] Remove Python-related headers from tf/type.h. (Internal change: 1667139) --- pxr/base/lib/gf/multiInterval.cpp | 1 + pxr/base/lib/plug/testenv/TestPlugDsoUnloadable.cpp | 1 + pxr/base/lib/tf/pyUtils.h | 3 ++- pxr/base/lib/tf/type.cpp | 2 ++ pxr/base/lib/tf/type.h | 3 --- pxr/base/lib/vt/arrayPyBuffer.cpp | 1 + pxr/base/lib/vt/value.h | 1 + pxr/usd/lib/sdf/valueTypeRegistry.cpp | 1 + pxr/usd/lib/usdUtils/wrapPipeline.cpp | 1 + 9 files changed, 10 insertions(+), 4 deletions(-) diff --git a/pxr/base/lib/gf/multiInterval.cpp b/pxr/base/lib/gf/multiInterval.cpp index 2042ea7ee4..95a49793ab 100644 --- a/pxr/base/lib/gf/multiInterval.cpp +++ b/pxr/base/lib/gf/multiInterval.cpp @@ -25,6 +25,7 @@ #include "pxr/base/gf/ostreamHelpers.h" #include "pxr/base/tf/iterator.h" +#include "pxr/base/tf/tf.h" #include "pxr/base/tf/type.h" #include diff --git a/pxr/base/lib/plug/testenv/TestPlugDsoUnloadable.cpp b/pxr/base/lib/plug/testenv/TestPlugDsoUnloadable.cpp index 797e48e355..e4e466da68 100644 --- a/pxr/base/lib/plug/testenv/TestPlugDsoUnloadable.cpp +++ b/pxr/base/lib/plug/testenv/TestPlugDsoUnloadable.cpp @@ -22,6 +22,7 @@ // language governing permissions and limitations under the Apache License. // #include "pxr/base/plug/testPlugBase.h" +#include "pxr/base/tf/tf.h" // This plugin depends on an undefined external function // and so will be unloadable. diff --git a/pxr/base/lib/tf/pyUtils.h b/pxr/base/lib/tf/pyUtils.h index 13fb731838..ad58040464 100644 --- a/pxr/base/lib/tf/pyUtils.h +++ b/pxr/base/lib/tf/pyUtils.h @@ -37,8 +37,9 @@ #include #include -#include #include +#include +#include #include /// A macro which expands to the proper __repr__ prefix for a library. This is diff --git a/pxr/base/lib/tf/type.cpp b/pxr/base/lib/tf/type.cpp index 1f81df688c..4732e0e755 100644 --- a/pxr/base/lib/tf/type.cpp +++ b/pxr/base/lib/tf/type.cpp @@ -30,7 +30,9 @@ #include "pxr/base/tf/iterator.h" #include "pxr/base/tf/mallocTag.h" #include "pxr/base/tf/singleton.h" +#include "pxr/base/tf/pyLock.h" #include "pxr/base/tf/pyObjWrapper.h" +#include "pxr/base/tf/pyObjectFinder.h" #include "pxr/base/tf/pyUtils.h" #include "pxr/base/tf/stl.h" #include "pxr/base/tf/typeInfoMap.h" diff --git a/pxr/base/lib/tf/type.h b/pxr/base/lib/tf/type.h index d4c65df6bc..23ad5c3c83 100644 --- a/pxr/base/lib/tf/type.h +++ b/pxr/base/lib/tf/type.h @@ -25,9 +25,6 @@ #define TF_TYPE_H #include "pxr/base/tf/cxxCast.h" -#include "pxr/base/tf/pyIdentity.h" -#include "pxr/base/tf/pyLock.h" -#include "pxr/base/tf/pyObjectFinder.h" #include "pxr/base/tf/refPtr.h" #include "pxr/base/tf/registryManager.h" #include "pxr/base/tf/traits.h" diff --git a/pxr/base/lib/vt/arrayPyBuffer.cpp b/pxr/base/lib/vt/arrayPyBuffer.cpp index 91a94ea1dc..73ebb9dc62 100644 --- a/pxr/base/lib/vt/arrayPyBuffer.cpp +++ b/pxr/base/lib/vt/arrayPyBuffer.cpp @@ -30,6 +30,7 @@ #include "pxr/base/gf/traits.h" #include "pxr/base/tf/pyLock.h" +#include "pxr/base/tf/pyUtils.h" #include #include diff --git a/pxr/base/lib/vt/value.h b/pxr/base/lib/vt/value.h index 5268ee5ab9..fb737b6d1a 100644 --- a/pxr/base/lib/vt/value.h +++ b/pxr/base/lib/vt/value.h @@ -28,6 +28,7 @@ #include "pxr/base/arch/hints.h" #include "pxr/base/tf/move.h" #include "pxr/base/tf/pointerAndBits.h" +#include "pxr/base/tf/pyLock.h" #include "pxr/base/tf/pyObjWrapper.h" #include "pxr/base/tf/safeTypeCompare.h" #include "pxr/base/tf/stringUtils.h" diff --git a/pxr/usd/lib/sdf/valueTypeRegistry.cpp b/pxr/usd/lib/sdf/valueTypeRegistry.cpp index f7859e8f99..d1e10b946b 100644 --- a/pxr/usd/lib/sdf/valueTypeRegistry.cpp +++ b/pxr/usd/lib/sdf/valueTypeRegistry.cpp @@ -26,6 +26,7 @@ #include "pxr/usd/sdf/valueTypePrivate.h" #include "pxr/usd/sdf/types.h" // For SdfDimensionlessUnitDefault #include "pxr/base/tf/diagnostic.h" +#include "pxr/base/tf/hashmap.h" #include "pxr/base/tf/type.h" #include diff --git a/pxr/usd/lib/usdUtils/wrapPipeline.cpp b/pxr/usd/lib/usdUtils/wrapPipeline.cpp index a8ab6a7902..ef5148888d 100644 --- a/pxr/usd/lib/usdUtils/wrapPipeline.cpp +++ b/pxr/usd/lib/usdUtils/wrapPipeline.cpp @@ -22,6 +22,7 @@ // language governing permissions and limitations under the Apache License. // #include +#include #include "pxr/usd/usdUtils/pipeline.h" From 40c6e0d340f76ea304c2d3bb712fbc518959ed91 Mon Sep 17 00:00:00 2001 From: sunyab Date: Tue, 25 Oct 2016 14:22:00 -0700 Subject: [PATCH 314/380] Remove ArchGetHomeDirectory and ArchGetUserName (Internal change: 1667174) --- pxr/base/lib/arch/systemInfo.cpp | 49 -------------------- pxr/base/lib/arch/systemInfo.h | 15 ------ pxr/base/lib/arch/testenv/testSystemInfo.cpp | 7 --- 3 files changed, 71 deletions(-) diff --git a/pxr/base/lib/arch/systemInfo.cpp b/pxr/base/lib/arch/systemInfo.cpp index d68388e61d..08ca1ba825 100644 --- a/pxr/base/lib/arch/systemInfo.cpp +++ b/pxr/base/lib/arch/systemInfo.cpp @@ -95,55 +95,6 @@ ArchGetCwd() return "."; } -string -ArchGetHomeDirectory(const std::string &login) -{ - if (login.empty()) { - const char* home = getenv("HOME"); - if (home && home[0] != '\0') - return home; - } - - - struct passwd pwd; - struct passwd* pwdPtr = &pwd; - struct passwd* tmpPtr; - char buf[2048]; - - // Both getpw* functions return zero on success, or an error number if an - // error occurs. If no entry is found for the uid/login, zero is returned - // and tmpPtr is set to NULL. - int result = login.empty() - ? getpwuid_r(getuid(), pwdPtr, buf, sizeof(buf), &tmpPtr) - : getpwnam_r(login.c_str(), pwdPtr, buf, sizeof(buf), &tmpPtr); - if (result == 0 and tmpPtr) - return pwd.pw_dir; - - return ""; -} - -string -ArchGetUserName() -{ - const char* envVarNames[] = {"LOGNAME", "USER", "LNAME", "USERNAME"}; - for (size_t i = 0; i < sizeof(envVarNames) / sizeof(*envVarNames); ++i) { - if (const char* user = getenv(envVarNames[i])) { - if (user && user[0] != '\0') - return user; - } - } - - // Convert the effective user ID into a string. If we can't do it, - // fall back to user name. - char buffer[2048]; - passwd pwd, *resultPwd; - - if (getpwuid_r(geteuid(), &pwd, buffer, sizeof(buffer), &resultPwd) == 0) - return pwd.pw_name; - - return ""; -} - string ArchGetExecutablePath() { diff --git a/pxr/base/lib/arch/systemInfo.h b/pxr/base/lib/arch/systemInfo.h index cc2a4267eb..94dbd9bb79 100644 --- a/pxr/base/lib/arch/systemInfo.h +++ b/pxr/base/lib/arch/systemInfo.h @@ -38,21 +38,6 @@ ARCH_API std::string ArchGetCwd(); -/// Return user's home directory. -/// -/// If \p login is not supplied, the home directory of the current user is -/// returned. Otherwise, the home directory of the user with the specified -/// login is returned. If the home directory cannot be determined, the empty -/// string is returned. -ARCH_API -std::string ArchGetHomeDirectory(const std::string &login = std::string()); - -/// Return user name. -/// -/// If the user name cannot determined, the empty string is returned. -ARCH_API -std::string ArchGetUserName(); - /// Return the path to the program's executable. ARCH_API std::string ArchGetExecutablePath(); diff --git a/pxr/base/lib/arch/testenv/testSystemInfo.cpp b/pxr/base/lib/arch/testenv/testSystemInfo.cpp index 54642bd064..40bc3253a9 100644 --- a/pxr/base/lib/arch/testenv/testSystemInfo.cpp +++ b/pxr/base/lib/arch/testenv/testSystemInfo.cpp @@ -33,14 +33,7 @@ using std::string; //most of these tests are just for code coverage int main(int argc, char const* argv[]) { - assert(! ArchGetUserName().empty()); - assert(ArchGetHomeDirectory("~nosuchuser").empty()); - assert(ArchGetHomeDirectory().find(ArchGetUserName(), 0) != string::npos); - assert(ArchGetHomeDirectory( - ArchGetUserName()).find(ArchGetUserName(), 0) != string::npos); - assert(ArchGetExecutablePath().find("testArch", 0) != string::npos); - return 0; } From e1463b19d418bb57d916a6d4a895b550559206d6 Mon Sep 17 00:00:00 2001 From: George ElKoura Date: Tue, 25 Oct 2016 19:49:54 -0700 Subject: [PATCH 315/380] Remove setting of RPATH on Windows. It was giving folks problems and shouldn't be required anyway. --- cmake/macros/Public.cmake | 1 - 1 file changed, 1 deletion(-) diff --git a/cmake/macros/Public.cmake b/cmake/macros/Public.cmake index afb4e87243..1867bbfbf5 100644 --- a/cmake/macros/Public.cmake +++ b/cmake/macros/Public.cmake @@ -242,7 +242,6 @@ function(pxr_shared_library LIBRARY_NAME) PREFIX "" SUFFIX ".pyd" FOLDER "${PXR_PREFIX}/_python" - INSTALL_RPATH ${rpath} LINK_FLAGS_RELEASE "/SUBSYSTEM:WINDOWS" ) else() From 2f27c6e3859dcb1efb99dae6159e3826d9f7a939 Mon Sep 17 00:00:00 2001 From: George ElKoura Date: Tue, 25 Oct 2016 21:23:09 -0700 Subject: [PATCH 316/380] Add a hacky way to inject more include directories for garch. --- pxr/imaging/lib/garch/CMakeLists.txt | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/pxr/imaging/lib/garch/CMakeLists.txt b/pxr/imaging/lib/garch/CMakeLists.txt index c4051c531c..3d0d0a9a5e 100644 --- a/pxr/imaging/lib/garch/CMakeLists.txt +++ b/pxr/imaging/lib/garch/CMakeLists.txt @@ -29,9 +29,7 @@ pxr_shared_library(garch INCLUDE_DIRS ${Boost_INCLUDE_DIRS} - - INCLUDE_DIRS - ${Boost_INCLUDE_DIRS} + ${HACK_GL_EXTRA_INCLUDE_DIR} PUBLIC_CLASSES glPlatformContext From b8a5ec2c7a5382444b3b1aa127b31acee92ca43c Mon Sep 17 00:00:00 2001 From: George ElKoura Date: Wed, 26 Oct 2016 08:55:06 -0700 Subject: [PATCH 317/380] Remove vestiges of Qt C++ requirements which have been removed. --- cmake/defaults/Packages.cmake | 13 ++----------- pxr/usdImaging/lib/usdviewq/CMakeLists.txt | 5 ----- 2 files changed, 2 insertions(+), 16 deletions(-) diff --git a/cmake/defaults/Packages.cmake b/cmake/defaults/Packages.cmake index e2a1fb7194..b768573385 100644 --- a/cmake/defaults/Packages.cmake +++ b/cmake/defaults/Packages.cmake @@ -101,17 +101,8 @@ if (PXR_BUILD_IMAGING) # --X11 find_package(X11) endif() - # --Qt - #find_package(Qt4) - #if (QT4_FOUND) - find_package(Qt5Core) - find_package(Qt5Gui) - find_package(Qt5OpenGL) - find_package(Qt5Xml) - find_package(Qt5Network) - if (Qt5Core_FOUND) - find_package(PySide REQUIRED) - endif() + # --PySide + find_package(PySide) # --Zlib find_package(ZLIB REQUIRED) endif() diff --git a/pxr/usdImaging/lib/usdviewq/CMakeLists.txt b/pxr/usdImaging/lib/usdviewq/CMakeLists.txt index 92304d2d9f..34036ccb18 100644 --- a/pxr/usdImaging/lib/usdviewq/CMakeLists.txt +++ b/pxr/usdImaging/lib/usdviewq/CMakeLists.txt @@ -1,11 +1,6 @@ set(PXR_PREFIX pxr/usdImaging) set(PXR_PACKAGE usdviewq) -if (NOT Qt5Core_FOUND) - message(WARNING "Not building ${PXR_PACKAGE} because of missing dependency: Qt4") - return() -endif() - if (NOT PYSIDE_FOUND) message(WARNING "Not building ${PXR_PACKAGE} because of missing dependency: PySide") return() From 22df217bf42349d84acd6600fb71e60f74f57923 Mon Sep 17 00:00:00 2001 From: screenblaster Date: Wed, 26 Oct 2016 10:27:26 -0700 Subject: [PATCH 318/380] Add user controled prefixing of shared library names. Controled by cmake variable PXR_LIB_PREFIX By default shared libraries will have the prefix 'lib' (NOTE: this does not apply to made PYTHON libraries) To change the prefix to a custom prefix or to remove it use the cmake variable PXR_LIB_PREFIX like this PXR_LIB_PREFIX:STRING="prefix_string_" If you wish to remove the prefix from the libraries set the variable with empty string like this PXR_LIB_PREFIX:STRING="" (Internal change: 1667206) --- BUILDING.md | 6 ++++++ cmake/defaults/Options.cmake | 6 +++++- cmake/macros/Public.cmake | 3 +++ 3 files changed, 14 insertions(+), 1 deletion(-) diff --git a/BUILDING.md b/BUILDING.md index 6fade1852a..aaa600a581 100644 --- a/BUILDING.md +++ b/BUILDING.md @@ -87,6 +87,12 @@ properly based on the install location of the build. However, if you plan to rel the build, you must inform the build by setting the cmake variable ```PXR_INSTALL_LOCATION``` to the intended final directory where these files will be located. This variable may be a ':'-delimited list of paths. +##### Shared library prefix + +By default shared libraries will have the prefix 'lib' (NOTE: this does not apply to made PYTHON libraries) To change the prefix +to a custom prefix or to remove it use the cmake variable ```PXR_LIB_PREFIX``` like this ```PXR_LIB_PREFIX:STRING="prefix_string_"```` +If you wish to remove the prefix from the libraries set the variable with empty string like this ```PXR_LIB_PREFIX:STRING=""```` (remember to prefix cmake variables with ```-D```) + ## USD Developer Options ##### ASCII Parser Editing/Validation diff --git a/cmake/defaults/Options.cmake b/cmake/defaults/Options.cmake index d97f2d7593..5670685082 100644 --- a/cmake/defaults/Options.cmake +++ b/cmake/defaults/Options.cmake @@ -41,7 +41,11 @@ set(PXR_ALL_LIBS "" INTERNAL "Aggregation of all built libraries." ) - +set(PXR_LIB_PREFIX "lib" + CACHE + STRING + "Prefix for build library name" +) if (${PXR_BUILD_USD_IMAGING} AND NOT ${PXR_BUILD_IMAGING}) message(STATUS "PXR_BUILD_IMAGING=OFF implies PXR_BUILD_USD_IMAGING=OFF" diff --git a/cmake/macros/Public.cmake b/cmake/macros/Public.cmake index 569c7b2bdf..88cbb524a7 100644 --- a/cmake/macros/Public.cmake +++ b/cmake/macros/Public.cmake @@ -136,6 +136,9 @@ function(pxr_shared_library LIBRARY_NAME) ${sl_PRIVATE_HEADERS} ${${LIBRARY_NAME}_PRIVATE_HEADERS} ) + # Set prefix here after the library add; ahead of python so that python lib prefix is reset to correct + set_target_properties(${LIBRARY_NAME} PROPERTIES PREFIX "${PXR_LIB_PREFIX}") + if(sl_PYTHON_FILES) _install_python(${LIBRARY_NAME} FILES ${sl_PYTHON_FILES} From bff85bcd138b4417fb03593f079d8c66378e67b3 Mon Sep 17 00:00:00 2001 From: superfunc Date: Wed, 26 Oct 2016 10:28:57 -0700 Subject: [PATCH 319/380] [Pxr] Doc cleanup. (Internal change: 1667216) --- BUILDING.md | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/BUILDING.md b/BUILDING.md index aaa600a581..b48912194e 100644 --- a/BUILDING.md +++ b/BUILDING.md @@ -89,9 +89,20 @@ directory where these files will be located. This variable may be a ':'-delimite ##### Shared library prefix -By default shared libraries will have the prefix 'lib' (NOTE: this does not apply to made PYTHON libraries) To change the prefix -to a custom prefix or to remove it use the cmake variable ```PXR_LIB_PREFIX``` like this ```PXR_LIB_PREFIX:STRING="prefix_string_"```` -If you wish to remove the prefix from the libraries set the variable with empty string like this ```PXR_LIB_PREFIX:STRING=""```` (remember to prefix cmake variables with ```-D```) +By default shared libraries will have the prefix 'lib'. This means, for a given +component such as [usdGeom](pxr/usd/lib/usdGeom), the build will generate a corresponding +libusdGeom object (libusdGeom.so on Linux, libusdGeom.dll on Windows +and libusdGeom.dylib on Mac). You can change the prefix(or remove it) through +```PXR_LIB_PREFIX```. For example, + +``` +-DPXR_LIB_PREFIX=pxr +``` + +Will generate pxrusdGeom.so on Linux, pxrusdGeom.dll on Windows and +pxrusdGeom.dylib on Mac for the usdGeom component. + +> Note: This prefix does not apply to shared objects used for Python bindings. ## USD Developer Options From 9102d9d61c2855b1a1c6624c3e494640d9c06425 Mon Sep 17 00:00:00 2001 From: superfunc Date: Wed, 26 Oct 2016 10:29:01 -0700 Subject: [PATCH 320/380] [Pxr] Typo. (Internal change: 1667224) --- BUILDING.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/BUILDING.md b/BUILDING.md index b48912194e..3b3fbf13a2 100644 --- a/BUILDING.md +++ b/BUILDING.md @@ -92,7 +92,7 @@ directory where these files will be located. This variable may be a ':'-delimite By default shared libraries will have the prefix 'lib'. This means, for a given component such as [usdGeom](pxr/usd/lib/usdGeom), the build will generate a corresponding libusdGeom object (libusdGeom.so on Linux, libusdGeom.dll on Windows -and libusdGeom.dylib on Mac). You can change the prefix(or remove it) through +and libusdGeom.dylib on Mac). You can change the prefix (or remove it) through ```PXR_LIB_PREFIX```. For example, ``` From caab0c7e8ffb7bb18d1caf57fff9de4f9ba4963c Mon Sep 17 00:00:00 2001 From: sunyab Date: Wed, 26 Oct 2016 10:29:08 -0700 Subject: [PATCH 321/380] Fix GetLoadSet when loaded prim no longer exists UsdStage::GetLoadSet asserted that all prims in its load set will always exist on the stage. This was incorrect; it's actually very easy to get into such a state -- for example, by deactivating the ancestor of a loaded prim. This change removes the assertion and will simply return the previously-loaded path in this case. This accurately reflects what payloads are loaded in the underlying PcpCache. This restores the behavior of GetLoadSet in this case to what it was prior to the introduction of the TF_VERIFY. This behavior is confusing, though. A good follow-up might be to unload prims whenever we deactivate them, but that's a larger change. (Internal change: 1667228) --- pxr/usd/lib/usd/stage.cpp | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/pxr/usd/lib/usd/stage.cpp b/pxr/usd/lib/usd/stage.cpp index d5f829325e..1b2c8730d9 100644 --- a/pxr/usd/lib/usd/stage.cpp +++ b/pxr/usd/lib/usd/stage.cpp @@ -1825,9 +1825,23 @@ UsdStage::GetLoadSet() { SdfPathSet loadSet; for (const auto& primIndexPath : _cache->GetIncludedPayloads()) { - const SdfPath primPath = _GetPrimPathUsingPrimIndexAtPath(primIndexPath); - if (TF_VERIFY(not primPath.IsEmpty(), "Unable to get prim path using " - "prim index at path <%s>.", primIndexPath.GetText())) { + // Get the path of the Usd prim using this prim index path. + // This ensures we return the appropriate path if this prim index + // is being used by a prim within a master. + // + // If there is no Usd prim using this prim index, we return the + // prim index path anyway. This could happen if the ancestor of + // a previously-loaded prim is deactivated, for instance. + // Including this path in the returned set reflects what's loaded + // in the underlying PcpCache and ensures users can still unload + // the payloads for those prims by calling + // LoadAndUnload([], GetLoadSet()). + const SdfPath primPath = + _GetPrimPathUsingPrimIndexAtPath(primIndexPath); + if (primPath.IsEmpty()) { + loadSet.insert(primIndexPath); + } + else { loadSet.insert(primPath); } } From c8f5eed1cd1f05897ce18a096c0ac5ae73d1985f Mon Sep 17 00:00:00 2001 From: blevin Date: Wed, 26 Oct 2016 10:29:16 -0700 Subject: [PATCH 322/380] Use TfSimpleRefBase for types that are not wrapped to python. (Internal change: 1667281) --- pxr/usd/lib/pcp/primIndex_Graph.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pxr/usd/lib/pcp/primIndex_Graph.h b/pxr/usd/lib/pcp/primIndex_Graph.h index b3cc621c75..df41c6983a 100644 --- a/pxr/usd/lib/pcp/primIndex_Graph.h +++ b/pxr/usd/lib/pcp/primIndex_Graph.h @@ -51,7 +51,7 @@ TF_DECLARE_WEAK_AND_REF_PTRS(PcpPrimIndex_Graph); /// opinions in the prim index. /// class PcpPrimIndex_Graph - : public TfRefBase + : public TfSimpleRefBase , public TfWeakBase { public: From 264606358dd38d51b7eb70d47b1555029f35adf1 Mon Sep 17 00:00:00 2001 From: blevin Date: Wed, 26 Oct 2016 10:29:19 -0700 Subject: [PATCH 323/380] Remove unused PcpPrimIndex::Validate(). (Internal change: 1667284) --- pxr/usd/lib/pcp/primIndex.cpp | 29 ----------------------------- pxr/usd/lib/pcp/primIndex.h | 3 --- pxr/usd/lib/pcp/wrapPrimIndex.cpp | 1 - 3 files changed, 33 deletions(-) diff --git a/pxr/usd/lib/pcp/primIndex.cpp b/pxr/usd/lib/pcp/primIndex.cpp index feca32e24d..b0b0ea309c 100644 --- a/pxr/usd/lib/pcp/primIndex.cpp +++ b/pxr/usd/lib/pcp/primIndex.cpp @@ -158,35 +158,6 @@ PcpPrimIndex::PrintStatistics() const Pcp_PrintPrimIndexStatistics(*this); } -void PcpPrimIndex::Validate() -{ - // TODO validate graph structure: - // - children are correctly sorted - // - valid map functions - // - valid site paths - // - valid layer stacks - // - 'payload' flag only used on root nodes - // - small integer values within range (may need to do this as we go) - // - validate prim stack / node stack are consistent - - // - validate consistent variant selections throughout the index - // - // This code taken from the old _GatherVariantSelections(): - // XXX: - // This verify asserts that variant selections should be - // consistent throughout the prim index. Unfortunately, to match - // Csd's behavior, this is not always the case. We'd like it to - // be someday, though. - // - // TF_VERIFY(result->find(vsel.first)->second == vsel.second, - // "Found conflicting variant selections: " - // "{%s=%s} vs {%s=%s}", - // vsel.first.c_str(), - // result->find(vsel.first)->second.c_str(), - // vsel.first.c_str(), - // vsel.second.c_str()); -} - std::string PcpPrimIndex::DumpToString( bool includeInheritOriginInfo, bool includeMaps) const diff --git a/pxr/usd/lib/pcp/primIndex.h b/pxr/usd/lib/pcp/primIndex.h index 163702d9c7..cf77183cc9 100644 --- a/pxr/usd/lib/pcp/primIndex.h +++ b/pxr/usd/lib/pcp/primIndex.h @@ -201,9 +201,6 @@ class PcpPrimIndex bool includeInheritOriginInfo = true, bool includeMaps = false) const; - /// Verify that this is index is well-formed. - void Validate(); - /// @} diff --git a/pxr/usd/lib/pcp/wrapPrimIndex.cpp b/pxr/usd/lib/pcp/wrapPrimIndex.cpp index 1abd54f9dc..a1d129333e 100644 --- a/pxr/usd/lib/pcp/wrapPrimIndex.cpp +++ b/pxr/usd/lib/pcp/wrapPrimIndex.cpp @@ -88,7 +88,6 @@ void wrapPrimIndex() &This::GetSelectionAppliedForVariantSet) .def("PrintStatistics", &This::PrintStatistics) - .def("Validate", &This::Validate) .def("DumpToString", &This::DumpToString, (args("includeInheritOriginInfo") = true, args("includeMaps") = true)) From ce77e5dd20a8cc80523e7bdaca59ce7b5ec134ba Mon Sep 17 00:00:00 2001 From: blevin Date: Wed, 26 Oct 2016 10:29:25 -0700 Subject: [PATCH 324/380] Fix build (Internal change: 1667308) --- pxr/usd/lib/pcp/primIndex.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/pxr/usd/lib/pcp/primIndex.cpp b/pxr/usd/lib/pcp/primIndex.cpp index b0b0ea309c..4bb3f15fb3 100644 --- a/pxr/usd/lib/pcp/primIndex.cpp +++ b/pxr/usd/lib/pcp/primIndex.cpp @@ -4128,9 +4128,6 @@ PcpComputePrimIndex( } } } - - // Validate the result. - outputs->primIndex.Validate(); } //////////////////////////////////////////////////////////////////////// From 24b5a02c5105077b49ed4ae5a429de80ebb22bf1 Mon Sep 17 00:00:00 2001 From: mattyjams Date: Wed, 26 Oct 2016 10:29:35 -0700 Subject: [PATCH 325/380] widen tolerance from 1e-9 to 1e-7 when checking whether Maya transform attributes are identity In particular, we don't want to be authoring shear XformOps unnecessarily. (Internal change: 1667366) --- third_party/maya/lib/usdMaya/MayaTransformWriter.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/third_party/maya/lib/usdMaya/MayaTransformWriter.cpp b/third_party/maya/lib/usdMaya/MayaTransformWriter.cpp index 681b89d041..33f7d00f79 100644 --- a/third_party/maya/lib/usdMaya/MayaTransformWriter.cpp +++ b/third_party/maya/lib/usdMaya/MayaTransformWriter.cpp @@ -193,7 +193,7 @@ _GatherAnimChannel( chan.sampleType[i] = ANIMATED; validComponents++; } - else if (not GfIsClose(chan.defValue[i], nullValue[i], 1e-9)) { + else if (not GfIsClose(chan.defValue[i], nullValue[i], 1e-7)) { chan.sampleType[i] = STATIC; validComponents++; } From c38d99ff4156485ff9d272050d8d44ace2ee80ca Mon Sep 17 00:00:00 2001 From: blevin Date: Wed, 26 Oct 2016 10:29:42 -0700 Subject: [PATCH 326/380] Use Identity for PcpMapFunction repr. (Internal change: 1667506) --- pxr/usd/lib/pcp/wrapMapFunction.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/pxr/usd/lib/pcp/wrapMapFunction.cpp b/pxr/usd/lib/pcp/wrapMapFunction.cpp index 4535ea8659..f6b2e5614c 100644 --- a/pxr/usd/lib/pcp/wrapMapFunction.cpp +++ b/pxr/usd/lib/pcp/wrapMapFunction.cpp @@ -36,6 +36,9 @@ using std::string; static string _Repr(const PcpMapFunction &f) { + if (f.IsIdentity()) { + return "Pcp.MapFunction.Identity()"; + } string s = "Pcp.MapFunction("; if (not f.IsNull()) { const boost::python::dict sourceToTargetMap = From 81713a6d1f6da5210c78d65a6dc7b231e3d03b5e Mon Sep 17 00:00:00 2001 From: blevin Date: Wed, 26 Oct 2016 10:30:03 -0700 Subject: [PATCH 327/380] Pcp: Dependency system redesign. Replace Spec-based tracking. As Pcp indexes scene description it discovers composition arcs representing dependencies ("deps") on other scene description. Pcp must track deps to manage data lifetime, to process later changes to scene data, to invalidate caches, and to support features that must reason about the dependency graph structure, such as namespace editing. Each dependency points to a "site" representing all the SdfSpecs ("specs") that reside at a path in a layer stack. Historically our old composition system tracked deps in terms of spec stacks, not sites. We retained that in Pcp, while suspecting that tracking specs is a mismatch for the task, because of the principle that composition arcs connect sites, not specs, and the specs can always be derived from sites. Further experience confirmed there were some issues. The usd project found that spec tracking was too expensive in memory terms, so it turns them off entirely, but at the cost of not supporting all dependency features correctly. The other issue is complexity: there are cases that spec deps are insufficient to handle, so Pcp_Dependencies was actually a hybrid that also tracked sites, and would use one representation or the other in various cases. This made the code tricky to follow, and required additional concepts to emerge in the API like "fallback ancestor". The new system tracks the sites used by every prim index, and stores a reverse mapping from sites back to index paths. details * PcpDependencyType is now a full-fledged categorization of dependency types. PcpClassifyNodeDependency() can compute the dep type of a given node. * Rather than maintaining a self-contained external bimap, Pcp_Dependencies now takes advantage of lock-step update with PcpPrimIndex entries in PcpCache so it can store only the inverse map and use indexes for the forward map. This cuts the runtime memory usage in half. * The above change means we can simplify the update process and no longer need an async "flush" pass. * PcpPrimIndex no longer builds a side list of deps as it goes. Instead, we rely on the node graph to fully represent the actual dependency structure. To support this, we now introduce variant nodes for variant selections even when the variant specs at the target do not yet exist. This lets us track the dependency purely as a node, and is consistent with other kinds of arcs. To handle "spooky dependencies" we now propagate implied relocate nodes up to the root -- formally representing what was previously implicit structure, and allowing "spooky" cases to be handled by the normal code paths. This obviates the "shouldContributeDependencies" node flag. "fallbackAncestor" is also no longer a necessary API concept, because we always have ancestral site deps to use. * PcpLayerStackSite now holds a ref rather than weakptr to its layer stack. This is consistent with its purpose in representing a dependency on a layer stack (not a weak reference!); allows us to avoid having a duplicate side-structure for tracking the actual references already described by the sites; and shrinks the size of a pcp graph node (48 B -> 40 B). (It doesn't make any difference to the # of atomic ref count ops we do since weakptrs refcount their remnant; now we refcount the layerstack instead.) results * less code, fixes correctness bugs * less runtime memory -- ~5-7x less Pcp dependency memory; one production set usd goes from 933MB to 883MB (total) * depenency tracking overhead now scales with dependency arc complexity of the scene, not the prim count bugs: 135974, 137333, 96529 (Internal change: 1667509) --- pxr/usd/lib/pcp/cache.cpp | 1332 +++++++++-------------- pxr/usd/lib/pcp/cache.h | 149 +-- pxr/usd/lib/pcp/changes.cpp | 422 +++----- pxr/usd/lib/pcp/changes.h | 4 +- pxr/usd/lib/pcp/debugCodes.cpp | 2 + pxr/usd/lib/pcp/debugCodes.h | 3 +- pxr/usd/lib/pcp/dependencies.cpp | 1618 +++------------------------- pxr/usd/lib/pcp/dependencies.h | 285 ++--- pxr/usd/lib/pcp/dependency.cpp | 142 +++ pxr/usd/lib/pcp/dependency.h | 131 +++ pxr/usd/lib/pcp/diagnostic.cpp | 35 +- pxr/usd/lib/pcp/layerStack.cpp | 11 + pxr/usd/lib/pcp/layerStack.h | 1 + pxr/usd/lib/pcp/module.cpp | 1 + pxr/usd/lib/pcp/node.cpp | 5 +- pxr/usd/lib/pcp/node.h | 7 +- pxr/usd/lib/pcp/primIndex.cpp | 432 ++++---- pxr/usd/lib/pcp/primIndex.h | 69 +- pxr/usd/lib/pcp/primIndex_Graph.h | 8 +- pxr/usd/lib/pcp/site.cpp | 5 +- pxr/usd/lib/pcp/site.h | 6 +- pxr/usd/lib/pcp/statistics.cpp | 10 +- pxr/usd/lib/pcp/types.cpp | 3 - pxr/usd/lib/pcp/types.h | 9 - pxr/usd/lib/pcp/wrapCache.cpp | 71 +- pxr/usd/lib/pcp/wrapDependency.cpp | 65 ++ pxr/usd/lib/pcp/wrapNode.cpp | 2 - pxr/usd/lib/pcp/wrapTypes.cpp | 1 - pxr/usd/lib/usd/stage.cpp | 40 +- 29 files changed, 1628 insertions(+), 3241 deletions(-) create mode 100644 pxr/usd/lib/pcp/dependency.cpp create mode 100644 pxr/usd/lib/pcp/dependency.h create mode 100644 pxr/usd/lib/pcp/wrapDependency.cpp diff --git a/pxr/usd/lib/pcp/cache.cpp b/pxr/usd/lib/pcp/cache.cpp index 3819a7e084..56fcc50f5d 100644 --- a/pxr/usd/lib/pcp/cache.cpp +++ b/pxr/usd/lib/pcp/cache.cpp @@ -25,6 +25,8 @@ #include "pxr/usd/pcp/arc.h" #include "pxr/usd/pcp/changes.h" +#include "pxr/usd/pcp/diagnostic.h" +#include "pxr/usd/pcp/debugCodes.h" #include "pxr/usd/pcp/dependencies.h" #include "pxr/usd/pcp/layerStack.h" #include "pxr/usd/pcp/layerStackIdentifier.h" @@ -75,9 +77,11 @@ TF_DEFINE_ENV_SETTING( TF_REGISTRY_FUNCTION(TfEnum) { - TF_ADD_ENUM_NAME(PcpCache::UsingSiteOnly); - TF_ADD_ENUM_NAME(PcpCache::UsingSiteAndDescendants); - TF_ADD_ENUM_NAME(PcpCache::UsingSiteAndDescendantPrims); + TF_ADD_ENUM_NAME(PcpCache::NamespaceEditType::NamespaceEditPath); + TF_ADD_ENUM_NAME(PcpCache::NamespaceEditType::NamespaceEditInherit); + TF_ADD_ENUM_NAME(PcpCache::NamespaceEditType::NamespaceEditReference); + TF_ADD_ENUM_NAME(PcpCache::NamespaceEditType::NamespaceEditPayload); + TF_ADD_ENUM_NAME(PcpCache::NamespaceEditType::NamespaceEditRelocate); } // Helper for applying changes immediately if the client hasn't asked that @@ -125,7 +129,7 @@ PcpCache::PcpCache( _targetSchema(targetSchema), _payloadDecorator(payloadDecorator), _layerStackCache(Pcp_LayerStackRegistry::New(_targetSchema, _usd)), - _dependencies(new Pcp_Dependencies()) + _primDependencies(new Pcp_Dependencies()) { // Do nothing } @@ -149,7 +153,6 @@ PcpCache::~PcpCache() // a bit of time. WorkArenaDispatcher wd; - wd.Run([this]() { _dependencies.reset(); }); wd.Run([this]() { _rootLayer.Reset(); }); wd.Run([this]() { _sessionLayer.Reset(); }); wd.Run([this]() { _payloadDecorator.Reset(); }); @@ -158,8 +161,16 @@ PcpCache::~PcpCache() wd.Run([this]() { _primIndexCache.ClearInParallel(); }); wd.Run([this]() { TfReset(_propertyIndexCache); }); - // Wait, since _layerStackCache cannot be destroyed until _dependencies is - // cleaned up. + // Wait, since _primDependencies cannot be destroyed concurrently + // with the prim indexes, since they both hold references to + // layer stacks and the layer stack registry is not currently + // prepared to handle concurrent expiry of layer stacks. + wd.Wait(); + + wd.Run([this]() { _primDependencies.reset(); }); + + // Wait, since _layerStackCache cannot be destroyed until + // _primDependencies is cleaned up. wd.Wait(); wd.Run([this]() { _layerStackCache.Reset(); }); @@ -476,7 +487,7 @@ PcpCache::FindPropertyIndex(const SdfPath & path) const SdfLayerHandleSet PcpCache::GetUsedLayers() const { - SdfLayerHandleSet rval = _dependencies->GetUsedLayers(); + SdfLayerHandleSet rval = _primDependencies->GetUsedLayers(); // Dependencies don't include the local layer stack, so manually add those // layers here. @@ -490,7 +501,7 @@ PcpCache::GetUsedLayers() const SdfLayerHandleSet PcpCache::GetUsedRootLayers() const { - SdfLayerHandleSet rval = _dependencies->GetUsedRootLayers(); + SdfLayerHandleSet rval = _primDependencies->GetUsedRootLayers(); // Dependencies don't include the local layer stack, so manually add the // local root layer here. @@ -498,665 +509,283 @@ PcpCache::GetUsedRootLayers() const return rval; } -SdfPathVector -PcpCache::_GetPathsUsingPcpSite( - const PcpLayerStackPtr& layerStack, - const SdfPath& path, - unsigned int dependencyType, - PcpNodeRefVector* sourceNodes, - bool recursive, - bool spooky) const -{ - TRACE_FUNCTION(); - - if (layerStack->_registry != _layerStackCache) { - TF_CODING_ERROR("PcpLayerStack does not belong to this PcpCache"); - return SdfPathVector(); - } - - const SdfPathVector results = - _dependencies->Get(layerStack, path, dependencyType, recursive, spooky); - - // If asked, we need to do some extra processing to figure out the nodes - // that introduced the dependencies on the given Pcp site. In the simple - // case, we would just need to grab the prim index for each result and - // find the node that uses that site. However, this doesn't always work. - // We may not have actually computed the prim index for each result path, - // or we the node that actually uses the exact Pcp site may have been - // culled out. Both cases happen when dealing with ancestral dependencies. - // - // To produce the desired nodes, this code walks up namespace until it - // finds the node that introduced the dependency. This means that the - // nodes that are returned are not always from the prim index for each path - // returned. However, these nodes are still valid and usable for path - // translation. - if (sourceNodes) { - sourceNodes->clear(); - sourceNodes->reserve(results.size()); - - for (const auto& pcpSitePath : results) { - SdfPath primUsingSite = pcpSitePath; - PcpLayerStackSite usedSite(layerStack, path); - PcpNodeRef nodeUsingSite; - - while (primUsingSite.IsAbsoluteRootOrPrimPath()) { - if (const PcpPrimIndex* primIndex = - _GetPrimIndex(primUsingSite)) { - - TF_FOR_ALL(it, primIndex->GetNodeRange()) { - const PcpLayerStackSite& nodeSite = it->GetSite(); - if (nodeSite.layerStack == usedSite.layerStack and - nodeSite.path.HasPrefix(usedSite.path)) { - nodeUsingSite = *it; - goto found; - } - } - } - - if (not usedSite.path.IsPrimVariantSelectionPath()) { - primUsingSite = primUsingSite.GetParentPath(); - } - usedSite.path = usedSite.path.GetParentPath(); +PcpDependencyVector +PcpCache::FindDependentPaths( + const SdfLayerHandle& layer, + const SdfPath& sitePath, + PcpDependencyFlags depMask, + bool recurseOnSite, + bool recurseOnIndex, + bool filterForExistingCachesOnly + ) const +{ + PcpDependencyVector result; + for (const auto& layerStack: FindAllLayerStacksUsingLayer(layer)) { + PcpDependencyVector deps = FindDependentPaths( + layerStack, sitePath, depMask, recurseOnSite, recurseOnIndex, + filterForExistingCachesOnly); + for (PcpDependency dep: deps) { + SdfLayerOffset offset = dep.mapFunc.GetTimeOffset(); + // Fold in any sublayer offset. + if (const SdfLayerOffset *sublayer_offset = + layerStack->GetLayerOffsetForLayer(layer)) { + offset = offset * *sublayer_offset; } - - found: - TF_VERIFY( - nodeUsingSite, - "Unable to find node that introduced dependency on Pcp site %s" - "for prim <%s>", - TfStringify(PcpLayerStackSite(layerStack, path)).c_str(), - pcpSitePath.GetText()); - - sourceNodes->push_back(nodeUsingSite); + dep.mapFunc = PcpMapFunction::Create( + dep.mapFunc.GetSourceToTargetMap(), offset); + result.push_back(dep); } } - - TF_VERIFY(not sourceNodes or results.size() == sourceNodes->size(), - "%zu sourceNodes != %zu results -- they must correspond", - sourceNodes->size(), results.size()); - return results; -} - -bool -PcpCache::_UsesLayer(const SdfLayerHandle& layer) const -{ - const PcpLayerStackPtrVector& layerStacks = - FindAllLayerStacksUsingLayer(layer); - - for (const auto& layerStack : layerStacks) { - // PcpCache doesn't record dependencies on its root layer stack, - // so we have to check that explicitly. - if (layerStack == _layerStack or - _dependencies->UsesLayerStack(layerStack)) { - return true; - } - } - - return false; + return result; } -static bool -_IsAbsoluteRootOrPrimOrVariantPath(const SdfPath& path) +PcpDependencyVector +PcpCache::FindDependentPaths( + const PcpLayerStackPtr& siteLayerStack, + const SdfPath& sitePath, + PcpDependencyFlags depMask, + bool recurseOnSite, + bool recurseOnIndex, + bool filterForExistingCachesOnly + ) const { - return (path == SdfPath::AbsoluteRootPath() or - path.IsPrimOrPrimVariantSelectionPath()); -} + TRACE_FUNCTION(); -static SdfPath -_GetAbsoluteRootOrPrimOrVariantPath(const SdfPath& path) -{ - return path == SdfPath::AbsoluteRootPath() ? - path : path.GetPrimOrPrimVariantSelectionPath(); -} + PcpDependencyVector deps; -SdfPathVector -PcpCache::_GetPathsUsingPrimFromDependencies( - const SdfLayerHandle& layer, - const SdfPath& path, - PcpNodeRefVector* sourceNodes, - UsingSite usingSite, - bool spookyDependencies) const -{ - // PcpCache only stores dependencies for prims and variants - if (not TF_VERIFY( - _IsAbsoluteRootOrPrimOrVariantPath(path), - "Expected prim path, got: <%s>", path.GetText())) { - return SdfPathVector(); - } - - // Map UsingSite to flags. - static const bool recursive[] = { false, true, true }; - static const bool primsOnly[] = { false, false, true }; - - // Get the dependencies. - SdfPathVector result = - _dependencies->Get(layer, path, - recursive[usingSite], - primsOnly[usingSite] or spookyDependencies, - spookyDependencies, - sourceNodes); - - // Special case for the pseudo-root. // - // XXX: It seems like this special case shouldn't be necessary -- shouldn't - // we be capturing spec dependencies for the pseudo-root? Removing - // this causes at least one test (testCsdLayering6) to fail, though. - if (path == SdfPath::AbsoluteRootPath()) { - if (_layerStack and _layerStack->HasLayer(layer)) { - switch (usingSite) { - case UsingSiteOnly: - result.push_back(path); - if (sourceNodes) { - const PcpPrimIndex* rootIndex = _GetPrimIndex(path); - if (TF_VERIFY(rootIndex)) { - sourceNodes->push_back(rootIndex->GetRootNode()); + // Validate arguments. + // + if (!(depMask & (PcpDependencyTypeVirtual|PcpDependencyTypeNonVirtual))) { + TF_CODING_ERROR("depMask must include at least one of " + "{PcpDependencyTypeVirtual, " + "PcpDependencyTypeNonVirtual}"); + return deps; + } + if (!(depMask & (PcpDependencyTypeRoot | PcpDependencyTypeDirect | + PcpDependencyTypeAncestral))) { + TF_CODING_ERROR("depMask must include at least one of " + "{PcpDependencyTypeRoot, " + "PcpDependencyTypePurelyDirect, " + "PcpDependencyTypePartlyDirect, " + "PcpDependencyTypeAncestral}"); + return deps; + } + if ((depMask & PcpDependencyTypeRoot) && + !(depMask & PcpDependencyTypeNonVirtual)) { + // Root deps are only ever non-virtual. + TF_CODING_ERROR("depMask of PcpDependencyTypeRoot requires " + "PcpDependencyTypeNonVirtual"); + return deps; + } + if (siteLayerStack->_registry != _layerStackCache) { + TF_CODING_ERROR("PcpLayerStack does not belong to this PcpCache"); + return deps; + } + + // Dependency arcs expressed in scene description connect prim + // paths, prim variant paths, and absolute paths only. Those arcs + // imply dependency structure for children, such as properties. + // To service dependency queries about those children, we must + // examine structure at the enclosing prim/root level where deps + // are expresed. Find the containing path. + const SdfPath sitePrimPath = + (sitePath == SdfPath::AbsoluteRootPath()) ? sitePath : + sitePath.GetPrimOrPrimVariantSelectionPath(); + + // Handle the root dependency. + // Sites containing variant selections are never root dependencies. + if (depMask & PcpDependencyTypeRoot && + siteLayerStack == _layerStack && + !sitePath.ContainsPrimVariantSelection()) { + deps.push_back(PcpDependency{ + sitePath, sitePath, PcpMapFunction::Identity()}); + } + + // Handle dependencies stored at this level of namespace. + // These may include ancestral and direct deps. + if (depMask & (PcpDependencyTypeDirect | PcpDependencyTypeAncestral)) { + auto visitPrimDepFn = [&](const SdfPath &depPrimIndexPath, + const SdfPath &depPrimSitePath) { + // Find the actual dependency site, which may be a property, + // etc. + const SdfPath depSitePath = + (sitePrimPath == sitePath) ? depPrimSitePath : + sitePath.ReplacePrefix(sitePrimPath, depPrimSitePath); + auto visitNodeFn = [&](const SdfPath &depPrimIndexPath, + const PcpNodeRef &node, + PcpDependencyFlags flags) { + if ((flags & depMask) == flags) { + bool valid = false; + // Now that we have found a dependency on sitePrimPath, + // use path translation to find the corresponding + // dependency on the (possibly descendent) sitePath. + SdfPath indexPath; + if (node.GetArcType() == PcpArcTypeRelocate) { + // Relocates require special handling. Because + // a relocate node's map function is always + // identity, we must do our own prefix replacement + // to step out of the relocate, then continue + // with regular path translation. + const PcpNodeRef parent = node.GetParentNode(); + indexPath = PcpTranslatePathFromNodeToRoot( + parent, + depSitePath.ReplacePrefix( node.GetPath(), + parent.GetPath() ), + &valid ); + } else { + indexPath = PcpTranslatePathFromNodeToRoot( + node, depSitePath, &valid); + } + if (valid && TF_VERIFY(!indexPath.IsEmpty())) { + deps.push_back(PcpDependency{ + indexPath, depSitePath, + node.GetMapToRoot().Evaluate() }); } } - break; - - // This function is only expected to return prims, so we don't - // need to look for descendant properties -- that will be up - // to the consumer. - case UsingSiteAndDescendants: - case UsingSiteAndDescendantPrims: - TF_FOR_ALL(it, _primIndexCache) { - const SdfPath& primPath = it->first; - const PcpPrimIndex& primIndex = it->second; - if (primIndex.GetRootNode()) { - result.push_back(primPath); - if (sourceNodes) { - sourceNodes->push_back(primIndex.GetRootNode()); + }; + Pcp_ForEachDependentNode(depPrimSitePath, siteLayerStack, + depPrimIndexPath, *this, visitNodeFn); + }; + _primDependencies->ForEachDependencyOnSite( + siteLayerStack, sitePrimPath, recurseOnSite, visitPrimDepFn); + } + + // Handle dependencies stored at ancestral levels of namespace. + if (depMask & PcpDependencyTypeAncestral) { + // Direct dependencies from ancestors are considered ancestral + // as inherited by descendents, so gather both here. + PcpDependencyFlags ancestorMask = depMask | PcpDependencyTypeDirect; + // Walk up ancestors. + for (SdfPath ancestorPrimPath = sitePrimPath.GetParentPath(); + !ancestorPrimPath.IsEmpty(); + ancestorPrimPath = ancestorPrimPath.GetParentPath()) + { + auto visitPrimDepFn = [&](const SdfPath &ancestorDepIndexPath, + const SdfPath &ancestorDepPrimSitePath) { + auto visitNodeFn = [&](const SdfPath &depPrimIndexPath, + const PcpNodeRef &node, + PcpDependencyFlags flags) { + if ((flags & ancestorMask) == flags) { + bool valid = false; + // Just as with direct dependencies, we must use + // path translation here to find sitePath. + SdfPath indexPath = + PcpTranslatePathFromNodeToRoot(node, sitePath, + &valid); + if (valid && TF_VERIFY(!indexPath.IsEmpty())) { + deps.push_back(PcpDependency{ + indexPath, sitePath /* original query site */, + node.GetMapToRoot().Evaluate() }); } } + }; + Pcp_ForEachDependentNode(sitePath, siteLayerStack, + ancestorDepIndexPath, *this, + visitNodeFn); + }; + _primDependencies->ForEachDependencyOnSite( + siteLayerStack, ancestorPrimPath, + // We don't need to recurse since we are walking up + // namespace and will encounter everything along the way. + /* recurseOnSite */ false, + visitPrimDepFn); + } + } + + // If recursing down namespace, we may have cache entries for + // descendants that did not introduce new dependency arcs, and + // therefore were not encountered above, but which nonetheless + // represent dependent paths. Add them if requested. + if (recurseOnIndex) { + SdfPathSet seenDeps; + PcpDependencyVector expandedDeps; + for(PcpDependency &dep: deps) { + const SdfPath & indexPath = dep.indexPath; + if (seenDeps.find(indexPath) != seenDeps.end()) { + // Short circuit further expansion; expect we + // have already recursed below this path. + continue; + } + seenDeps.insert(indexPath); + expandedDeps.push_back(dep); + // Recurse on child index entries. + if (indexPath.IsAbsoluteRootOrPrimPath()) { + const auto primRange = + _primIndexCache.FindSubtreeRange(indexPath); + for (auto entryIter = primRange.first; + entryIter != primRange.second; ++entryIter) { + const SdfPath& subPath = entryIter->first; + const PcpPrimIndex& subPrimIndex = entryIter->second; + if (subPrimIndex.GetGraph() && + seenDeps.find(subPath) == seenDeps.end()) { + expandedDeps.push_back(PcpDependency{ + subPath, + subPath.ReplacePrefix(indexPath, dep.sitePath), + dep.mapFunc}); + } } - break; } - } - } - - TF_VERIFY(not sourceNodes or result.size() == sourceNodes->size(), - "%zu sourceNodes != %zu results -- they must correspond", - sourceNodes->size(), result.size()); - - return result; -} - -struct PcpCache::_PathDebugInfo -{ - std::vector descriptions; - std::vector paths; - std::vector sourceNodes; -}; - -#define PCP_PATH_DEBUG(resultPaths, resultSourceNodes, ...) \ - if (debugInfo) { \ - debugInfo->descriptions.push_back(TfStringPrintf(__VA_ARGS__)); \ - debugInfo->paths.push_back(resultPaths); \ - debugInfo->sourceNodes.push_back(resultSourceNodes); \ - } - -SdfPathVector -PcpCache::_GetPathsUsingPrim( - const SdfLayerHandle& layer, - const SdfPath& path, - PcpNodeRefVector* sourceNodes, - UsingSite usingSite, - const SdfPath& fallbackAncestor, - bool spookyDependencies, - _PathDebugInfo* debugInfo) const -{ - if (not TF_VERIFY( - _IsAbsoluteRootOrPrimOrVariantPath(path), - "Expected prim path, got: <%s>", path.GetText())) { - return SdfPathVector(); - } - - // Dummy variables to make some code below a bit shorter. - PcpNodeRefVector dummy; - const PcpNodeRefVector& resultNodes = (sourceNodes ? *sourceNodes : dummy); - - SdfPathVector result = - _GetPathsUsingPrimFromDependencies(layer, path, sourceNodes, - usingSite, spookyDependencies); - - // Found dependencies for the search path. - if (not result.empty()) { - PCP_PATH_DEBUG(result, resultNodes, "found by spec"); - } - else if (spookyDependencies) { - // Spooky dependencies can only be queried on prim paths. - TF_VERIFY(path != SdfPath::AbsoluteRootPath()); - TF_VERIFY(fallbackAncestor.IsEmpty()); - - // Spooky dependencies cannot be queried recursively - // (because they are due to namespace relocations). - static const bool recursive = true; - - const PcpLayerStackPtrVector& layerStacks = - FindAllLayerStacksUsingLayer(layer); - for (const auto& layerStack : layerStacks) { - PcpNodeRefVector spookyNodes; - const SdfPathVector spookyPaths = - _GetPathsUsingPcpSite(layerStack, path, - PcpDirect | PcpAncestral, - sourceNodes ? &spookyNodes : NULL, - not recursive, spookyDependencies); - if (not spookyPaths.empty()) { - result.insert( - result.end(), spookyPaths.begin(), spookyPaths.end()); - - if (sourceNodes) { - sourceNodes->insert( - sourceNodes->end(), - spookyNodes.begin(), spookyNodes.end()); + // Recurse on child property entries. + const auto propRange = + _propertyIndexCache.FindSubtreeRange(indexPath); + for (auto entryIter = propRange.first; + entryIter != propRange.second; ++entryIter) { + const SdfPath& subPath = entryIter->first; + const PcpPropertyIndex& subPropIndex = entryIter->second; + if (!subPropIndex.IsEmpty() && + seenDeps.find(subPath) == seenDeps.end()) { + expandedDeps.push_back(PcpDependency{ + subPath, + subPath.ReplacePrefix(indexPath, dep.sitePath), + dep.mapFunc}); } - - PCP_PATH_DEBUG( - spookyPaths, spookyNodes, - "found by spooky arc to site %s", - TfStringify(PcpLayerStackSite(layerStack, path)).c_str()); } } - } - // No dependencies. If no fallback and no spooky dependenceies to - // check then we're done. - else if (fallbackAncestor.IsEmpty()) { - // Do nothing - } - - // Try dependencies on the name parent prim for prim paths. - else if (path.IsPrimOrPrimVariantSelectionPath()) { - // Find dependencies on the parent. Don't check recursively because - // that would search siblings of path, which we don't want, and - // because since there is no opinion at path there can't be any - // opinions below path so there can't be any dependencies on anything - // below path. Since we recursively blow at the dependencies we find, - // we're sure to update any prim index that depends on anything below - // path. - result = _GetPathsUsingPrimFromDependencies( - layer, fallbackAncestor, sourceNodes); - - if (not result.empty()) { - for (auto& resultPath : result) { - // Strip out any variant selections from the result path, - // as each should be a Pcp site path and not a storage path. - // XXX: This probably isn't handling - // relocations in some important way. - resultPath = path - .ReplacePrefix(fallbackAncestor, resultPath) - .StripAllVariantSelections(); + std::swap(deps, expandedDeps); + } + + // Filter results against existing caches, if requested. + // Callers could do this themselves, but we provide it as a + // convenience. + if (filterForExistingCachesOnly) { + for (PcpDependencyVector::iterator i = deps.begin(); + i != deps.end(); /* increment below */) { + bool keep = false; + const SdfPath & indexPath = i->indexPath; + if (indexPath.IsAbsoluteRootOrPrimPath()) { + keep = FindPrimIndex(indexPath); + } else if (indexPath.IsPropertyPath()) { + keep = FindPropertyIndex(indexPath); } - - PCP_PATH_DEBUG(result, resultNodes, "found by ancestor spec"); - } - - // The above isn't quite enough. If we inherit from a site with no - // opinions then add a spec there, we won't yet have dependencies on - // that spec (so the initial GetPathsUsingSite() call failed) and - // our parent will not have a relevant dependency. We must use the - // Pcp site to site dependencies to find that dangling inherit. - const PcpLayerStackPtrVector& layerStacks = - FindAllLayerStacksUsingLayer(layer); - for (const auto& layerStack : layerStacks) { - PcpNodeRefVector nodes; - const SdfPathVector paths = - _GetPathsUsingPcpSite(layerStack, path, - PcpDirect | PcpAncestral, - sourceNodes ? &nodes : NULL); - - if (not paths.empty()) { - result.insert(result.end(), paths.begin(), paths.end()); - - if (sourceNodes) { - sourceNodes->insert( - sourceNodes->end(), nodes.begin(), nodes.end()); + if (keep) { + ++i; + } else { + const PcpDependencyVector::iterator iLast = --deps.end(); + if (i != iLast) { + std::swap(*i, *iLast); } - - PCP_PATH_DEBUG( - paths, nodes, - "found by arc to site %s", - TfStringify(PcpLayerStackSite(layerStack, path)).c_str()); + deps.erase(iLast); } } } - TF_VERIFY(not sourceNodes or result.size() == sourceNodes->size(), - "%zu sourceNodes != %zu results -- they must correspond", - sourceNodes->size(), result.size()); - - return result; + return deps; } -SdfPathVector -PcpCache::_GetPathsUsingSite( - const SdfLayerHandle& layer, - const SdfPath& path, - UsingSite usingSite, - SdfLayerOffsetVector* layerOffsets, - PcpNodeRefVector* sourceNodes, - const SdfPath& fallbackAncestor, - bool spookyDependencies, - std::string* debugSummary) const +bool +PcpCache::_UsesLayer(const SdfLayerHandle& layer) const { - if (not TF_VERIFY(path.IsAbsolutePath())) { - return SdfPathVector(); - } - - SdfPathVector result; - - // Instantiate a struct to hold on to debug info; this will only be used - // if we need to fill in debugSummary. - _PathDebugInfo localDebugInfo; - _PathDebugInfo* debugInfo = debugSummary ? &localDebugInfo : NULL; - - // Flag to determine whether path translation is needed after dependencies - // are retrieved. If translation is required, sourceNodes must be filled - // with the nodes from which each dependency originates. - PcpNodeRefVector localSourceNodes; - bool needsPathTranslation = (layerOffsets != NULL); - bool needsSourceNodes = (needsPathTranslation or sourceNodes); - - // If layerOffsets are requested, we will need to go through the path - // translation mechanism to compute them after we find dependencies. - if (layerOffsets) { - layerOffsets->clear(); - } - - // We can bail out immediately if there are no prim indexes that use - // the given layer. - if (not _UsesLayer(layer)) { - return result; - } - - // Pcp_Dependencies explicitly stores prim dependencies, so if we're - // given a prim path, we can just query the object directly. - if (_IsAbsoluteRootOrPrimOrVariantPath(path)) { - result = _GetPathsUsingPrim( - layer, path, - needsSourceNodes ? &localSourceNodes : NULL, - usingSite, fallbackAncestor, - spookyDependencies, debugInfo); - } - - // For everything else, we need to synthesize the answer from - // dependencies on the owning prim. We can skip this if we've been - // asked to return prims only, because at this point we know we've - // been asked for dependencies on something that isn't a prim. - else if (usingSite != UsingSiteAndDescendantPrims) { - const SdfPath owningPrimPath = - _GetAbsoluteRootOrPrimOrVariantPath(path); - const SdfPath fallbackAncestorPrimPath = - _GetAbsoluteRootOrPrimOrVariantPath(fallbackAncestor); - - // Optimization: Prim properties are easy -- if we can find - // the composed prims that depend on the property's owning prim, - // the dependent paths are just the prim paths plus the property - // name. This lets us skip some path translations. If we don't - // find any dependencies, we fall back to using the fallback ancestor - // below. - if (path.IsPrimPropertyPath()) { - result = _GetPathsUsingPrim( - layer, owningPrimPath, - needsSourceNodes ? &localSourceNodes : NULL); - - if (not result.empty()) { - // Prim-path-less references/payloads to layers that don't have - // 'defaultPrim' bill dependencies to the pseudoroot, since they - // need to be invalidated when that metadata changes, but we - // can't (and don't need to) translate property paths to those - // places, so we remove them here. We must also remove the - // corresponding elements from localSourceNodes (if - // needsSourceNodes is true). - SdfPath const &absRoot = SdfPath::AbsoluteRootPath(); - SdfPathVector::iterator i = result.begin(); - while (i != result.end()) { - if (*i == absRoot) { - i = result.erase(i); - if (needsSourceNodes) { - localSourceNodes.erase(localSourceNodes.begin() + - (i - result.begin())); - } - } else { - ++i; - } - } - - TF_FOR_ALL(it, result) { - *it = it->AppendProperty(path.GetNameToken()); - } - PCP_PATH_DEBUG( - result, localSourceNodes, "found by owning prim spec"); - } - } - - // Determine the composed prims that depend on the owning prim and, - // more importantly, the nodes in those prim indexes where those - // dependencies originated. These nodes will be used to translate - // \p path to the root namespace, which will give us the dependency - // paths we want. - if (result.empty()) { - needsPathTranslation = true; - needsSourceNodes = true; - - // Spooky dependencies can only be queried for prim paths, so - // we won't look at spooky dependencies here. - static const bool spooky = true; - // We only need dependencies on the owning prim and not any of - // its descendant prims. We're synthesizing dependencies on a - // property beneath this prim and this prim only. - static const UsingSite owningPrimSiteOnly = UsingSiteOnly; - - result = _GetPathsUsingPrim( - layer, owningPrimPath, - &localSourceNodes, owningPrimSiteOnly, fallbackAncestorPrimPath, - not spooky, debugInfo); - } + if (_layerStack->HasLayer(layer)) { + return true; } - - // Perform any necessary path translations. - if (not result.empty() and needsPathTranslation) { - TF_VERIFY(needsSourceNodes); - result = _Translate(localSourceNodes, layer, path, layerOffsets); - - // Make sure we also translate the paths we've stored in the debug - // info. If the debugSummary wasn't requested, the info should be - // empty and this will do nothing. - if (debugInfo) { - TF_VERIFY(debugInfo->paths.size() == debugInfo->sourceNodes.size()); - for (size_t i = 0; i < debugInfo->paths.size(); ++i) { - debugInfo->paths[i] = _Translate( - debugInfo->sourceNodes[i], layer, path, NULL); - } - } - } - - // If asked for descendant dependencies, we need to check for descendant - // properties beneath the dependencies we've already computed. We don't - // need to check for descendant prims, as that would have been handled - // for us earlier in _GetPathsUsingPrim. - SdfPathVector descendantDeps; - SdfLayerOffsetVector descendantOffsets; - PcpNodeRefVector descendantNodes; - if (not result.empty() and usingSite == UsingSiteAndDescendants) { - // The descendant dependencies we'll find below won't need path - // translation, as they're already in the cache's namespace, unless - // we need layer offsets. - const bool descendantsNeedPathTranslation = (layerOffsets != NULL); - const bool descendantsNeedSourceNodes = - (descendantsNeedPathTranslation or needsSourceNodes); - - for (const auto& depPath : result) { - auto range = _propertyIndexCache.FindSubtreeRange(depPath); - for (auto valueIter = range.first; valueIter != range.second; - ++valueIter) - { - const auto& v = *valueIter; - const SdfPath& propertyPath = v.first; - const PcpPropertyIndex& propertyIndex = v.second; - - // Check the property index to make sure it actually has a - // dependency on a descendant of \p path in \p layer. Note - // that specs in the property index may be invalid at this - // point if this function is being called during change - // processing. - TF_FOR_ALL(propIt, propertyIndex.GetPropertyRange()) { - const SdfPropertySpecHandle& spec = *propIt; - if (spec and - spec->GetLayer() == layer and - spec->GetPath().HasPrefix(path)) { - descendantDeps.push_back(propertyPath); - - if (descendantsNeedSourceNodes) { - descendantNodes.push_back(propIt.base().GetNode()); - } - - break; - } - - } // end for each property in property stack - } // end for each property index under depPath - } // end for each path in result - - if (not descendantDeps.empty()) { - PCP_PATH_DEBUG( - descendantDeps, descendantNodes, "found by descendant search"); - } - - if (descendantsNeedPathTranslation) { - TF_VERIFY(descendantsNeedSourceNodes); - _Translate(descendantNodes, layer, path, &descendantOffsets); - } - } - - // All of the previous code may have synthesized dependent paths that don't - // refer to any object in the cache. If \p fallbackAncestor is supplied, - // this is OK -- the consumer wants to know about all possible dependents. - // Otherwise, we need to filter out the paths that aren't in the cache. - const bool needsCacheCheck = (fallbackAncestor.IsEmpty()); - if (not result.empty() and needsCacheCheck) { - - struct _CacheChecker { - static void _RemoveResultsNotInCache( - const PcpCache* cache, - SdfPathVector* paths, - PcpNodeRefVector* sourceNodes = 0, - SdfLayerOffsetVector* layerOffsets = 0) - { - SdfPathVector existingResults; - PcpNodeRefVector existingSourceNodes; - SdfLayerOffsetVector existingOffsets; - - for (size_t i = 0; i < paths->size(); ++i) { - SdfPath depPath = (*paths)[i]; - while (not (depPath.IsAbsoluteRootOrPrimPath() or - depPath.IsPropertyPath())) { - depPath = depPath.GetParentPath(); - } - - const bool dependentObjectExistsInCache = - (depPath.IsAbsoluteRootOrPrimPath() and - cache->_GetPrimIndex(depPath)) - or - (depPath.IsPropertyPath() and - cache->_GetPropertyIndex(depPath)); - - if (dependentObjectExistsInCache) { - existingResults.push_back((*paths)[i]); - - if (layerOffsets and not layerOffsets->empty()) { - existingOffsets.push_back((*layerOffsets)[i]); - } - - if (sourceNodes and not sourceNodes->empty()) { - existingSourceNodes.push_back((*sourceNodes)[i]); - } - } - } - - paths->swap(existingResults); - if (sourceNodes) { - sourceNodes->swap(existingSourceNodes); - } - if (layerOffsets) { - layerOffsets->swap(existingOffsets); - } - } - }; - - - _CacheChecker::_RemoveResultsNotInCache( - this, &result, &localSourceNodes, layerOffsets); - - if (debugInfo) { - for (size_t i = 0; i < debugInfo->paths.size(); ++i) { - _CacheChecker::_RemoveResultsNotInCache( - this, &debugInfo->paths[i], &debugInfo->sourceNodes[i]); - } - } - } - - // Descendant property dependencies (if any) were generated by inspecting - // cache contents, so they don't need to be run through the cache existence - // check above. Just append them to the results. - result.insert(result.end(), descendantDeps.begin(), descendantDeps.end()); - localSourceNodes.insert( - localSourceNodes.end(), - descendantNodes.begin(), descendantNodes.end()); - - if (layerOffsets) { - layerOffsets->insert( - layerOffsets->end(), - descendantOffsets.begin(), descendantOffsets.end()); - } - - // If consumer wants the source nodes for the dependencies, swap them - // into place. - if (sourceNodes) { - sourceNodes->swap(localSourceNodes); - } - - // Generate the debug summary if requested. - if (debugInfo) { - std::vector entries(debugInfo->descriptions.size()); - - std::string usingSiteDescription; - switch (usingSite) { - case UsingSiteOnly: break; - case UsingSiteAndDescendants: - usingSiteDescription = " and descendants"; break; - case UsingSiteAndDescendantPrims: - usingSiteDescription = " and descendant prims"; break; - } - - for (size_t i = 0, numEntries = entries.size(); i < numEntries; ++i) { - std::vector pathEntries(debugInfo->paths[i].size()); - for (size_t j = 0; j < pathEntries.size(); ++j) { - pathEntries[j] = - TfStringPrintf(" <%s>", debugInfo->paths[i][j].GetText()); - } - - std::sort(pathEntries.begin(), pathEntries.end()); - - entries[i] = TfStringPrintf( - "Paths using site%s @%s@<%s> (%s):\n%s", - usingSiteDescription.c_str(), - layer->GetIdentifier().c_str(), path.GetText(), - debugInfo->descriptions[i].c_str(), - TfStringJoin(pathEntries, "\n").c_str()); + for (const auto& layerStack : FindAllLayerStacksUsingLayer(layer)) { + if (_primDependencies->UsesLayerStack(layerStack)) { + return true; } - - std::sort(entries.begin(), entries.end()); - *debugSummary = TfStringJoin(entries, "\n"); } - - TF_VERIFY(not layerOffsets or layerOffsets->size() == result.size(), - "%zu layerOffsets != %zu results", - layerOffsets->size(), result.size()); - TF_VERIFY(not sourceNodes or result.size() == sourceNodes->size(), - "%zu sourceNodes != %zu results -- they must correspond", - sourceNodes->size(), result.size()); - - return result; + + return false; } SdfPathVector @@ -1202,30 +831,6 @@ PcpCache::_Translate( return result; } -SdfPathVector -PcpCache::GetPathsUsingSite( - const SdfLayerHandle& layer, - const SdfPath& path, - UsingSite usingSite, - SdfLayerOffsetVector* layerOffsets, - const SdfPath& fallbackAncestor) const -{ - return _GetPathsUsingSite( - layer, path, usingSite, layerOffsets, /* sourceNodes = */ NULL, - fallbackAncestor); -} - -SdfPathVector -PcpCache::GetPathsUsingSite( - const PcpLayerStackPtr& layerStack, - const SdfPath& path, - unsigned int dependencyType, - bool recursive) const -{ - return _GetPathsUsingPcpSite( - layerStack, path, dependencyType, /* sourceNodes = */ NULL, recursive); -} - bool PcpCache::CanHaveOpinionForSite( const SdfPath& localPcpSitePath, @@ -1542,16 +1147,22 @@ _AddLayerStackSite( // Ignore. *oldNodePath = oldPath; *newNodePath = newPath; + TF_DEBUG(PCP_NAMESPACE_EDIT) + .Msg(" - not final. skipping relocate\n"); return final; } else if (*oldNodePath == *newNodePath) { // The edit is absorbed by this layer stack, so there's // no need to propagate the edit any further. + TF_DEBUG(PCP_NAMESPACE_EDIT) + .Msg(" - final. stopping at node where path is unaffected\n"); final = true; return final; } else if (oldNodePath->IsPrimPath() and not node.IsDueToAncestor()) { final = true; + TF_DEBUG(PCP_NAMESPACE_EDIT) + .Msg(" - final. direct arc fixup\n"); switch (node.GetArcType()) { case PcpArcTypeLocalInherit: case PcpArcTypeGlobalInherit: @@ -1598,6 +1209,11 @@ _AddLayerStackSite( site.newPath = newPath; site.layerStack = node.GetParentNode().GetLayerStack(); + TF_DEBUG(PCP_NAMESPACE_EDIT) + .Msg(" - adding layer stack edit <%s> -> <%s>\n", + site.oldPath.GetText(), + site.newPath.GetText()); + return final; } @@ -1610,10 +1226,6 @@ PcpCache::ComputeNamespaceEdits( { TRACE_FUNCTION(); - static const bool recursive = true; - static const bool spooky = true; - static const bool primsOnly = true; - NamespaceEdits result; SdfPathVector depPaths; @@ -1674,38 +1286,32 @@ PcpCache::ComputeNamespaceEdits( }; if (primSites.empty()) { - // This is the relocation case and we don't have any convenient - // dependency to report sites using (relocatesLayer, primPath). - // So we'll find every site using (someLayerStack, primPath) + // This is the relocation case. + // We'll find every site using (someLayerStack, primPath) // where someLayerStack is any layer stack that includes // relocatesLayer. for (size_t cacheIndex = 0, n = caches.size(); cacheIndex != n; ++cacheIndex) { PcpCache* cache = caches[cacheIndex]; - const PcpLayerStackPtrVector& layerStacks = - cache->FindAllLayerStacksUsingLayer(relocatesLayer); - - // Get all sites in cache that depend on primPath in any of - // the layer stacks. - for (const auto& layerStack : layerStacks) { - PcpNodeRefVector depNodes; - depPaths = cache->_GetPathsUsingPcpSite( - layerStack, primPath, PcpDirect | PcpAncestral, &depNodes); - - // If this is the cache's own layer stack then include the - // original path itself. - if (cache->_layerStack == layerStack) { - depPaths.push_back(primPath); - depNodes.push_back(cache->_GetNodeProvidingSpec( - primPath, relocatesLayer, primPath)); - TF_VERIFY(depNodes.back()); - } - // Store the node for each dependent site. - for (const auto& node : depNodes) { - _CacheNodeHelper::InsertCacheNodePair( - cacheIndex, node, &nodes); - } + // Store the node for each dependent site. + PcpDependencyVector deps = + cache->FindDependentPaths( + relocatesLayer, primPath, + PcpDependencyTypeAnyNonVirtual, + /* recurseOnSite */ true, + /* recurseOnIndex */ true, + /* filter */ true); + auto visitNodeFn = [&](const SdfPath &depIndexPath, + const PcpNodeRef &node, + PcpDependencyFlags flags) { + _CacheNodeHelper::InsertCacheNodePair(cacheIndex, + node, &nodes); + }; + for(const PcpDependency &dep: deps) { + Pcp_ForEachDependentNode(dep.sitePath, relocatesLayer, + dep.indexPath, + *cache, visitNodeFn); } } } @@ -1715,19 +1321,32 @@ PcpCache::ComputeNamespaceEdits( cacheIndex != n; ++cacheIndex) { PcpCache* cache = caches[cacheIndex]; - // Get all sites in cache that depend on any spec in primSites. - for (const auto& primSite : primSites) { - TF_VERIFY(primSite.path == primPath); - PcpNodeRefVector depNodes; - depPaths = - cache->_dependencies->Get(primSite.layer, primSite.path, - not recursive, primsOnly, - not spooky, &depNodes); - - // Store the node for each dependent site. - for (const auto& node : depNodes) { - _CacheNodeHelper::InsertCacheNodePair( - cacheIndex, node, &nodes); + // Store the node for each dependent site. + for(const SdfSite& primSite: primSites) { + PcpDependencyVector deps = + cache->FindDependentPaths( + primSite.layer, primPath, + PcpDependencyTypeAnyNonVirtual, + /* recurseOnSite */ false, + /* recurseOnIndex */ false, + /* filter */ true); + auto visitNodeFn = [&](const SdfPath &depIndexPath, + const PcpNodeRef &node, + PcpDependencyFlags flags) { + TF_DEBUG(PCP_NAMESPACE_EDIT) + .Msg(" found dep node: <%s> -> <%s> %s\n", + depIndexPath.GetText(), + node.GetPath().GetText(), + PcpDependencyFlagsToString(flags).c_str()); + if (flags != PcpDependencyTypeNone) { + _CacheNodeHelper::InsertCacheNodePair(cacheIndex, + node, &nodes); + } + }; + for(const PcpDependency &dep: deps) { + Pcp_ForEachDependentNode(dep.sitePath, primSite.layer, + dep.indexPath, + *cache, visitNodeFn); } } @@ -1741,37 +1360,44 @@ PcpCache::ComputeNamespaceEdits( // they must be fixed, but can't inherits outside // this cache also see the namespace edit? if (cache == this and curPath.IsPrimPath()) { - // Get all of the direct dependents on anything at and below - // the namespace edited site. - depPaths = GetPathsUsingSite(_layerStack, primPath, - PcpDirect, recursive); - SdfPathSet allSites(depPaths.begin(), depPaths.end()); + + SdfPathSet descendentPrimPaths; + + const PcpDependencyFlags depMask = + PcpDependencyTypeDirect | PcpDependencyTypeNonVirtual; // Get all of the direct dependents on the namespace edited - // site. - depPaths = GetPathsUsingSite(_layerStack, primPath, - PcpDirect, not recursive); - SdfPathSet directSites(depPaths.begin(), depPaths.end()); - - // Compute the direct dependents on descendant of the - // namespace edited site. - SdfPathSet descendantSites; - std::set_difference(allSites.begin(), allSites.end(), - directSites.begin(), directSites.end(), - std::inserter(descendantSites, - descendantSites.end())); + // site and anything below. + for (const PcpDependency &dep: + FindDependentPaths(_layerStack, primPath, depMask, + /* recurseOnSite */ true, + /* recurseOnIndex */ false, + /* filter */ true)) { + if (dep.indexPath.IsPrimPath()) { + descendentPrimPaths.insert(dep.indexPath); + } + } + + // Remove the direct dependents on the site itself. + for (const PcpDependency &dep: + FindDependentPaths(_layerStack, primPath, depMask, + /* recurseOnSite */ false, + /* recurseOnIndex */ false, + /* filter */ true)) { + descendentPrimPaths.erase(dep.indexPath); + } // Check each direct dependent site for inherits pointing // at this cache's layer stack. Make sure to skip ancestral // nodes, since the code that handles direct inherits below // needs to have the nodes where the inherits are introduced. - for (const auto& descendantSite : descendantSites) { - auto range = _GetPrimIndex(descendantSite)->GetNodeRange( - PcpRangeTypeLocalInherit); + for (const SdfPath& descendentPrimPath : descendentPrimPaths) { + auto range = _GetPrimIndex(descendentPrimPath) + ->GetNodeRange(PcpRangeTypeLocalInherit); for (auto nodeIter = range.first; nodeIter != range.second; ++nodeIter) { - const auto& node = *nodeIter; + const PcpNodeRef &node = *nodeIter; if (node.GetLayerStack() == _layerStack and not node.IsDueToAncestor()) { // Found an inherit using a descendant. @@ -1891,6 +1517,29 @@ PcpCache::ComputeNamespaceEdits( SdfPath oldNodePath = curPath; SdfPath newNodePath = newPath; + TF_DEBUG(PCP_NAMESPACE_EDIT) + .Msg("\n processing node:\n" + " cache: %s\n" + " node.type: %s\n" + " node.path: <%s>\n" + " node.rootPath: <%s>\n" + " node.layerStack: %s\n" + " curPath: <%s>\n" + " newPath: <%s>\n" + " oldNodePath: <%s>\n" + " newNodePath: <%s>\n", + TfStringify( caches[cacheIndex] + ->GetLayerStack()->GetIdentifier()).c_str(), + TfStringify(node.GetArcType()).c_str(), + node.GetPath().GetText(), + node.GetRootNode().GetPath().GetText(), + TfStringify(node.GetLayerStack()->GetIdentifier()).c_str(), + curPath.GetText(), + newPath.GetText(), + oldNodePath.GetText(), + newNodePath.GetText() + ); + // Handle the node itself. Note that the node, although representing // the namespace edited site, can appear in different layer stacks. // This happens when we have two scenes sharing a layer. If we edit @@ -1915,16 +1564,28 @@ PcpCache::ComputeNamespaceEdits( // Handle each arc from node to the root. while (node.GetParentNode()) { + TF_DEBUG(PCP_NAMESPACE_EDIT) + .Msg(" - traverse to parent of <%s>. <%s> -> <%s>\n", + node.GetPath().GetText(), + oldNodePath.GetText(), + newNodePath.GetText()); if (sites.insert(node.GetParentNode().GetSite()).second) { // Add site and translate paths to parent node. if (_AddLayerStackSite(&result, node, cacheIndex, &oldNodePath, &newNodePath)) { - // Reached a direct arc so we don't have to continue. + // Reached a direct arc, so we don't have to continue. + // The composed object will continue to exist at the + // same path, with the arc target updated. + TF_DEBUG(PCP_NAMESPACE_EDIT) + .Msg(" - done! fixed direct arc.\n"); break; } } else { + TF_DEBUG(PCP_NAMESPACE_EDIT) + .Msg(" - adjusted path for relocate\n"); // Translate paths to parent node. + // Adjust relocates as needed. _TranslatePathsAndEditRelocates(NULL, node, cacheIndex, &oldNodePath, &newNodePath); } @@ -1936,6 +1597,9 @@ PcpCache::ComputeNamespaceEdits( // If we made it all the way to the root then we have a cacheSite. if (not node.GetParentNode()) { if (not _IsInvalidEdit(oldNodePath, newNodePath)) { + TF_DEBUG(PCP_NAMESPACE_EDIT) + .Msg(" - adding cacheSite for %s\n", + node.GetPath().GetText()); result.cacheSites.resize(result.cacheSites.size() + 1); CacheSite& cacheSite = result.cacheSites.back(); cacheSite.cacheIndex = cacheIndex; @@ -1993,21 +1657,40 @@ PcpCache::ComputeNamespaceEdits( cacheIndex != n; ++cacheIndex) { PcpCache* cache = caches[cacheIndex]; + TF_DEBUG(PCP_NAMESPACE_EDIT) + .Msg("- dep cache: %s\n", + TfStringify( cache->GetLayerStack()->GetIdentifier()).c_str()); + + std::set layerStacks; + for(const SdfLayerRefPtr &layer: _layerStack->GetLayers()) { + const PcpLayerStackPtrVector& layerStackVec = + cache->FindAllLayerStacksUsingLayer(layer); + layerStacks.insert(layerStackVec.begin(), layerStackVec.end()); + } + // Get the sites in cache that use any proper descendant of the // namespace edited site and what each site depends on. std::map descendantPathsAndNodes; - PcpNodeRefVector sourceNodes; - for (const auto& layer : _layerStack->GetLayers()) { - SdfPathVector paths = - cache->_GetPathsUsingSite(layer, curPath, - UsingSiteAndDescendants, - /* layerOffsets = */ NULL, - &sourceNodes); - for (size_t i = 0, n = paths.size(); i != n; ++i) { - if (not paths[i].IsPrimPath() or - sourceNodes[i].GetPath() != curPath) { - descendantPathsAndNodes[paths[i]] = sourceNodes[i]; + for (const PcpLayerStackPtr& layerStack: layerStacks) { + PcpDependencyVector deps = + cache->FindDependentPaths( + layerStack, primPath, + PcpDependencyTypeAnyNonVirtual, + /* recurseOnSite */ true, + /* recurseOnIndex */ true, + /* filter */ true); + auto visitNodeFn = [&](const SdfPath &depIndexPath, + const PcpNodeRef &node, + PcpDependencyFlags flags) { + if (!depIndexPath.IsPrimPath() || + node.GetPath() != curPath) { + descendantPathsAndNodes[depIndexPath] = node; } + }; + for(const PcpDependency &dep: deps) { + Pcp_ForEachDependentNode(dep.sitePath, layerStack, + dep.indexPath, + *cache, visitNodeFn); } } @@ -2068,6 +1751,70 @@ PcpCache::ComputeNamespaceEdits( } } + // Final namespace edits. + + // Diagnostics. + // TODO: We should split this into a NamespaceEdits->string function + // in diagnostics.cpp. + if (TfDebug::IsEnabled(PCP_NAMESPACE_EDIT)) { + TF_DEBUG(PCP_NAMESPACE_EDIT) + .Msg("PcpCache::ComputeNamespaceEdits():\n" + " cache: %s\n" + " curPath: <%s>\n" + " newPath: <%s>\n", + TfStringify( GetLayerStack()->GetIdentifier()).c_str(), + curPath.GetText(), + newPath.GetText() + ); + TF_FOR_ALL(cacheSite, result.cacheSites) { + TF_DEBUG(PCP_NAMESPACE_EDIT) + .Msg(" cacheSite:\n" + " cache: %s\n" + " oldPath: <%s>\n" + " newPath: <%s>\n", + TfStringify( caches[cacheSite->cacheIndex] + ->GetLayerStack()->GetIdentifier()).c_str(), + cacheSite->oldPath.GetText(), + cacheSite->newPath.GetText()); + } + TF_FOR_ALL(layerStackSite, result.layerStackSites) { + TF_DEBUG(PCP_NAMESPACE_EDIT) + .Msg(" layerStackSite:\n" + " cache: %s\n" + " type: %s\n" + " layerStack: %s\n" + " sitePath: <%s>\n" + " oldPath: <%s>\n" + " newPath: <%s>\n", + TfStringify( caches[layerStackSite->cacheIndex] + ->GetLayerStack()->GetIdentifier()).c_str(), + TfStringify(layerStackSite->type).c_str(), + TfStringify(layerStackSite->layerStack + ->GetIdentifier()).c_str(), + layerStackSite->sitePath.GetText(), + layerStackSite->oldPath.GetText(), + layerStackSite->newPath.GetText()); + } + TF_FOR_ALL(layerStackSite, result.invalidLayerStackSites) { + TF_DEBUG(PCP_NAMESPACE_EDIT) + .Msg(" invalidLayerStackSite:\n" + " cache: %s\n" + " type: %s\n" + " layerStack: %s\n" + " sitePath: <%s>\n" + " oldPath: <%s>\n" + " newPath: <%s>\n", + TfStringify( caches[layerStackSite->cacheIndex] + ->GetLayerStack()->GetIdentifier()).c_str(), + TfStringify(layerStackSite->type).c_str(), + TfStringify(layerStackSite->layerStack + ->GetIdentifier()).c_str(), + layerStackSite->sitePath.GetText(), + layerStackSite->oldPath.GetText(), + layerStackSite->newPath.GetText()); + } + } + return result; } @@ -2169,7 +1916,7 @@ PcpCache::Apply(const PcpCacheChanges& changes, PcpLifeboat* lifeboat) // Clear everything for scene graph objects. _primIndexCache.clear(); _propertyIndexCache.clear(); - _dependencies->RemoveAll(lifeboat); + _primDependencies->RemoveAll(lifeboat); } else { // Blow prim and property indexes due to prim graph changes. @@ -2193,29 +1940,24 @@ PcpCache::Apply(const PcpCacheChanges& changes, PcpLifeboat* lifeboat) TF_FOR_ALL(i, changes.didChangeSpecs) { const SdfPath& path = *i; if (path.IsAbsoluteRootOrPrimPath()) { - // We've possibly changed the prim spec stack. Since - // we track dependencies using those specs we must - // update those specs. Note that we may have blown - // the prim index so check that it still exists. + // We've possibly changed the prim spec stack. Note that + // we may have blown the prim index so check that it exists. if (PcpPrimIndex* primIndex = _GetPrimIndex(path)) { - // Rebuild the prim stack and get the sites the prim - // index depends on. - SdfSiteVector depSites; - PcpNodeRefVector depNodes; - Pcp_UpdatePrimStack(primIndex, &depSites, &depNodes); + Pcp_RescanForSpecs(primIndex, IsUsd(), + /* updateHasSpecs */ true); // If there are no specs left then we can discard the // prim index. - if (depSites.empty()) { - _RemovePrimAndPropertyCaches(path, lifeboat); + bool anyNodeHasSpecs = false; + TF_FOR_ALL(it, primIndex->GetNodeRange()) { + if (it->HasSpecs()) { + anyNodeHasSpecs = true; + break; + } } - else { - // Replace dependencies. - static const bool specsAtPathOnly = true; - _dependencies->Remove(path, lifeboat, specsAtPathOnly); - _dependencies->Add(path, depSites, depNodes); + if (not anyNodeHasSpecs) { + _RemovePrimAndPropertyCaches(path, lifeboat); } - } } else if (path.IsPropertyPath()) { @@ -2277,9 +2019,6 @@ PcpCache::Apply(const PcpCacheChanges& changes, PcpLifeboat* lifeboat) } } _includedPayloads.insert(newIncludes.begin(), newIncludes.end()); - - // We can now flush any pending changes in our dependencies. - _dependencies->Flush(); } void @@ -2340,8 +2079,6 @@ PcpCache::ReloadReferences(PcpChanges* changes, const SdfPath& primPath) { TRACE_FUNCTION(); - static const bool recursive = true; - ArResolverContextBinder binder(_pathResolverContext); // Traverse every PrimIndex at or under primPath to find @@ -2369,12 +2106,12 @@ PcpCache::ReloadReferences(PcpChanges* changes, const SdfPath& primPath) } // Check each used layer stack (gathered above) for invalid sublayers. - TF_FOR_ALL(layerStack, layerStacksAtOrUnderPrim) { + for (const PcpLayerStackPtr& layerStack: layerStacksAtOrUnderPrim) { // Scan errors for a sublayer error. - PcpErrorVector errs = (*layerStack)->GetLocalErrors(); - TF_FOR_ALL(e, errs) { + PcpErrorVector errs = layerStack->GetLocalErrors(); + for (const PcpErrorBasePtr &err: errs) { if (PcpErrorInvalidSublayerPathPtr typedErr = - dynamic_pointer_cast(*e)){ + dynamic_pointer_cast(err)){ changes->DidMaybeFixSublayer(this, typedErr->layer, typedErr->sublayerPath); } @@ -2383,12 +2120,12 @@ PcpCache::ReloadReferences(PcpChanges* changes, const SdfPath& primPath) // Reload every layer used by prims at or under primPath, except for // local layers. - SdfLayerHandleSet layersToReload = - _dependencies->GetLayersUsedByPrim(primPath, recursive); - - if (_layerStack) { - TF_FOR_ALL(it, _layerStack->GetLayers()) { - layersToReload.erase(*it); + SdfLayerHandleSet layersToReload; + for (const PcpLayerStackPtr& layerStack: layerStacksAtOrUnderPrim) { + for (const SdfLayerHandle& layer: layerStack->GetLayers()) { + if (not _layerStack->HasLayer(layer)) { + layersToReload.insert(layer); + } } } @@ -2400,9 +2137,7 @@ PcpCache::_RemovePrimCache(const SdfPath& primPath, PcpLifeboat* lifeboat) { _PrimIndexCache::iterator it = _primIndexCache.find(primPath); if (it != _primIndexCache.end()) { - static const bool specsAtPathOnly = true; - _dependencies->Remove(it->first, lifeboat, specsAtPathOnly); - + _primDependencies->Remove(it->second, lifeboat); PcpPrimIndex empty; it->second.Swap(empty); } @@ -2415,7 +2150,7 @@ PcpCache::_RemovePrimAndPropertyCaches(const SdfPath& root, std::pair<_PrimIndexCache::iterator, _PrimIndexCache::iterator> range = _primIndexCache.FindSubtreeRange(root); for (_PrimIndexCache::iterator i = range.first; i != range.second; ++i) { - _dependencies->Remove(i->first, lifeboat); + _primDependencies->Remove(i->second, lifeboat); } if (range.first != range.second) { _primIndexCache.erase(range.first); @@ -2631,7 +2366,7 @@ struct Pcp_ParallelIndexer SdfPath const &primIndexPath = outputs->primIndex.GetPath(); // Add dependencies. - _cache->_AddIndexDependencies(primIndexPath, outputs); + _cache->_primDependencies->Add(outputs->primIndex); // Store index off to the side so we can publish several at once, // ideally. We have to make a copy to move into the _cache itself, @@ -2801,43 +2536,16 @@ PcpCache::ComputePrimIndex(const SdfPath & path, PcpErrorVector *allErrors) outputs.allErrors.begin(), outputs.allErrors.end()); + // Add dependencies. + _primDependencies->Add(outputs.primIndex); + // Save the prim index. PcpPrimIndex &cacheEntry = _primIndexCache[path]; cacheEntry.Swap(outputs.primIndex); - // Add dependencies. - _AddIndexDependencies(path, &outputs); - return cacheEntry; } -void -PcpCache::_AddIndexDependencies( - const SdfPath &path, PcpPrimIndexOutputs *outputs) -{ - // Don't add dependencies on our own site. - outputs->dependencies.sites.erase( - PcpPrimIndexDependencies::Site(_layerStack, path)); - - // Add dependencies. - Pcp_Dependencies *deps = _dependencies.get(); - deps->Add(path, outputs->dependencies); - if (not _usd) { - deps->Add(path, outputs->dependencySites, outputs->dependencyNodes); - deps->AddSpookySitesUsedByPrim(path, outputs->spookyDependencies); - deps->AddSpookySitesUsedByPrim( - path, outputs->spookyDependencySites, - outputs->spookyDependencyNodes); - } - else { - // We should not be picking up any spooky dependencies here, since - // inherits are not supported in the usd codepath. - TF_VERIFY(outputs->spookyDependencies.sites.empty()); - TF_VERIFY(outputs->spookyDependencySites.empty()); - TF_VERIFY(outputs->spookyDependencyNodes.empty()); - } -} - PcpPropertyIndex* PcpCache::_GetPropertyIndex(const SdfPath& path) { @@ -2901,15 +2609,3 @@ PcpCache::PrintStatistics() const { Pcp_PrintCacheStatistics(this); } - -void -PcpCache::PrintDependencies() const -{ - _dependencies->DumpDependencies(std::cout); -} - -void -PcpCache::CheckDependencies() const -{ - _dependencies->CheckInvariants(); -} diff --git a/pxr/usd/lib/pcp/cache.h b/pxr/usd/lib/pcp/cache.h index 3d7e0a801e..42180d3567 100644 --- a/pxr/usd/lib/pcp/cache.h +++ b/pxr/usd/lib/pcp/cache.h @@ -24,7 +24,9 @@ #ifndef PCP_CACHE_H #define PCP_CACHE_H +#include "pxr/usd/pcp/dependency.h" #include "pxr/usd/pcp/errors.h" +#include "pxr/usd/pcp/mapFunction.h" #include "pxr/usd/pcp/primIndex.h" #include "pxr/usd/pcp/propertyIndex.h" #include "pxr/usd/sdf/declareHandles.h" @@ -49,6 +51,7 @@ class Pcp_Dependencies; class PcpLayerStackIdentifier; class PcpLifeboat; class PcpNodeRef; +class PcpMapFunction; TF_DECLARE_WEAK_AND_REF_PTRS(PcpLayerStack); TF_DECLARE_WEAK_AND_REF_PTRS(Pcp_LayerStackRegistry); @@ -374,13 +377,6 @@ class PcpCache /// \name Dependencies /// @{ - /// Options for finding dependencies. - enum UsingSite { - UsingSiteOnly, ///< Dependencies of site only - UsingSiteAndDescendants, ///< Dependencies at and under site - UsingSiteAndDescendantPrims ///< Dependencies on prims at and under site - }; - /// Returns set of all layers used by this cache. SdfLayerHandleSet GetUsedLayers() const; @@ -391,46 +387,43 @@ class PcpCache const PcpLayerStackPtrVector& FindAllLayerStacksUsingLayer(const SdfLayerHandle& layer) const; - /// Returns the path of every \c PcpSite that uses the spec in \p layer at - /// \p path. If \p usingSite is \c UsingSiteAndDescendantPrims then also - /// returns the path of every \c PcpSite that uses any prim descendant of - /// \p path. If \p usingSite is UsingSiteAndDescendants then also returns - /// the path of every \c PcpSite that uses any descendant of \p path. + /// Returns dependencies on the given site of scene description, + /// as discovered by the cached index computations. /// - /// If \p layerOffsets is not \c NULL then it will be filled with the - /// layer offsets from the site of the spec to the resulting paths. - /// Each element in \p layerOffsets corresponds to the path at the same - /// index in the return value. + /// \param depMask specifies what classes of dependency to include; + /// see PcpDependencyFlags for details + /// \param recurseOnSite includes incoming dependencies on + /// children of sitePath + /// \param recurseOnIndex extends the result to include all PcpCache + /// child indexes below discovered results + /// \param filterForExistingCachesOnly filters the results to only + /// paths representing computed prim and property index caches; + /// otherwise a recursively-expanded result can include + // un-computed paths that are expected to depend on the site + PcpDependencyVector + FindDependentPaths(const PcpLayerStackPtr& siteLayerStack, + const SdfPath& sitePath, + PcpDependencyFlags depMask, + bool recurseOnSite, + bool recurseOnIndex, + bool filterForExistingCachesOnly) const; + + /// Returns dependencies on the given site of scene description, + /// as discovered by the cached index computations. /// - /// If \p fallbackAncestor isn't empty then, if necessary, the paths - /// that use the spec in \p layer at \p path will be derived from the - /// paths that use the \p fallbackAncestor path. This is needed in - /// cases where dependencies on the spec have not yet been registered, - /// e.g. during change processing. - // - // XXX: The fallbackAncestor behavior feels a bit out of place in this API. - // It was originally intended to be a private helper for PcpChanges, - // but was moved here and made public because Csd's change processing - // needed the same functionality. There are likely alternative methods - // for getting Csd the information it needs; we should revisit this - // API to see if we can clean this up. - SdfPathVector GetPathsUsingSite(const SdfLayerHandle& layer, - const SdfPath& path, - UsingSite usingSite = UsingSiteOnly, - SdfLayerOffsetVector* layerOffsets = 0, - const SdfPath& fallbackAncestor = - SdfPath()) const; - - /// Returns the path of every \c PcpSite that uses the site given by - /// \p layerStack and \p path, via a dependency specified by - /// \p dependencyType. \p dependencyType is a bitwise-OR of - /// \c PcpDependencyType enum values. If \p recursive is \c true, - /// then we return the path of every \c PcpSite that uses any descendant - /// of \p path, via a dependency specified by \p dependencyType. - SdfPathVector GetPathsUsingSite(const PcpLayerStackPtr& layerStack, - const SdfPath& path, - unsigned int dependencyType, - bool recursive = false) const; + /// This variant takes a site layer rather than a layer stack. + /// It will check every layer stack using that layer, and apply + /// any relevant sublayer offsets to the map functions in the + /// returned PcpDependencyVector. + /// + /// See the other method for parameter details. + PcpDependencyVector + FindDependentPaths(const SdfLayerHandle& siteLayer, + const SdfPath& sitePath, + PcpDependencyFlags depMask, + bool recurseOnSite, + bool recurseOnIndex, + bool filterForExistingCachesOnly) const; /// Returns \c true if an opinion for the site at \p localPcpSitePath /// in the cache's layer stack can be provided by an opinion in \p layer, @@ -610,12 +603,6 @@ class PcpCache /// Prints various statistics about the data stored in this cache. void PrintStatistics() const; - /// Prints the known dependencies. - void PrintDependencies() const; - - /// Verify that the internal dependency data structures are consistent. - void CheckDependencies() const; - /// @} private: @@ -625,8 +612,6 @@ class PcpCache template friend struct Pcp_ParallelIndexer; - struct _PathDebugInfo; - // Helper struct to type-erase a children predicate for the duration of // ComputePrimIndexesInParallel. // @@ -685,10 +670,6 @@ class PcpCache const char *mallocTag1, const char *mallocTag2); - // Helper to add a computed prim index to dependency structures. - void _AddIndexDependencies(const SdfPath &path, - PcpPrimIndexOutputs *outputs); - void _RemovePrimCache(const SdfPath& primPath, PcpLifeboat* lifeboat); void _RemovePrimAndPropertyCaches(const SdfPath& root, PcpLifeboat* lifeboat); @@ -719,58 +700,6 @@ class PcpCache const SdfPath& path, SdfLayerOffsetVector* layerOffsets) const; - // Implementation for GetPathsUsingSite; see documentation on public API - // for details. If \p nodes is not \c NULL, the node that introduced - // the dependency on \p layerStack and \p path will be added to it/ - // If \p spookyDependencies is true this will use the spooky dependencies - // instead of normal dependencies. - SdfPathVector _GetPathsUsingPcpSite(const PcpLayerStackPtr& layerStack, - const SdfPath& path, - unsigned int dependencyType, - PcpNodeRefVector* sourceNodes = 0, - bool recursive = false, - bool spookyDependencies = false) const; - - // Implementation for GetPathsUsingSite; see documentation on public API - // for details. If supplied, this function will also fill in \p debugSummary - // with useful debugging information. If \p spookyDependencies is true - // this will use the spooky dependencies instead of normal dependencies. - SdfPathVector _GetPathsUsingSite(const SdfLayerHandle& layer, - const SdfPath& path, - UsingSite usingSite = UsingSiteOnly, - SdfLayerOffsetVector* layerOffsets = 0, - PcpNodeRefVector* sourceNodes = 0, - const SdfPath& fallbackAncestor = - SdfPath(), - bool spookyDependencies = false, - std::string* debugSummary = 0) const; - - // Returns the path of every prim in this cache that uses the prim given - // by \p layerStack and \p path. See documentation on _GetPathsUsingSite - // and _GetPathsUsingSiteFromDependencies for details about arguments. - SdfPathVector _GetPathsUsingPrim(const SdfLayerHandle& layer, - const SdfPath& path, - PcpNodeRefVector* sourceNodes = 0, - UsingSite usingSite = UsingSiteOnly, - const SdfPath& fallbackAncestor = - SdfPath(), - bool spookyDependencies = false, - _PathDebugInfo* debugInfo = 0) const; - - // Queries the Pcp_Dependency object for the path of every \c PcpSite - // that uses the prim in \p layer at \p path. Additional dependencies - // will be returned based on the value for \p use. If \p sourceNodes - // is not \c NULL, then for each returned path the node that introduced - // the dependency on \p layer and \p path will be added to it. - // \p spookyDependencies is true this will use the spooky dependencies - // instead of normal dependencies. - SdfPathVector - _GetPathsUsingPrimFromDependencies(const SdfLayerHandle& layer, - const SdfPath& path, - PcpNodeRefVector* sourceNodes = 0, - UsingSite use = UsingSiteOnly, - bool spookyDependencies = false) const; - // Returns true if any prim in this cache uses \p layer, false otherwise. bool _UsesLayer(const SdfLayerHandle& layer) const; @@ -818,7 +747,7 @@ class PcpCache _LayerStackCache _layerStackCache; _PrimIndexCache _primIndexCache; _PropertyIndexCache _propertyIndexCache; - boost::scoped_ptr _dependencies; + boost::scoped_ptr _primDependencies; }; #endif diff --git a/pxr/usd/lib/pcp/changes.cpp b/pxr/usd/lib/pcp/changes.cpp index f98c157b6b..a0ea6240d6 100644 --- a/pxr/usd/lib/pcp/changes.cpp +++ b/pxr/usd/lib/pcp/changes.cpp @@ -320,44 +320,6 @@ PcpChanges::DidChange(const std::vector& caches, typedef std::map SpecChangesTypes; - class _FindAncestor { - public: - _FindAncestor(const SdfPathSet& pcs) : _pcs(pcs) { } - - // If \p path or a prefix of \p path is in the set passed to the - // c'tor then returns the path to the nearest ancestral property - // or prim of the path found in the set. Otherwise returns the - // empty path. - SdfPath operator()(const SdfPath& path) const - { - SdfPath result; - - if (not _pcs.empty()) { - SdfPathSet::const_iterator i = _pcs.lower_bound(path); - if (i != _pcs.end() and *i == path) { - result = *i; - } - else if (i != _pcs.begin()) { - --i; - if (path.HasPrefix(*i)) { - result = *i; - } - } - if (not result.IsEmpty()) { - if (result.IsRelationalAttributePath()) { - result = result.GetParentPath(); - } - result = result.GetParentPath(); - } - } - - return result; - } - - private: - const SdfPathSet& _pcs; - }; - TRACE_FUNCTION(); SdfPathSet pathsWithSignificantChanges; @@ -380,6 +342,12 @@ PcpChanges::DidChange(const std::vector& caches, std::string summary; std::string* debugSummary = TfDebug::IsEnabled(PCP_CHANGES) ? &summary : 0; + PCP_APPEND_DEBUG(" Caches:\n"); + for (PcpCache* cache: caches) { + PCP_APPEND_DEBUG(" %s\n", + TfStringify(cache->GetLayerStack()->GetIdentifier()).c_str()); + } + // Process all changes, first looping over all layers. TF_FOR_ALL(i, changes) { const SdfLayerHandle& layer = TfDynamic_cast(i->first); @@ -546,11 +514,6 @@ PcpChanges::DidChange(const std::vector& caches, // XXX: If this becomes a performance issue, we could // potentially apply the same incremental updating // that's currently done for relocates. - // - // XXX: This isn't picking up the case when layer - // offsets are changed in a referenced layer - // stack -- see bug 96370. - // pathsWithSignificantChanges.insert(path); PCP_APPEND_DEBUG(" Layer @%s@ changed: " "layer offsets (significant)\n", @@ -708,25 +671,16 @@ PcpChanges::DidChange(const std::vector& caches, } } - // Remove every path for which a prefix path is in the ancestor set. - Pcp_SubsumeDescendants(&fallbackToAncestorPaths); - - // Make a functor for finding the fallback ancestor. - _FindAncestor findAncestor(fallbackToAncestorPaths); - - // For every path we've found on this layer that has a significant - // change, find all paths in the cache that use the spec at - // (layer,path). If there aren't any and we want to fallback to our - // parent then find all paths in the cache that use the parent. In - // either case mark the found paths as having a significant change. + // For every path we've found on this layer that has a + // significant change, find all paths in the cache that use the + // spec at (layer, path) and mark them as affected. for (const auto& path : pathsWithSignificantChanges) { - // Compute the closest ancestor that must have dependencies. - SdfPath fallbackPath = findAncestor(path); - + const bool onlyExistingDependentPaths = + fallbackToAncestorPaths.count(path) == 0; for (auto cache : caches) { _DidChangeDependents( _ChangeTypeSignificant, cache, layer, - path, fallbackPath, debugSummary); + path, onlyExistingDependentPaths, debugSummary); } } @@ -734,12 +688,11 @@ PcpChanges::DidChange(const std::vector& caches, // a specific cache, use the same logic as above to mark those paths // as having a significant change, but only in the associated cache. for (const auto& p : pathsWithSignificantChangesByCache) { - // Compute the closest ancestor that must have dependencies. - SdfPath fallbackPath = findAncestor(p.second); - + const bool onlyExistingDependentPaths = + fallbackToAncestorPaths.count(p.second) == 0; _DidChangeDependents( _ChangeTypeSignificant, p.first, layer, - p.second, fallbackPath, debugSummary); + p.second, onlyExistingDependentPaths, debugSummary); } // For every path we've found that has a significant change, @@ -804,13 +757,10 @@ PcpChanges::DidChange(const std::vector& caches, changeType |= _ChangeTypeSpecs; } - // Compute the closest ancestor that must have dependencies. - SdfPath fallbackPath = findAncestor(path); - for (auto cache : caches) { _DidChangeDependents( changeType, cache, layer, - path, fallbackPath, debugSummary); + path, /* filter */ false, debugSummary); } } @@ -820,7 +770,6 @@ PcpChanges::DidChange(const std::vector& caches, // comparison to edits added through DidChangePaths(). if (not oldPaths.empty()) { SdfPathVector depPaths; - PcpNodeRefVector depNodes; for (auto cache : caches) { PcpCacheChanges::PathEditMap& renameChanges = @@ -835,33 +784,39 @@ PcpChanges::DidChange(const std::vector& caches, // it with the object at the old path. So we must // act as if we're deleting the object at the new path. if (not newPath.IsEmpty()) { - depPaths = cache->GetPathsUsingSite(layer, newPath); - for (const auto& depNewPath : depPaths) { - renameChanges[depNewPath] = SdfPath(); + PcpDependencyVector deps = + cache->FindDependentPaths( + layer, newPath, + PcpDependencyTypeAnyNonVirtual, + /* recurseOnSite */ false, + /* recurseOnIndex */ false, + /* filter */ true + ); + for (const auto &dep: deps) { + renameChanges[dep.indexPath] = SdfPath(); } } // Do every path dependent on the old path. - depPaths = cache->_GetPathsUsingSite( - layer, oldPath, PcpCache::UsingSiteOnly, - /* layerOffsets = */ 0, &depNodes); - - for (size_t j = 0, o = depPaths.size(); j != o; ++j) { - const SdfPath& depOldPath = depPaths[j]; - const PcpNodeRef& sourceNode = depNodes[j]; - - SdfPath depNewPath; - - // If this isn't a delete then translate the new path + PcpDependencyVector deps = + cache->FindDependentPaths( + layer, oldPath, + PcpDependencyTypeAnyNonVirtual, + /* recurseOnSite */ false, + /* recurseOnIndex */ false, + /* filter */ true + ); + for (const auto &dep: deps) { + SdfPath newIndexPath; + // If this isn't a delete then translate newPath if (not newPath.IsEmpty()) { - // XXX: Will translation work correctly - // given that it's based on the old - // path? - depNewPath = PcpTranslatePathFromNodeToRoot( - sourceNode, newPath); + newIndexPath = + dep.mapFunc.MapSourceToTarget(newPath); } - - renameChanges[depOldPath] = depNewPath; + renameChanges[dep.indexPath] = newIndexPath; + PCP_APPEND_DEBUG(" renameChanges <%s> to <%s>\n", + dep.indexPath.GetText(), + newIndexPath.GetText()); } } } @@ -1049,12 +1004,15 @@ PcpChanges::DidMaybeFixAsset( PCP_APPEND_DEBUG(" <%s>\n", site.path.GetText()); DidChangeSignificantly(cache, site.path); } - SdfPathVector depPaths = - cache->GetPathsUsingSite(layerStack, site.path, - PcpDirect | PcpAncestral); - for (const auto& depPath : depPaths) { - PCP_APPEND_DEBUG(" <%s>\n", depPath.GetText()); - DidChangeSignificantly(cache, depPath); + PcpDependencyVector deps = + cache->FindDependentPaths(layerStack, site.path, + PcpDependencyTypeAnyIncludingVirtual, + /* recurseOnSite */ true, + /* recurseOnIndex */ true, + /* filter */ true); + for(const auto &dep: deps) { + PCP_APPEND_DEBUG(" <%s>\n", dep.indexPath.GetText()); + DidChangeSignificantly(cache, dep.indexPath); } } @@ -1164,7 +1122,7 @@ PcpChanges::DidChangePaths( // oldPath appearing multiple times, e.g. A -> B -> C and // D -> B -> E, where B appears in two chains. - TF_DEBUG(PCP_CHANGES).Msg("PcpChanges::DidChangePath: @%s@<%s> to <%s>\n", + TF_DEBUG(PCP_CHANGES).Msg("PcpChanges::DidChangePaths: @%s@<%s> to <%s>\n", cache->GetLayerStackIdentifier().rootLayer-> GetIdentifier().c_str(), oldPath.GetText(), newPath.GetText()); @@ -1352,18 +1310,17 @@ PcpChanges::_DidChangeDependents( PcpCache* cache, const SdfLayerHandle& layer, const SdfPath& path, - const SdfPath& fallbackAncestor, + bool onlyExistingDependentPaths, std::string* debugSummary) { // Don't want to put a trace here, as this function can get called many // times during change processing. // TRACE_FUNCTION(); - const char* significance = - (changeType & _ChangeTypeSignificant) ? "significant" : "insignificant"; const bool isSignificantPrimChange = (changeType & _ChangeTypeSignificant) and - path.IsPrimOrPrimVariantSelectionPath(); + (path == SdfPath::AbsoluteRootPath() or + path.IsPrimOrPrimVariantSelectionPath()); // Set up table of functions to call for each dependency, based // on the type of change we're trying to propagate. @@ -1406,10 +1363,6 @@ PcpChanges::_DidChangeDependents( const _ChangeFunctions changeFuncs(this, changeType); - // Find all the dependencies specified. - std::string pathDebugSummary; - static const bool spookyDependencies = true; - // For significant changes to an Sd prim, we need to process its // dependencies as well as dependencies on descendants of that prim. // @@ -1421,95 +1374,32 @@ PcpChanges::_DidChangeDependents( // // We don't need to do this for significant property changes as properties // can't be individually relocated. - const PcpCache::UsingSite usingSite = - isSignificantPrimChange ? - PcpCache::UsingSiteAndDescendantPrims : PcpCache::UsingSiteOnly; - - SdfPathVector depPaths; - - // In USD mode, dependencies will be on the layer stacks, not the SdSites. - if (cache->_usd) { - const PcpLayerStackPtrVector& layerStacks = - cache->FindAllLayerStacksUsingLayer(layer); - for (const auto& layerStack : layerStacks) { - if (layerStack == cache->GetLayerStack()) { - depPaths.push_back(path.StripAllVariantSelections()); - } - SdfPathVector depsFromLayerStack = - cache->GetPathsUsingSite( - layerStack, - path, - PcpDirect | PcpAncestral, - (changeType & _ChangeTypeSignificant) /*recursive*/); - if (not depsFromLayerStack.empty()) { - depPaths.insert(depPaths.end(), - depsFromLayerStack.begin(), - depsFromLayerStack.end()); - } - } - } else { - depPaths = cache->_GetPathsUsingSite( - layer, path, usingSite, - /* layerOffsets = */ NULL, /* sourceNodes = */ NULL, - fallbackAncestor, not spookyDependencies, - debugSummary ? &pathDebugSummary : NULL); - } - - - if (not depPaths.empty()) { - // Found dependencies at path. We apparently did not just add - // the first spec. - PCP_APPEND_DEBUG( - " Resync following in @%s@ %s due to Sd site @%s@<%s>:\n" - " %s\n", - cache->GetLayerStackIdentifier().rootLayer->GetIdentifier().c_str(), - significance, - layer->GetIdentifier().c_str(), path.GetText(), - TfStringReplace(pathDebugSummary, "\n", "\n ").c_str()); - - for (const auto& depPath : depPaths) { - changeFuncs.RunFunctionsOnDependency(cache, depPath, layer, path); - } - } + PcpDependencyVector deps = cache->FindDependentPaths( + layer, path, PcpDependencyTypeAnyIncludingVirtual, + /* recurseOnSite */ isSignificantPrimChange, + /* recurseOnIndex */ false, + /* filter */ onlyExistingDependentPaths); - if (isSignificantPrimChange - // We do not have spooky dependencies in USD mode. - and not cache->_usd) { - // Significant prim changes require extra handling in addition - // to the processing above: We must also handle prims that - // depend on this path via spooky dependencies. - // - // For example, we need this so that switching a variant will - // invalidate prims relocated out from underneath. A variant - // selection change is itself a significant change (i.e. it - // requires rebuilding the prim index); but also any other - // significant change potentially introduces or otherwise - // modifes the variant selection. - const SdfPathVector spookyDepPaths = - cache->_GetPathsUsingSite( - layer, path, PcpCache::UsingSiteOnly, - /* layerOffsets = */ NULL, - /* sourceNodes = */ NULL, - /* fallbackAncestor = */ SdfPath(), - spookyDependencies, - debugSummary ? &pathDebugSummary : NULL); - - if (not spookyDepPaths.empty()) { - PCP_APPEND_DEBUG( - " Resync following in @%s@ %s due to spooky dependency on " - "Sd site @%s@<%s>:\n %s\n", - cache->GetLayerStackIdentifier(). - rootLayer->GetIdentifier().c_str(), - significance, - layer->GetIdentifier().c_str(), path.GetText(), - TfStringReplace(pathDebugSummary, "\n", "\n ").c_str()); - - for (const auto& depPath : spookyDepPaths) { - changeFuncs.RunFunctionsOnDependency(cache, depPath, - layer, path); - } - } + PCP_APPEND_DEBUG( + " Resync following in @%s@ %s due to Sd site @%s@<%s>%s:\n", + cache->GetLayerStackIdentifier() + .rootLayer->GetIdentifier().c_str(), + (changeType & _ChangeTypeSignificant) ? + "significant" : + "insignificant", + layer->GetIdentifier().c_str(), path.GetText(), + onlyExistingDependentPaths ? + " (restricted to existing caches)" : + " (not restricted to existing caches)"); + for (const auto& dep: deps) { + PCP_APPEND_DEBUG( + " <%s> depends on <%s>\n", + dep.indexPath.GetText(), + dep.sitePath.GetText()); + changeFuncs.RunFunctionsOnDependency(cache, dep.indexPath, + layer, dep.sitePath); } + PCP_APPEND_DEBUG(" Resync end\n"); } SdfLayerRefPtr @@ -1641,47 +1531,44 @@ PcpChanges::_DidChangeSublayer( // is because PcpPrimIndex's prim stack stores indices into the layer // stack that may need to be adjusted due to the addition or removal of // a layer from that stack. - const SdfPath& rootPath = SdfPath::AbsoluteRootPath(); - for (const auto& layerStack : layerStacks) { - static bool recursive = true; - SdfPathVector paths = - cache->GetPathsUsingSite(layerStack, rootPath, - PcpDirect | PcpAncestral, recursive); - - if (cache->GetLayerStack() == layerStack) { - if (*significant) { - paths.push_back(rootPath); - } - else { - const SdfPathVector otherPaths = - cache->GetPathsUsingSite( - layerStack->GetIdentifier().rootLayer, - rootPath, PcpCache::UsingSiteAndDescendantPrims); - paths.insert(paths.end(), otherPaths.begin(), otherPaths.end()); - } + // + // We rely on the caller to provide the affected layer stacks for + // us because some changes introduce new dependencies that wouldn't + // have been registered yet using the normal means -- such as unmuting + // a sublayer. + + SdfPathSet depPaths; + TF_FOR_ALL(layerStack, layerStacks) { + PcpDependencyVector deps = cache->FindDependentPaths( + *layerStack, + SdfPath::AbsoluteRootPath(), + PcpDependencyTypeAnyIncludingVirtual, + /* recurseOnSite */ true, + /* recurseOnIndex */ true, + /* filter */ true); + for (const auto &dep: deps) { + depPaths.insert(dep.indexPath); } + } - if (not paths.empty()) { - PCP_APPEND_DEBUG( - " %s following in @%s@ due to " - "%s sublayer @%s@ reload in Pcp layer stack @%s@:\n", - *significant ? "Resync" : "Spec changes", - cache->GetLayerStackIdentifier().rootLayer-> - GetIdentifier().c_str(), - *significant ? "significant" : "insignificant", - sublayer->GetIdentifier().c_str(), - layerStack->GetIdentifier().rootLayer-> - GetIdentifier().c_str()); - - for (const auto& path : paths) { - PCP_APPEND_DEBUG(" <%s>\n", path.GetText()); - if (*significant) { - DidChangeSignificantly(cache, path); - } - else { - DidChangeSpecStack(cache, path); - } - } + if (not depPaths.empty()) { + PCP_APPEND_DEBUG( + " %s following in @%s@ due to " + "%s reload in sublayer @%s@:\n", + *significant ? "Resync" : "Spec changes", + cache->GetLayerStackIdentifier().rootLayer-> + GetIdentifier().c_str(), + *significant ? "significant" : "insignificant", + sublayer->GetIdentifier().c_str()); + } + + for(const SdfPath& path: depPaths) { + PCP_APPEND_DEBUG(" <%s>\n", path.GetText()); + if (*significant) { + DidChangeSignificantly(cache, path); + } + else { + DidChangeSpecStack(cache, path); } } @@ -1769,64 +1656,49 @@ PcpChanges::_DidChangeLayerStackRelocations( &changes.newRelocatesPrimPaths); // Compare the old and new relocations to determine which - // paths are affected. + // paths (in this layer stack) are affected. _DeterminePathsAffectedByRelocationChanges( layerStack->GetRelocatesSourceToTarget(), changes.newRelocatesSourceToTarget, &changes.pathsAffectedByRelocationChanges); - // Diagnostics. + // Resync affected prims. + // Use dependencies to find affected caches. if (not changes.pathsAffectedByRelocationChanges.empty()) { - PCP_APPEND_DEBUG(" Relocation change in @%s@ affects\n", + PCP_APPEND_DEBUG(" Relocation change in %s affects:\n", TfStringify(layerStack).c_str()); - TF_FOR_ALL(path, changes.pathsAffectedByRelocationChanges) { - PCP_APPEND_DEBUG(" <%s>\n", path->GetText()); - } } + for (PcpCache* cache: caches) { + // Find the equivalent layer stack in this cache. + PcpLayerStackPtr equivLayerStack = + cache->FindLayerStack(layerStack->GetIdentifier()); + if (not equivLayerStack) { + continue; + } - // Resync affected prims. - for (const auto& path : changes.pathsAffectedByRelocationChanges) { - PCP_APPEND_DEBUG(" Relocation change affected path <%s>\n", - path.GetText()); - for (auto cache : caches) { - // Find paths to dependent caches. - SdfPathSet depPathSet; - - // Include the implicit self-dependency. - if (cache->GetLayerStack() == layerStack) { - depPathSet.insert(path); - } - - // Find the equivalent layer stack in this cache. - PcpLayerStackPtr equivLayerStack = - cache->FindLayerStack(layerStack->GetIdentifier()); - if (not equivLayerStack) { - continue; - } + SdfPathSet depPathSet; + for (const SdfPath& path : changes.pathsAffectedByRelocationChanges) { + PCP_APPEND_DEBUG(" <%s>\n", path.GetText()); - // Include normal dependencies. - const SdfPathVector depPaths = - cache->_GetPathsUsingPcpSite( - equivLayerStack, path, - /* dependencyType = */ PcpDirect | PcpAncestral, - /* sourceNodes = */ 0, - /* recursive = */ true, - /* spooky = */ false); - depPathSet.insert(depPaths.begin(), depPaths.end()); - - // Include spooky dependencies. - const SdfPathVector depPathsSpooky = - cache->_GetPathsUsingPcpSite( + PcpDependencyVector deps = + cache->FindDependentPaths( equivLayerStack, path, - /* dependencyType = */ PcpDirect | PcpAncestral, - /* sourceNodes = */ 0, - /* recursive = */ true, - /* spooky = */ true); - depPathSet.insert(depPathsSpooky.begin(), depPathsSpooky.end()); - - for (const auto& depPath : depPathSet) { - DidChangeSignificantly(cache, depPath); + PcpDependencyTypeAnyIncludingVirtual, + /* recurseOnSite */ true, + /* recurseOnIndex */ true, + /* filterForExistingCachesOnly */ false); + for (const auto &dep: deps) { + depPathSet.insert(dep.indexPath); } } + + if (not depPathSet.empty()) { + PCP_APPEND_DEBUG(" and dependent paths in %s\n", + TfStringify(layerStack).c_str()); + } + for (const SdfPath& depPath : depPathSet) { + PCP_APPEND_DEBUG(" <%s>\n", depPath.GetText()); + DidChangeSignificantly(cache, depPath); + } } } diff --git a/pxr/usd/lib/pcp/changes.h b/pxr/usd/lib/pcp/changes.h index 517d676d11..603ad3e38d 100644 --- a/pxr/usd/lib/pcp/changes.h +++ b/pxr/usd/lib/pcp/changes.h @@ -116,6 +116,8 @@ class PcpCacheChanges { PathEditMap didChangePath; }; +/// Structure used to temporarily retain layers and layerStacks within +/// a code block. Analogous to the autorelease pool in obj-c. class PcpLifeboat { public: PcpLifeboat(); @@ -303,7 +305,7 @@ class PcpChanges { PcpCache* cache, const SdfLayerHandle& layer, const SdfPath& path, - const SdfPath& fallbackAncestor, + bool onlyExistingDependentPaths, std::string* debugSummary); // Sublayer change type for _DidChangeSublayer. diff --git a/pxr/usd/lib/pcp/debugCodes.cpp b/pxr/usd/lib/pcp/debugCodes.cpp index 63f1364d55..b88cac5983 100644 --- a/pxr/usd/lib/pcp/debugCodes.cpp +++ b/pxr/usd/lib/pcp/debugCodes.cpp @@ -41,4 +41,6 @@ TF_REGISTRY_FUNCTION(TfDebug) PCP_PRIM_INDEX_GRAPHS, "Write graphviz 'dot' files during prim indexing " "(requires PCP_PRIM_INDEX)"); + + TF_DEBUG_ENVIRONMENT_SYMBOL(PCP_NAMESPACE_EDIT, "Pcp namespace edits"); } diff --git a/pxr/usd/lib/pcp/debugCodes.h b/pxr/usd/lib/pcp/debugCodes.h index 49edd2a6c8..cf78605269 100644 --- a/pxr/usd/lib/pcp/debugCodes.h +++ b/pxr/usd/lib/pcp/debugCodes.h @@ -31,7 +31,8 @@ TF_DEBUG_CODES( PCP_CHANGES, PCP_DEPENDENCIES, PCP_PRIM_INDEX, - PCP_PRIM_INDEX_GRAPHS + PCP_PRIM_INDEX_GRAPHS, + PCP_NAMESPACE_EDIT ); diff --git a/pxr/usd/lib/pcp/dependencies.cpp b/pxr/usd/lib/pcp/dependencies.cpp index 59ef47fc67..03c08e37a6 100644 --- a/pxr/usd/lib/pcp/dependencies.cpp +++ b/pxr/usd/lib/pcp/dependencies.cpp @@ -29,312 +29,17 @@ #include "pxr/usd/pcp/cache.h" #include "pxr/usd/pcp/changes.h" #include "pxr/usd/pcp/debugCodes.h" +#include "pxr/usd/pcp/diagnostic.h" #include "pxr/usd/pcp/iterator.h" #include "pxr/usd/pcp/layerStack.h" #include "pxr/usd/pcp/primIndex.h" -#include "pxr/usd/pcp/propertyIndex.h" #include "pxr/usd/sdf/pathTable.h" #include "pxr/usd/sdf/primSpec.h" -#include "pxr/usd/sdf/propertySpec.h" -#include "pxr/base/tracelite/trace.h" #include "pxr/base/tf/diagnostic.h" -#include "pxr/base/tf/mallocTag.h" #include "pxr/base/tf/stl.h" -#include "pxr/base/work/arenaDispatcher.h" -#include -#include -#include -#include #include -template -struct Pcp_DependencyMultisetGetKey -{ - static const T& GetKey(const T& obj) { return obj; } -}; - -// A type for holding an unordered multiset of dependencies. We don't -// need many operations on this type and we expect the number of items in -// it to be small. -// XXX: If this becomes a performance bottleneck this type could -// internally switch to a different data structure when the -// number of elements gets too big. -template > -class Pcp_DependencyMultiset { -private: - typedef std::vector _Data; - -public: - typedef Key key_type; - typedef T value_type; - typedef typename _Data::const_iterator iterator; - typedef typename _Data::const_iterator const_iterator; - - Pcp_DependencyMultiset() { } - ~Pcp_DependencyMultiset() { } - - // Insert another entry for \p value. Order is not maintained. - void Insert(const value_type& value) - { - _data.push_back(value); - } - - // Insert another entry for \p value. Order is not maintained. - template - void Insert(const U& collection) - { - _data.insert(_data.end(), collection.begin(), collection.end()); - } - - // Erase one entry for \p key. - void EraseOne(const key_type& key) - { - TRACE_FUNCTION(); - - typename _Data::iterator j = _data.end(); - typename _Data::iterator i = _data.begin(); - while (i != j) { - if (KeyFn::GetKey(*i) == key) { - // Copy last element over element to remove. - *i = *--j; - - // Remove last element. - _data.erase(j); - break; - } - ++i; - } - } - - void clear() - { - _data.clear(); - } - - void reset() - { - TfReset(_data); - } - - const_iterator begin() const - { - return _data.begin(); - } - - const_iterator end() const - { - return _data.end(); - } - - bool empty() const - { - return _data.empty(); - } - -protected: - _Data &_GetData() - { - return _data; - } - -private: - _Data _data; -}; - -// Specifies a path and whether it is ancestral or direct. -struct Pcp_DependencyPathType { - SdfPath path; - PcpDependencyType dependencyType; -}; - -struct Pcp_DependencyPathTypeKeyFn -{ - static const SdfPath& GetKey(const Pcp_DependencyPathType& obj) - { return obj.path; } -}; - -typedef Pcp_DependencyMultiset< - /* T = */ Pcp_DependencyPathType, - /* Key = */ SdfPath, - /* KeyFn = */ Pcp_DependencyPathTypeKeyFn> Pcp_DependencyPathTypeMultiset; - -// Defines a Pcp_DependencyMultiset of nodes where the key for each -// node is the root node's path. -struct Pcp_NodeKeyFn -{ - static const SdfPath& GetKey(const PcpNodeRef& obj) - { return obj.GetRootNode().GetPath(); } -}; - -typedef Pcp_DependencyMultiset< - /* T = */ PcpNodeRef, - /* Key = */ SdfPath, - /* KeyFn = */ Pcp_NodeKeyFn> Pcp_NodeMultiset; - -class Pcp_LayerStackRefCountMap { -private: - typedef boost::unordered_map _Data; - _Data _data; - -public: - typedef _Data::value_type value_type; - typedef _Data::const_iterator iterator; - typedef _Data::const_iterator const_iterator; - - Pcp_LayerStackRefCountMap() { } - ~Pcp_LayerStackRefCountMap() { } - - bool Has(const PcpLayerStackRefPtr& layerStack) const - { - return TfMapLookupPtr(_data, layerStack) != NULL; - } - - void Insert(const PcpLayerStackRefPtr& layerStack) - { ++(_data[layerStack]); } - - bool EraseOne(const PcpLayerStackRefPtr& layerStack) - { - _Data::iterator it = _data.find(layerStack); - if (TF_VERIFY(it != _data.end())) { - if (TF_VERIFY(it->second > 0)) { - --it->second; - } - - if (it->second == 0) { - _data.erase(it); - } - return true; - } - return false; - } - - void clear() - { - _data.clear(); - } - - void reset() - { - TfReset(_data); - } - - const_iterator begin() const - { - return _data.begin(); - } - - const_iterator end() const - { - return _data.end(); - } - - bool empty() const - { - return _data.empty(); - } -}; - -struct Pcp_DependenciesData { - - ~Pcp_DependenciesData() { - // Tear down in parallel, since these can get big. - WorkArenaDispatcher wd; - wd.Run([this]() { TfReset(sdToPcp); }); - wd.Run([this]() { TfReset(pcpToSd); }); - wd.Run([this]() { TfReset(sitesUsingSite); }); - wd.Run([this]() { TfReset(sitesUsedBySite); }); - wd.Run([this]() { TfReset(spookySdToPcp); }); - wd.Run([this]() { TfReset(spookyPcpToSd); }); - wd.Run([this]() { TfReset(spookySitesUsingSite); }); - wd.Run([this]() { TfReset(spookySitesUsedBySite); }); - wd.Run([this]() { layerStacks.reset(); }); - wd.Run([this]() { sdfSiteNeedsFlush.reset(); }); - wd.Run([this]() { pcpSiteNeedsFlush.reset(); }); - wd.Run([this]() { sdfSpookySiteNeedsFlush.reset(); }); - wd.Run([this]() { pcpSpookySiteNeedsFlush.reset(); }); - wd.Run([this]() { retainedLayerStacks.reset(); }); - wd.Wait(); - } - - // A map of layers to path tables of multisets of nodes. These multisets - // are keyed by Pcp site paths, so ultimately what we have here is a map of - // Sd layer -> Sd path -> Pcp site path -> PcpNode. - // - // This is used to maintain information about what Pcp sites depend on a - // given Sd site, and what node in that Pcp site introduced that dependency. - typedef SdfPathTable PathToNodeMultiset; - typedef boost::unordered_map SdToPcp; - - // A path table of multisets of SdfSites. - typedef Pcp_DependencyMultiset SdfSiteMultiset; - typedef SdfPathTable PcpToSd; - - // A multiset of layer stacks. - typedef Pcp_DependencyMultiset LayerStackMultiset; - - // Table of sites using a site. - typedef SdfPathTable PathToPathTypeMultiset; - typedef boost::unordered_map SitesUsingSite; - - typedef std::pair PcpStackSite; - typedef Pcp_DependencyMultiset PcpSiteMultiset; - typedef SdfPathTable SitesUsedBySite; - - // Handy types. - typedef std::pair PcpToSdRange; - typedef std::pair SitesUsedBySiteRange; - - // A bidirectional map of SdfSite <-> PcpSite path. - SdToPcp sdToPcp; - PcpToSd pcpToSd; - - // A bidirectional map of PcpSite dependencies. - SitesUsingSite sitesUsingSite; - SitesUsedBySite sitesUsedBySite; - - // A bidirectional map of SdfSite <-> PcpSite spooky dependencies. - SdToPcp spookySdToPcp; - PcpToSd spookyPcpToSd; - - // A bidirectional map of PcpSite spooky dependencies. - SitesUsingSite spookySitesUsingSite; - SitesUsedBySite spookySitesUsedBySite; - - // Mapping of all PcpLayerStacks with dependencies registered on them - // to the number of dependencies. This also retains the layer stacks - // to ensure each layer stack's lifetime while a dependency is using it. - Pcp_LayerStackRefCountMap layerStacks; - - // Sd sites that have had Pcp sites removed. Some of these sites may - // be empty, allowing us to remove entries from the maps, but we defer - // doing that to Flush() to allow the client to time the cleanup. - SdfSiteMultiset sdfSiteNeedsFlush; - PcpSiteMultiset pcpSiteNeedsFlush; - - // Same as above except for spooky sites. - SdfSiteMultiset sdfSpookySiteNeedsFlush; - PcpSiteMultiset pcpSpookySiteNeedsFlush; - - // Layer stacks on Pcp sites that have been removed. Some of these - // layer stacks might be released except for being in this multiset. - // Holding them here allows the client to time their release with a - // call to Flush(). - LayerStackMultiset retainedLayerStacks; -}; - -Pcp_Dependencies::Pcp_Dependencies() : - _data(new Pcp_DependenciesData) -{ - // Do nothing -} - -Pcp_Dependencies::Pcp_Dependencies(const Pcp_Dependencies& other) : - _data(new Pcp_DependenciesData(*other._data)) +Pcp_Dependencies::Pcp_Dependencies() { // Do nothing } @@ -344,415 +49,150 @@ Pcp_Dependencies::~Pcp_Dependencies() // Do nothing } -static -std::string -_FormatSite(const SdfSite& sdfSite) -{ - return TfStringPrintf(" @%s@<%s>", - sdfSite.layer->GetIdentifier().c_str(), - sdfSite.path.GetText()); -} - -static -std::string -_FormatSite(const Pcp_DependenciesData::PcpStackSite& pcpStackSite) -{ - return TfStringPrintf(" @%s@<%s>", - pcpStackSite.first->GetIdentifier().rootLayer - ? pcpStackSite.first->GetIdentifier().rootLayer-> - GetIdentifier().c_str() - : "", - pcpStackSite.second.GetText()); -} - -template -static -std::string -_FormatSites(FwdIter first, FwdIter last) -{ - typedef typename FwdIter::value_type T; - std::vector specStrings(std::distance(first, last)); - std::transform(first, last, specStrings.begin(), - (std::string (*)(const T&))_FormatSite); - std::sort(specStrings.begin(), specStrings.end()); - return TfStringJoin(specStrings, "\n"); -} - -inline -void -Pcp_Dependencies::_Add( - const SdfPath& pcpSitePath, - SdfSite sdfSite, const PcpNodeRef& node, - bool spooky) -{ - TfAutoMallocTag2 tag("Pcp", "Pcp_Dependencies:Add SdfSite"); - - // Save the dependency. - Pcp_DependenciesData::SdToPcp& sdToPcp = - (spooky ? _data->spookySdToPcp : _data->sdToPcp); - Pcp_DependenciesData::PcpToSd& pcpToSd = - (spooky ? _data->spookyPcpToSd : _data->pcpToSd); - - sdToPcp[sdfSite.layer][sdfSite.path].Insert(node); - pcpToSd[pcpSitePath].Insert(sdfSite); -} - -void -Pcp_Dependencies::Add( - const SdfPath& pcpSitePath, - const SdfSiteVector& sdfSites, - const PcpNodeRefVector& nodes) -{ - static const bool spooky = true; - - TF_VERIFY(sdfSites.size() == nodes.size()); - if (sdfSites.empty()) { - return; - } - - TfAutoMallocTag2 tag("Pcp", "Pcp_Dependencies"); - - TF_DEBUG(PCP_DEPENDENCIES).Msg( - "Pcp_Dependencies::Add: Adding spec dependencies for path <%s>:\n%s\n", - pcpSitePath.GetText(), - _FormatSites(sdfSites.begin(), sdfSites.end()).c_str()); - - for (size_t i = 0; i < sdfSites.size(); ++i) { - _Add(pcpSitePath, sdfSites[i], nodes[i], not spooky); - } -} - -static -std::string -_FormatDependencies(const PcpPrimIndexDependencies& deps) +// Determine if Pcp_Dependencies should store an entry +// for the arc represented by the given node. +// +// As a space optimization, Pcp_Dependencies does not store entries +// for arcs that are implied by nearby structure and which can +// be easily synthesized. Specifically, it does not store arcs +// introduced purely ancestrally, nor does it store arcs for root nodes +// (PcpDependencyTypeRoot). +inline static bool +_ShouldStoreDependency(PcpDependencyFlags depFlags) { - std::vector depStrings; - TF_FOR_ALL(it, deps.sites) { - const PcpLayerStackSite site(it->first.first, it->first.second); - - depStrings.push_back( - TfStringPrintf(" %s (%s)", - TfStringify(site).c_str(), - TfEnum::GetDisplayName(it->second).c_str())); - } - - std::sort(depStrings.begin(), depStrings.end()); - return TfStringJoin(depStrings, "\n"); + return depFlags & PcpDependencyTypeDirect; } void -Pcp_Dependencies::Add( - const SdfPath& pcpSitePath, - const PcpPrimIndexDependencies& dependencies) +Pcp_Dependencies::Add(const PcpPrimIndex &primIndex) { - if (dependencies.sites.empty()) { + TfAutoMallocTag2 tag("Pcp", "Pcp_Dependencies::Add"); + if (not primIndex.GetRootNode()) { return; } + const SdfPath& primIndexPath = primIndex.GetRootNode().GetPath(); + TF_DEBUG(PCP_DEPENDENCIES) + .Msg("Pcp_Dependencies: Adding deps for index <%s>:\n", + primIndexPath.GetText()); - TfAutoMallocTag2 tag("Pcp", "Pcp_Dependencies"); - TfAutoMallocTag2 tag2("Pcp", "Pcp_Dependencies:Add PcpSite"); - - TF_DEBUG(PCP_DEPENDENCIES).Msg( - "Pcp_Dependencies::Add: Adding site dependencies for path <%s>:\n%s\n", - pcpSitePath.GetText(), - _FormatDependencies(dependencies).c_str()); - - for (const auto& dep : dependencies.sites) { - const PcpPrimIndexDependencies::Site& site = dep.first; - - // Retain the layer stack. - _data->layerStacks.Insert(site.first); - - // Create a struct to insert into the sitesUsingSite table. - Pcp_DependencyPathType curPath; - curPath.path = pcpSitePath; - curPath.dependencyType = dep.second; - - _data->sitesUsingSite[site.first][site.second].Insert(curPath); - _data->sitesUsedBySite[pcpSitePath]. - Insert(Pcp_DependenciesData::PcpStackSite(site.first,site.second)); - } -} + int nodeIndex=0, count=0; + const auto nodeRange = primIndex.GetNodeRange(); + for (auto nodeIter = nodeRange.first; nodeIter != nodeRange.second; + ++nodeIter, ++nodeIndex) + { + const PcpNodeRef &n = *nodeIter; + const PcpDependencyFlags depFlags = PcpClassifyNodeDependency(n); + if (_ShouldStoreDependency(depFlags)) { + _SiteDepMap &siteDepMap = _deps[n.GetLayerStack()]; + std::vector &deps = siteDepMap[n.GetPath()]; -void -Pcp_Dependencies::AddSpookySitesUsedByPrim( - const SdfPath& pcpSitePath, - const SdfSiteVector& spookySites, - const PcpNodeRefVector& spookyNodes) -{ - static const bool spooky = true; + TF_DEBUG(PCP_DEPENDENCIES) + .Msg(" - Node %i (%s %s): <%s> %s\n", + nodeIndex, + PcpDependencyFlagsToString(depFlags).c_str(), + TfEnum::GetDisplayName(n.GetArcType()).c_str(), + n.GetPath().GetText(), + TfStringify(n.GetLayerStack()->GetIdentifier()).c_str()); - TF_VERIFY(spookySites.size() == spookyNodes.size()); - if (spookySites.empty()) { - return; + deps.push_back(primIndexPath); + count++; + } } - - TfAutoMallocTag2 tag("Pcp", "Pcp_Dependencies - spooky"); - - TF_DEBUG(PCP_DEPENDENCIES).Msg( - "Pcp_Dependencies::Add: Adding spooky spec dependencies for path " - "<%s>:\n%s\n", - pcpSitePath.GetText(), - _FormatSites(spookySites.begin(), spookySites.end()).c_str()); - - for (size_t i = 0; i < spookySites.size(); ++i) { - _Add(pcpSitePath, spookySites[i], spookyNodes[i], spooky); + if (count == 0) { + TF_DEBUG(PCP_DEPENDENCIES).Msg(" None\n"); } } void -Pcp_Dependencies::AddSpookySitesUsedByPrim( - const SdfPath& pcpSitePath, - const PcpPrimIndexDependencies& spookyDependencies) +Pcp_Dependencies::Remove(const PcpPrimIndex &primIndex, PcpLifeboat *lifeboat) { - if (spookyDependencies.sites.empty()) { + if (not primIndex.GetRootNode()) { return; } - - TfAutoMallocTag2 tag("Pcp", "Pcp_Dependencies - spooky"); - - TF_DEBUG(PCP_DEPENDENCIES).Msg( - "Pcp_Dependencies::Add: Adding spooky site dependencies for path " - "<%s>:\n%s\n", - pcpSitePath.GetText(), - _FormatDependencies(spookyDependencies).c_str()); - - for (const auto& dep : spookyDependencies.sites) { - const PcpPrimIndexDependencies::Site& site = dep.first; - - // Spooky dependencies do not retain the layer stack. - // This is because spooky dependencies are the result of a - // relocation applied across a different kind of arc, and - // the other arc will already depend on the layer stack. - // - // XXX It might be nice to verify that there is a dependency - // registered on that layerStack here, but would be under - // a different path, so we do not have an easy way to look - // for an entry without scanning the whole table. - - // Create a struct to insert into the sitesUsingSite table. - Pcp_DependencyPathType curPath; - curPath.path = pcpSitePath; - curPath.dependencyType = dep.second; - - _data->spookySitesUsingSite[site.first][site.second].Insert(curPath); - _data->spookySitesUsedBySite[pcpSitePath]. - Insert(Pcp_DependenciesData::PcpStackSite(site.first,site.second)); - } -} - -void -Pcp_Dependencies::Remove( - const SdfPath& pcpSitePath, - PcpLifeboat* lifeboat, - bool specsAtPathOnly) -{ - // This is for debugging output only. - std::vector debugSites; - - // Remove spec dependencies. - { - // Find all Pcp sites to remove. - Pcp_DependenciesData::PcpToSd::iterator i = - _data->pcpToSd.find(pcpSitePath); - Pcp_DependenciesData::PcpToSdRange range(i, i); - if (specsAtPathOnly and i != _data->pcpToSd.end()) { - // Only removing spec dependencies at pcpSitePath. - ++range.second; - } - else { - // Remove all dependencies at and below pcpSitePath. - range.second = range.first.GetNextSubtree(); - } - - // Discard sdToPcp entries, i.e. the entries in the reverse mapping of - // the pcpToSd/sdToPcp bidirectional map. - for (auto valueIter = range.first; valueIter != range.second; ++valueIter) { - const auto& value = *valueIter; - const Pcp_DependenciesData::SdfSiteMultiset& entry = value.second; - if (TfDebug::IsEnabled(PCP_DEPENDENCIES)) { - debugSites.push_back( - TfStringPrintf(" <%s> (spec):", value.first.GetText())); - debugSites.push_back( - _FormatSites(entry.begin(), entry.end())); - } - - // Remove the reverse mapping. - for (const auto& sdfSite : entry) { - _data->sdToPcp[sdfSite.layer][sdfSite.path].EraseOne(value.first); - - // Only mark this Sd site as needing to be flushed if we're - // removing all dependencies at and below pcpSitePath. This is - // because Flush() assumes that it can remove all dependencies - // at and below each site it processes. - if (not specsAtPathOnly) { - _data->sdfSiteNeedsFlush.Insert(sdfSite); + const SdfPath& primIndexPath = primIndex.GetRootNode().GetPath(); + TF_DEBUG(PCP_DEPENDENCIES) + .Msg("Pcp_Dependencies: Removing deps for index <%s>\n", + primIndexPath.GetText()); + + int nodeIndex=0; + const auto nodeRange = primIndex.GetNodeRange(); + for (auto nodeIter = nodeRange.first; nodeIter != nodeRange.second; + ++nodeIter, ++nodeIndex) + { + const PcpNodeRef &n = *nodeIter; + const PcpDependencyFlags depFlags = PcpClassifyNodeDependency(n); + if (not _ShouldStoreDependency(depFlags)) { + continue; + } + + _SiteDepMap &siteDepMap = _deps[n.GetLayerStack()]; + std::vector &deps = siteDepMap[n.GetPath()]; + + TF_DEBUG(PCP_DEPENDENCIES) + .Msg(" - Node %i (%s %s): <%s> %s\n", + nodeIndex, + PcpDependencyFlagsToString(depFlags).c_str(), + TfEnum::GetDisplayName(n.GetArcType()).c_str(), + n.GetPath().GetText(), + TfStringify(n.GetLayerStack()->GetIdentifier()).c_str()); + + // Swap with last element, then remove that. + // We are using the vector as an unordered set. + std::vector::iterator i = + std::find(deps.begin(), deps.end(), primIndexPath); + if (not TF_VERIFY(i != deps.end())) { + continue; + } + std::vector::iterator last = --deps.end(); + std::swap(*i, *last); + deps.erase(last); + + // Reap container entries when no deps are left. + // This is slightly tricky with SdfPathTable since we need + // to examine subtrees and parents. + if (deps.empty()) { + TF_DEBUG(PCP_DEPENDENCIES).Msg(" Removed last dep on site\n"); + + // Scan children to see if we can remove this subtree. + _SiteDepMap::iterator i, iBegin, iEnd; + std::tie(iBegin, iEnd) = siteDepMap.FindSubtreeRange(n.GetPath()); + for (i = iBegin; i != iEnd && i->second.empty(); ++i) {} + bool subtreeIsEmpty = i == iEnd; + if (subtreeIsEmpty) { + siteDepMap.erase(iBegin); + TF_DEBUG(PCP_DEPENDENCIES).Msg(" No subtree deps\n"); + + // Now scan upwards to reap parent entries. + for (SdfPath p = n.GetPath().GetParentPath(); + not p.IsEmpty(); p = p.GetParentPath()) { + std::tie(iBegin, iEnd) = siteDepMap.FindSubtreeRange(p); + if (iBegin != iEnd + and std::next(iBegin) == iEnd + and iBegin->second.empty()) { + TF_DEBUG(PCP_DEPENDENCIES) + .Msg(" Removing empty parent entry <%s>\n", + p.GetText()); + siteDepMap.erase(iBegin); + } else { + break; + } } - } - } - - // Discard pcpToSd sites. - if (range.first != range.second) { - if (specsAtPathOnly) { - TF_VERIFY(std::distance(range.first, range.second) == 1); - range.first->second.clear(); - } - else { - _data->pcpToSd.erase(range.first); - } - } - } - - if (specsAtPathOnly) { - TF_DEBUG(PCP_DEPENDENCIES).Msg( - "Pcp_Dependencies::Remove: Removed dependencies for path <%s>:\n" - "%s\n", - pcpSitePath.GetText(), - TfStringJoin(debugSites, "\n").c_str()); - return; - } - - // Remove spooky spec dependencies. - // We do not do this if specsAtPathOnly is true because that is used - // to rebuild the spec stack after an insignificant change, which - // does not affect spooky dependencies. Also, rebuilding the spec stack - // does not rebuild the spooky spec dependencies, so we need to - // preserve them here. - // - // TODO: Share this code with the above, by refactoring out a - // separate bimap. - { - // Find all spooky Pcp sites to remove. - Pcp_DependenciesData::PcpToSd::iterator i = - _data->spookyPcpToSd.find(pcpSitePath); - Pcp_DependenciesData::PcpToSdRange range(i, i); - if (specsAtPathOnly and i != _data->spookyPcpToSd.end()) { - // Only removing spec dependencies at pcpSitePath. - ++range.second; - } - else { - // Remove all dependencies at and below pcpSitePath. - range.second = range.first.GetNextSubtree(); - } - - // Discard spookySdToPcp entries, i.e. the entries in the - // reverse mapping of the spookyPcpToSd/spookySdToPcp - // bidirectional map. - for (auto valueIter = range.first; valueIter != range.second; ++valueIter) { - const auto& value = *valueIter; - const Pcp_DependenciesData::SdfSiteMultiset& entry = value.second; - if (TfDebug::IsEnabled(PCP_DEPENDENCIES)) { - debugSites.push_back( - TfStringPrintf(" <%s> (spooky spec):", - value.first.GetText())); - debugSites.push_back( - _FormatSites(entry.begin(), entry.end())); - } - - // Remove the reverse mapping. - for (const auto& sdfSite : entry) { - _data->spookySdToPcp[sdfSite.layer][sdfSite.path]. - EraseOne(value.first); - _data->sdfSpookySiteNeedsFlush.Insert(sdfSite); - } - } - - // Discard spookyPcpToSd sites. - if (range.first != range.second) { - if (specsAtPathOnly) { - TF_VERIFY(std::distance(range.first, range.second) == 1); - range.first->second.clear(); - } - else { - _data->spookyPcpToSd.erase(range.first); - } - } - } - - // Remove site dependencies. - { - // Find all sites used by site to remove. - Pcp_DependenciesData::SitesUsedBySiteRange siteRange = - _data->sitesUsedBySite.FindSubtreeRange(pcpSitePath); - // Discard sites using site entries, i.e. the entries in the reverse - // mapping of the PcpSite dependencies bidirectional map. - for (auto valueIter = siteRange.first; valueIter != siteRange.second; - ++valueIter) - { - const auto& value = *valueIter; - if (TfDebug::IsEnabled(PCP_DEPENDENCIES)) { - debugSites.push_back( - TfStringPrintf(" <%s> (site):", - value.first.GetText())); - debugSites.push_back( - _FormatSites(value.second.begin(), value.second.end())); - } - - // Remove the reverse mapping. - for (const auto& pcpSite : value.second) { - _data->sitesUsingSite[pcpSite.first][pcpSite.second]. - EraseOne(value.first); - _data->pcpSiteNeedsFlush.Insert(pcpSite); + // Check if the entire table is empty. + if (siteDepMap.empty()) { + if (lifeboat) { + lifeboat->Retain(n.GetLayerStack()); + } + _deps.erase(n.GetLayerStack()); - // Hold onto layer stacks and remove from count. - PcpLayerStackRefPtr layerStack = pcpSite.first; - if (lifeboat) { - lifeboat->Retain(layerStack); + TF_DEBUG(PCP_DEPENDENCIES) + .Msg(" Removed last dep on %s\n", + TfStringify(n.GetLayerStack() + ->GetIdentifier()).c_str()); } - _data->retainedLayerStacks.Insert(layerStack); - TF_VERIFY(_data->layerStacks.EraseOne(layerStack)); - } - } - - // Discard sites used by site entries. - if (siteRange.first != siteRange.second) { - _data->sitesUsedBySite.erase(siteRange.first); - } - } - - // Remove spooky site dependencies. - { - // Find all spooky sites used by site to remove. - Pcp_DependenciesData::SitesUsedBySiteRange siteRange = - _data->spookySitesUsedBySite.FindSubtreeRange(pcpSitePath); - - // Discard sites using site entries, i.e. the entries in the reverse - // mapping of the PcpSite dependencies bidirectional map. - for (auto valueIter = siteRange.first; valueIter != siteRange.second; - ++valueIter) { - const auto& value = *valueIter; - - if (TfDebug::IsEnabled(PCP_DEPENDENCIES)) { - debugSites.push_back( - TfStringPrintf(" <%s> (spooky site):", - value.first.GetText())); - debugSites.push_back( - _FormatSites(value.second.begin(), value.second.end())); } - - // Remove the reverse mapping. - for (const auto& pcpSite : value.second) { - _data->spookySitesUsingSite[pcpSite.first][pcpSite.second]. - EraseOne(value.first); - _data->pcpSpookySiteNeedsFlush.Insert(pcpSite); - - // Note: We do not retain layer stacks for spooky dependencies, - // so we we do not need to drop a _data->layerStacks entry here. - } - } - - // Discard sites used by site entries. - if (siteRange.first != siteRange.second) { - _data->spookySitesUsedBySite.erase(siteRange.first); } } - - TF_DEBUG(PCP_DEPENDENCIES).Msg( - "Pcp_Dependencies::Remove: Removed dependencies for path <%s>:\n" - "%s\n", - pcpSitePath.GetText(), - TfStringJoin(debugSites, "\n").c_str()); } void @@ -761,522 +201,14 @@ Pcp_Dependencies::RemoveAll(PcpLifeboat* lifeboat) TF_DEBUG(PCP_DEPENDENCIES).Msg( "Pcp_Dependencies::RemoveAll: Clearing all dependencies\n"); - // Collect all of the used layer stacks. - std::set layerStacks; - for (const auto& v : _data->layerStacks) { - layerStacks.insert(v.first); - } - - // Put layer stacks in the lifeboat. + // Retain all layerstacks in the lifeboat. if (lifeboat) { - for (const auto& layerStack : layerStacks) { - lifeboat->Retain(layerStack); + TF_FOR_ALL(i, _deps) { + lifeboat->Retain(i->first); } } - // Put layer stacks in _data->retainedLayerStacks as well. If there's - // no lifeboat this means the client can still time the release of - // the layer stacks using Flush(). - _data->retainedLayerStacks.Insert(layerStacks); - - // Clear all dependencies. - _data->sdToPcp.clear(); - _data->pcpToSd.clear(); - _data->sitesUsingSite.clear(); - _data->sitesUsedBySite.clear(); - _data->spookySdToPcp.clear(); - _data->spookyPcpToSd.clear(); - _data->spookySitesUsingSite.clear(); - _data->spookySitesUsedBySite.clear(); - _data->layerStacks.clear(); - _data->sdfSiteNeedsFlush.clear(); - _data->pcpSiteNeedsFlush.clear(); - _data->sdfSpookySiteNeedsFlush.clear(); - _data->pcpSpookySiteNeedsFlush.clear(); - - // Put back dependencies for the layer stacks in retainedLayerStacks. - // If we don't then Flush() will get upset when calling EraseOne() - // for each layer stack in retainedLayerStacks since there won't be - // an expected entry. - for (const auto& layerStack : _data->retainedLayerStacks) { - _data->layerStacks.Insert(layerStack); - } -} - -void -Pcp_Dependencies::Flush() -{ - typedef Pcp_DependenciesData::PcpStackSite PcpStackSite; - - // These are for debugging output only. - std::vector debugSites; - bool anyFound; - - // Copy multisets to sets -- we only want each site once. Note - // that we may have sites that are descendants of other sites. - // That's okay; see the comment in the loop below. - std::set sdfSites(_data->sdfSiteNeedsFlush.begin(), - _data->sdfSiteNeedsFlush.end()); - std::set pcpSites(_data->pcpSiteNeedsFlush.begin(), - _data->pcpSiteNeedsFlush.end()); - std::set sdfSpookySites(_data->sdfSpookySiteNeedsFlush.begin(), - _data->sdfSpookySiteNeedsFlush.end()); - std::set pcpSpookySites(_data->pcpSpookySiteNeedsFlush.begin(), - _data->pcpSpookySiteNeedsFlush.end()); - - // Done with the flush sets. - _data->sdfSiteNeedsFlush.clear(); - _data->pcpSiteNeedsFlush.clear(); - _data->sdfSpookySiteNeedsFlush.clear(); - _data->pcpSpookySiteNeedsFlush.clear(); - - // Go through Sd sites discarding unused sites and layers. - anyFound = false; - for (const auto& sdfSite : sdfSites) { - // Find the layer. - Pcp_DependenciesData::SdToPcp::iterator i = - _data->sdToPcp.find(sdfSite.layer); - - if (i != _data->sdToPcp.end()) { - Pcp_DependenciesData::PathToNodeMultiset& pathToNodes = i->second; - // We can only remove entire subtrees from an SdfPathTable. While - // this seems to mean we have to check every path in the subtree - // to see if any have dependencies, it does not. It doesn't - // because for a descendant to exist all of its ancestors must - // also exist. If the ancestor doesn't exist then none of its - // descendants exist either. If the ancestor exists then we - // don't care if descendants don't exist (beyond the fact that - // they can use memory unnecessarily). - // - // We iterate through all the sites that need flushing. Some of - // these may be descendants of others and that's okay. We'll - // always check the most ancestral path first (due to the sorting - // of sites). If it's empty we'll remove the entire subtree and - // we'll simply not find the descendants later. If the ancestor - // isn't empty then we'll find the descendant, which itself might - // be empty and we'll remove it. - Pcp_DependenciesData::PathToNodeMultiset::iterator j = - pathToNodes.find(sdfSite.path); - if (j != pathToNodes.end() and j->second.empty()) { - if (TfDebug::IsEnabled(PCP_DEPENDENCIES)) { - if (not anyFound) { - debugSites.push_back(" Sdf to Pcp"); - anyFound = true; - } - debugSites.push_back(_FormatSite(sdfSite) + " (spec)"); - } - pathToNodes.erase(j); - - // If path table is empty we can remove the layer. - if (pathToNodes.empty()) { - if (TfDebug::IsEnabled(PCP_DEPENDENCIES)) { - debugSites.push_back( - TfStringPrintf(" <%s> (spec layer)", - sdfSite.layer->GetIdentifier().c_str())); - } - _data->sdToPcp.erase(i); - } - } - } - } - - // Flush spooky spec dependencies. - anyFound = false; - for (const auto& sdfSite : sdfSpookySites) { - // Find the layer. - const Pcp_DependenciesData::SdToPcp::iterator j = - _data->spookySdToPcp.find(sdfSite.layer); - if (j != _data->spookySdToPcp.end()) { - Pcp_DependenciesData::PathToNodeMultiset& pathToNodes = j->second; - Pcp_DependenciesData::PathToNodeMultiset::iterator k = - pathToNodes.find(sdfSite.path); - if (k != pathToNodes.end() and k->second.empty()) { - if (TfDebug::IsEnabled(PCP_DEPENDENCIES)) { - if (not anyFound) { - debugSites.push_back(" Sdf to Pcp (spooky)"); - anyFound = true; - } - debugSites.push_back(_FormatSite(sdfSite) + " (spooky spec)"); - } - pathToNodes.erase(k); - - // If path table is empty we can remove the layer. - if (pathToNodes.empty()) { - if (TfDebug::IsEnabled(PCP_DEPENDENCIES)) { - debugSites.push_back( - TfStringPrintf(" <%s> (spooky spec layer)", - sdfSite.layer->GetIdentifier().c_str())); - } - _data->spookySdToPcp.erase(j); - } - } - } - } - - // Go through pcpSites discarding unused sites. This is the same - // algorithm as above. - anyFound = false; - for (const auto& pcpSite : pcpSites) { - // Find the layer stack. - Pcp_DependenciesData::SitesUsingSite::iterator i = - _data->sitesUsingSite.find(pcpSite.first); - if (i != _data->sitesUsingSite.end()) { - // Find the site. - Pcp_DependenciesData::PathToPathTypeMultiset& pathToPaths = - i->second; - Pcp_DependenciesData::PathToPathTypeMultiset::iterator j = - pathToPaths.find(pcpSite.second); - if (j != pathToPaths.end() and j->second.empty()) { - // Remove the entry. Remove the layer stack if it has no - // entries anymore. - if (TfDebug::IsEnabled(PCP_DEPENDENCIES)) { - if (not anyFound) { - debugSites.push_back(" Sites using site"); - anyFound = true; - } - debugSites.push_back(_FormatSite(pcpSite) + " (site)"); - } - pathToPaths.erase(j); - if (pathToPaths.empty()) { - if (TfDebug::IsEnabled(PCP_DEPENDENCIES)) { - debugSites.push_back( - TfStringPrintf(" <%s> (site layer stack)", - pcpSite.first->GetIdentifier().rootLayer-> - GetIdentifier().c_str())); - } - _data->sitesUsingSite.erase(i); - } - } - } - } - - // Flush spooky site dependencies. - anyFound = false; - for (const auto& pcpSite : pcpSpookySites) { - const Pcp_DependenciesData::SitesUsingSite::iterator j = - _data->spookySitesUsingSite.find(pcpSite.first); - if (j != _data->spookySitesUsingSite.end()) { - // Find the site. - Pcp_DependenciesData::PathToPathTypeMultiset& pathToPaths = - j->second; - Pcp_DependenciesData::PathToPathTypeMultiset::iterator k = - pathToPaths.find(pcpSite.second); - if (k != pathToPaths.end() and k->second.empty()) { - // Remove the entry. Remove the layer stack if it has no - // entries anymore. - if (TfDebug::IsEnabled(PCP_DEPENDENCIES)) { - if (not anyFound) { - debugSites.push_back(" Sites using site (spooky)"); - anyFound = true; - } - debugSites.push_back(_FormatSite(pcpSite) + " (spooky site)"); - } - pathToPaths.erase(k); - if (pathToPaths.empty()) { - if (TfDebug::IsEnabled(PCP_DEPENDENCIES)) { - debugSites.push_back( - TfStringPrintf(" <%s> (spooky site layer stack)", - pcpSite.first->GetIdentifier().rootLayer-> - GetIdentifier().c_str())); - } - _data->spookySitesUsingSite.erase(j); - } - } - } - } - - TF_DEBUG(PCP_DEPENDENCIES).Msg( - "Pcp_Dependencies::Flush:\n%s\n", - TfStringJoin(debugSites, "\n").c_str()); - - // Release layer stacks. - _data->retainedLayerStacks.clear(); -} - - -// -// Forward declarations for local helpers. -// -static void -Pcp_GetSdToPcpDependencies( - const Pcp_DependenciesData::SdToPcp &sdToPcp, - const SdfSite& sdfSite, - SdfPathVector* pcpSitePaths, - PcpNodeRefVector* sourceNodes); -static void -Pcp_GetSdToPcpDependenciesRecursive( - const Pcp_DependenciesData::SdToPcp &sdToPcp, - const SdfSite& sdfSite, - bool primsOnly, - SdfPathVector* pcpSitePaths, - PcpNodeRefVector* sourceNodes); - -typedef boost::unordered_set _PathSet; -typedef boost::unordered_map _PathMap; -static void -Pcp_Get( - const Pcp_DependenciesData::SitesUsingSite &sitesUsingSite, - _PathSet* result, - const PcpLayerStackPtr& layerStack, - const SdfPath& path, - unsigned int dependencyType); -static void -Pcp_GetRecursive( - const Pcp_DependenciesData::SitesUsingSite &sitesUsingSite, - _PathSet* result, - const PcpLayerStackPtr& layerStack, - const SdfPath& path, - unsigned int dependencyType); - - -SdfPathVector -Pcp_Dependencies::Get( - const SdfLayerHandle& layer, - const SdfPath& path, - bool recursive, - bool primsOnly, - bool spooky, - PcpNodeRefVector* sourceNodes) const -{ - const Pcp_DependenciesData::SdToPcp &sdToPcp = - spooky ? _data->spookySdToPcp : _data->sdToPcp; - - // Find every Pcp site path used by the site. - SdfPathVector result; - if (sourceNodes) { - sourceNodes->clear(); - } - - if (recursive) { - TF_VERIFY(not spooky, - "Spooky dependencies cannot be queried recursively."); - - Pcp_GetSdToPcpDependenciesRecursive( - sdToPcp, SdfSite(layer, path), primsOnly, &result, sourceNodes); - } - else { - TF_VERIFY(primsOnly or not spooky, - "Can only ask for spooky dependencies on prims."); - - Pcp_GetSdToPcpDependencies( - sdToPcp, SdfSite(layer, path), &result, sourceNodes); - } - - return result; -} - -void -Pcp_GetSdToPcpDependencies( - const Pcp_DependenciesData::SdToPcp &sdToPcp, - const SdfSite& sdfSite, - SdfPathVector* pcpSitePaths, - PcpNodeRefVector* sourceNodes) -{ - Pcp_DependenciesData::SdToPcp::const_iterator i = - sdToPcp.find(sdfSite.layer); - if (i != sdToPcp.end()) { - Pcp_DependenciesData::PathToNodeMultiset::const_iterator j = - i->second.find(sdfSite.path); - if (j != i->second.end()) { - TF_FOR_ALL(k, j->second) { - pcpSitePaths->push_back(k->GetRootNode().GetPath()); - if (sourceNodes) { - sourceNodes->push_back(*k); - } - } - } - } -} - -void -Pcp_GetSdToPcpDependenciesRecursive( - const Pcp_DependenciesData::SdToPcp &sdToPcp, - const SdfSite& sdfSite, - bool primsOnly, - SdfPathVector* pcpSitePaths, - PcpNodeRefVector* sourceNodes) -{ - Pcp_DependenciesData::SdToPcp::const_iterator i = - sdToPcp.find(sdfSite.layer); - if (i != sdToPcp.end()) { - typedef Pcp_DependenciesData::PathToNodeMultiset::value_type ValueType; - auto range = i->second.FindSubtreeRange(sdfSite.path); - for (auto valueIter = range.first; valueIter != range.second; ++valueIter) { - const auto& value = *valueIter; - if (not primsOnly or - value.first.IsPrimOrPrimVariantSelectionPath()) { - TF_FOR_ALL(j, value.second) { - pcpSitePaths->push_back(j->GetRootNode().GetPath()); - if (sourceNodes) { - sourceNodes->push_back(*j); - } - } - } - } - } -} - -SdfPathVector -Pcp_Dependencies::Get( - const PcpLayerStackPtr& layerStack, - const SdfPath& path, - unsigned int dependencyType, - bool recursive, - bool spooky) const -{ - _PathSet result; - - const Pcp_DependenciesData::SitesUsingSite &sitesUsingSite = - spooky ? _data->spookySitesUsingSite : _data->sitesUsingSite; - - // Find every Pcp site path using the (layerStack, path) site. - if (recursive) { - Pcp_GetRecursive(sitesUsingSite, &result, layerStack, path, - dependencyType); - } - else { - Pcp_Get(sitesUsingSite, &result, layerStack, path, dependencyType); - } - - return SdfPathVector(result.begin(), result.end()); -} - -static void -Pcp_GetWithType( - _PathSet *result, - const Pcp_DependencyPathTypeMultiset& paths, - unsigned int dependencyType) -{ - for (const auto& curPath : paths) { - // Only include paths that match the specified type. - if (dependencyType & curPath.dependencyType) { - result->insert(curPath.path); - } - } -} - -static void -Pcp_GetAncestral( - _PathSet *result, - const Pcp_DependenciesData::PathToPathTypeMultiset& pathsUsingSite, - const SdfPath& originalPath) -{ - // Walk up the tree collecting ancestral dependencies. We don't care - // about the dependencyType because we only get here if ancestral was - // requested and we want any kind of dependency on ancestors. - // XXX: This is probably failing to account for relocations in - // the path translation. - SdfPath path = originalPath.GetParentPath(); - while (path.IsPrimOrPrimVariantSelectionPath()) { - Pcp_DependenciesData::PathToPathTypeMultiset::const_iterator j = - pathsUsingSite.find(path); - if (j != pathsUsingSite.end()) { - for (const auto& curPath : j->second) { - result->insert(originalPath - .ReplacePrefix(path, curPath.path) - .StripAllVariantSelections()); - } - } - path = path.GetParentPath(); - } -} - -void -Pcp_Get( - const Pcp_DependenciesData::SitesUsingSite &sitesUsingSite, - _PathSet* result, - const PcpLayerStackPtr& layerStack, - const SdfPath& path, - unsigned int dependencyType) -{ - Pcp_DependenciesData::SitesUsingSite::const_iterator i = - sitesUsingSite.find(layerStack); - if (i != sitesUsingSite.end()) { - Pcp_DependenciesData::PathToPathTypeMultiset::const_iterator j = - i->second.find(path); - if (j != i->second.end()) { - Pcp_GetWithType(result, j->second, dependencyType); - } - - // If we're requesting ancestral dependencies then check ancestors - // for any dependencies we don't have. - // XXX: There seems to be some inconsistency whether we store - // ancestral dependencies or now. We should either have - // them all or have none of them. - if (dependencyType & PcpAncestral) { - Pcp_GetAncestral(result, i->second, path); - } - } -} - -void -Pcp_GetRecursive( - const Pcp_DependenciesData::SitesUsingSite &sitesUsingSite, - _PathSet* result, - const PcpLayerStackPtr& layerStack, - const SdfPath& path, - unsigned int dependencyType) -{ - Pcp_DependenciesData::SitesUsingSite::const_iterator i = - sitesUsingSite.find(layerStack); - if (i != sitesUsingSite.end()) { - Pcp_DependenciesData::PathToPathTypeMultiset::const_iterator j = - i->second.find(path); - if (j != i->second.end()) { - // Get dependencies for the whole subtree. - Pcp_DependenciesData::PathToPathTypeMultiset::const_iterator k = - j.GetNextSubtree(); - for (; j != k; ++j) { - Pcp_GetWithType(result, j->second, dependencyType); - } - } - - // If we're requesting ancestral dependencies then check ancestors - // for any dependencies we don't have. - // XXX: There seems to be some inconsistency whether we store - // ancestral dependencies or now. We should either have - // them all or have none of them. - if (dependencyType & PcpAncestral) { - Pcp_GetAncestral(result, i->second, path); - } - } -} - -SdfLayerHandleSet -Pcp_Dependencies::GetLayersUsedByPrim(const SdfPath& path, - bool recursive) const -{ - typedef Pcp_DependenciesData::SitesUsedBySite::value_type ValueType; - - // Get layer stacks. - std::set layerStacks; - if (recursive) { - auto range = _data->sitesUsedBySite.FindSubtreeRange(path); - for (auto valueIter = range.first; valueIter != range.second; ++valueIter) { - const auto& value = *valueIter; - for (const auto& site : value.second) { - layerStacks.insert(site.first); - } - } - } - else { - Pcp_DependenciesData::SitesUsedBySite::const_iterator i = - _data->sitesUsedBySite.find(path); - if (i != _data->sitesUsedBySite.end()) { - for (const auto& site : i->second) { - layerStacks.insert(site.first); - } - } - } - - // Get layers. - SdfLayerHandleSet layers; - for (const auto& layerStack : layerStacks) { - const SdfLayerRefPtrVector& localLayers = layerStack->GetLayers(); - layers.insert(localLayers.begin(), localLayers.end()); - } - - return layers; + _deps.clear(); } SdfLayerHandleSet @@ -1284,8 +216,8 @@ Pcp_Dependencies::GetUsedLayers() const { SdfLayerHandleSet reachedLayers; - for (const auto& v : _data->layerStacks) { - const SdfLayerRefPtrVector& layers = v.first->GetLayers(); + TF_FOR_ALL(layerStack, _deps) { + const SdfLayerRefPtrVector& layers = layerStack->first->GetLayers(); reachedLayers.insert(layers.begin(), layers.end()); } @@ -1297,9 +229,9 @@ Pcp_Dependencies::GetUsedRootLayers() const { SdfLayerHandleSet reachedRootLayers; - for (const auto& v : _data->layerStacks) { - const PcpLayerStackPtr& layerStack = v.first; - reachedRootLayers.insert(layerStack->GetIdentifier().rootLayer); + TF_FOR_ALL(i, _deps) { + const PcpLayerStackPtr& layerStack = i->first; + reachedRootLayers.insert(layerStack->GetIdentifier().rootLayer ); } return reachedRootLayers; @@ -1308,293 +240,5 @@ Pcp_Dependencies::GetUsedRootLayers() const bool Pcp_Dependencies::UsesLayerStack(const PcpLayerStackPtr& layerStack) const { - return _data->layerStacks.Has(layerStack); -} - -// -// Debugging -// - -template -struct Pcp_DependenciesTupleTraits { -}; - -template <> -struct Pcp_DependenciesTupleTraits { - static const char* GetIdentifier(const SdfLayerHandle& a) - { - return a->GetIdentifier().c_str(); - } - - static const char* GetForwardLabel() - { - return "Sdf to Pcp"; - } - - static const char* GetReverseLabel() - { - return "Pcp to Sdf"; - } -}; - -template <> -struct Pcp_DependenciesTupleTraits { - static const char* GetIdentifier(const PcpLayerStackPtr& a) - { - return a->GetIdentifier().rootLayer->GetIdentifier().c_str(); - } - - static const char* GetForwardLabel() - { - return "Sites using site"; - } - - static const char* GetReverseLabel() - { - return "Sites used by site"; - } -}; - -template -struct Pcp_DependenciesTuple { - T a; SdfPath b; SdfPath c; - - Pcp_DependenciesTuple() { } - Pcp_DependenciesTuple(T a_, SdfPath b_, SdfPath c_) : - a(a_), b(b_), c(c_) { } - - bool operator<(const Pcp_DependenciesTuple& x) const - { - if (a < x.a) return true; - if (x.a < a) return false; - if (b < x.b) return true; - if (x.b < b) return false; - if (c < x.c) return true; - if (x.c < c) return false; - return false; - } - - struct ReverseLess { - bool operator()(const Pcp_DependenciesTuple& x, - const Pcp_DependenciesTuple& y) const - { - if (x.c < y.c) return true; - if (y.c < x.c) return false; - if (x.b < y.b) return true; - if (y.b < x.b) return false; - if (x.a < y.a) return true; - if (y.a < x.a) return false; - return false; - } - }; - - const char* GetIdentifier() const - { - return Pcp_DependenciesTupleTraits::GetIdentifier(a); - } - - static const char* GetForwardLabel() - { - return Pcp_DependenciesTupleTraits::GetForwardLabel(); - } - - static const char* GetReverseLabel() - { - return Pcp_DependenciesTupleTraits::GetReverseLabel(); - } -}; -typedef Pcp_DependenciesTuple Pcp_DependenciesSpecTuple; -typedef Pcp_DependenciesTuple Pcp_DependenciesSiteTuple; - -template -static void -_DumpDependencies( - std::ostream& s, - const char* prefix, - const std::multiset& fwd, - const std::multiset& tmpRev) -{ - T prev; - - // Print forward dependencies. - if (not fwd.empty()) { - s << prefix << T::GetForwardLabel() << ":" << std::endl; - for (const auto& x : fwd) { - if (prev.a != x.a) { - prev.a = x.a; - s << " @" << x.GetIdentifier() << "@:" << std::endl; - } - if (prev.b != x.b) { - prev.b = x.b; - s << " <" << x.b.GetText() << ">:" << std::endl; - } - s << " <" << x.c.GetText() << ">" << std::endl; - } - } - - // Get reverse in reverse sorted order - std::multiset rev(tmpRev.begin(), tmpRev.end()); - - // Print reverse dependencies. - if (not rev.empty()) { - prev = T(); - s << prefix << T::GetReverseLabel() << ":" << std::endl; - for (const auto& x : rev) { - if (prev.c != x.c) { - prev.c = x.c; - s << " <" << x.c.GetText() << ">:" << std::endl; - } - if (prev.b != x.b) { - prev.b = x.b; - s << " <" << x.b.GetText() << ">" << std::endl; - } - s << " @" << x.GetIdentifier() << "@" << std::endl; - } - } -} - -template -static void -_DiscardMatches(std::multiset* fwd, std::multiset* rev) -{ - typedef typename std::multiset::iterator iterator; - - for (iterator i = rev->begin(); i != rev->end(); ) { - iterator j = fwd->find(*i); - if (j != fwd->end()) { - fwd->erase(j); - rev->erase(i++); - } - else { - ++i; - } - } -} - -static -void -_GetDependencies( - const Pcp_DependenciesData::SdToPcp& fwdInput, - const Pcp_DependenciesData::PcpToSd& revInput, - std::multiset* fwd, - std::multiset* rev) -{ - typedef Pcp_DependenciesData DD; - - fwd->clear(); - rev->clear(); - - for (const auto& x : fwdInput) { - for (const auto& y : x.second) { - for (const auto& z : y.second) { - fwd->insert(Pcp_DependenciesSpecTuple( - x.first, y.first, z.GetRootNode().GetPath())); - } - } - } - - for (const auto& x : revInput) { - for (const auto& y : x.second) { - rev->insert(Pcp_DependenciesSpecTuple(y.layer, y.path, x.first)); - } - } -} - -static -void -_GetDependencies( - const Pcp_DependenciesData::SitesUsingSite& fwdInput, - const Pcp_DependenciesData::SitesUsedBySite& revInput, - std::multiset* fwd, - std::multiset* rev) -{ - typedef Pcp_DependenciesData DD; - - fwd->clear(); - rev->clear(); - - for (const auto& x : fwdInput) { - for (const auto& y : x.second) { - for (const auto& z : y.second) { - fwd->insert(Pcp_DependenciesSiteTuple(x.first, y.first,z.path)); - } - } - } - - for (const auto& x : revInput) { - for (const auto& y : x.second) { - rev->insert(Pcp_DependenciesSiteTuple(y.first, y.second, x.first)); - } - } -} - -void -Pcp_Dependencies::DumpDependencies(std::ostream& s) const -{ - { - std::multiset fwd, rev; - - _GetDependencies(_data->sdToPcp, _data->pcpToSd, &fwd, &rev); - _DumpDependencies(s, "", fwd, rev); - - _GetDependencies(_data->spookySdToPcp, _data->spookyPcpToSd, - &fwd, &rev); - _DumpDependencies(s, "spooky", fwd, rev); - } - - { - std::multiset fwd, rev; - _GetDependencies(_data->sitesUsingSite, _data->sitesUsedBySite, - &fwd, &rev); - _DumpDependencies(s, "", fwd, rev); - - _GetDependencies(_data->spookySitesUsingSite, - _data->spookySitesUsedBySite, - &fwd, &rev); - _DumpDependencies(s, "spooky", fwd, rev); - } -} - -std::string -Pcp_Dependencies::DumpDependencies() const -{ - std::stringstream ss; - DumpDependencies(ss); - return ss.str(); -} - -void -Pcp_Dependencies::CheckInvariants() const -{ - bool fail = false; - - { - std::multiset fwd, rev; - _GetDependencies(_data->sdToPcp, _data->pcpToSd, &fwd, &rev); - _DiscardMatches(&fwd, &rev); - _DumpDependencies(std::cerr, "ERROR: no match in ", fwd, rev); - fail = fail or not fwd.empty() or not rev.empty(); - - _GetDependencies(_data->spookySdToPcp, _data->spookyPcpToSd, &fwd,&rev); - _DiscardMatches(&fwd, &rev); - _DumpDependencies(std::cerr, "ERROR: no match in spooky ", fwd, rev); - fail = fail or not fwd.empty() or not rev.empty(); - } - { - std::multiset fwd, rev; - _GetDependencies(_data->sitesUsingSite, _data->sitesUsedBySite, - &fwd, &rev); - _DiscardMatches(&fwd, &rev); - _DumpDependencies(std::cerr, "ERROR: no match in ", fwd, rev); - fail = fail or not fwd.empty() or not rev.empty(); - - _GetDependencies(_data->spookySitesUsingSite, - _data->spookySitesUsedBySite, - &fwd, &rev); - _DiscardMatches(&fwd, &rev); - _DumpDependencies(std::cerr, "ERROR: no match in spooky ", fwd, rev); - fail = fail or not fwd.empty() or not rev.empty(); - } - - TF_VERIFY(not fail); + return _deps.find(layerStack) != _deps.end(); } diff --git a/pxr/usd/lib/pcp/dependencies.h b/pxr/usd/lib/pcp/dependencies.h index abc57109b1..325649554d 100644 --- a/pxr/usd/lib/pcp/dependencies.h +++ b/pxr/usd/lib/pcp/dependencies.h @@ -26,12 +26,19 @@ /// \file pcp/dependencies.h +#include "pxr/usd/pcp/node.h" #include "pxr/usd/pcp/node.h" #include "pxr/usd/pcp/types.h" +#include "pxr/usd/pcp/layerStack.h" +#include "pxr/usd/pcp/layerStackRegistry.h" +#include "pxr/usd/pcp/primIndex.h" +#include "pxr/usd/pcp/cache.h" #include "pxr/usd/sdf/layer.h" #include "pxr/usd/sdf/path.h" #include "pxr/usd/sdf/site.h" +#include #include +#include #include #include @@ -42,127 +49,80 @@ TF_DECLARE_WEAK_PTRS(PcpLayerStack); /// \class Pcp_Dependencies /// -/// Track dependencies between Sdf sites and Pcp sites. -/// -/// This object keeps track of which Pcp sites depend on which Sdf sites. -/// Clients can provide a collection of Sdf sites and get back a collection -/// of Pcp sites that use those Sdf sites. -/// -/// Relocations can introduce dependencies on prims which are not namespace -/// ancestors. These are known as "spooky" dependencies because of their -/// non-local effect. For an example, see the TrickySpookyVariantSelection -/// museum case: the relocated anim scopes have a spooky dependency on the -/// rig scope from under which they were relocated. We track spooky -/// dependencies separately because they do not contribute directly to -/// a computed prim index the way normal dependencies do, so they -/// require special handling. +/// Tracks the dependencies of PcpPrimIndex entries in a PcpCache. +/// This is an internal class only meant for use by PcpCache. /// class Pcp_Dependencies : boost::noncopyable { public: /// Construct with no dependencies. Pcp_Dependencies(); - Pcp_Dependencies(const Pcp_Dependencies&); - ~Pcp_Dependencies(); - /// \name Adding - /// @{ - - /// Records dependencies between \p pcpSitePath and the sites \p sdfSites. - /// For each site in \p sdfSites, the corresponding node in \p nodes - /// indicates the node in the prim index for \p pcpSitePath from which - /// the spec originated. - void Add(const SdfPath& pcpSitePath, - const SdfSiteVector& sdfSites, const PcpNodeRefVector& nodes); - - /// Records dependencies between \p pcpSitePath and the sites in - /// \p dependencies. - void Add(const SdfPath& pcpSitePath, - const PcpPrimIndexDependencies& dependencies); - - /// Records spooky dependencies between \p pcpSitePath and the - /// collection of specs in \p spookySpecs. For each spec in \p spookySpecs, - /// the corresponding node in \p nodes indicates the node in the prim index - /// for \p pcpSitePath from which the spec originated. - void AddSpookySitesUsedByPrim(const SdfPath& pcpSitePath, - const SdfSiteVector& spookySites, - const PcpNodeRefVector& spookyNodes); - - /// Records spooky dependencies between \p pcpSitePath and the sites in - /// \p deps. - void AddSpookySitesUsedByPrim(const SdfPath& pcpSitePath, - const PcpPrimIndexDependencies& deps); - - /// @} - /// \name Removing + /// \name Registration /// @{ - /// Remove all recorded dependencies (including spooky dependencies) - /// for the site at \p pcpSitePath and all descendant sites. This is - /// used when the Pcp graph may have changed for \p pcpSitePath. That - /// implies that the graph may have changed for any descendant. Any - /// layer stacks used by the site are added to \p lifeboat, if not - /// \c NULL. + /// Add dependency information for the given PcpPrimIndex. /// - /// If \p specsAtPathOnly is \c true then this only removes - /// non-spooky dependencies due to specs and only those at - /// \p pcpSitePath (not descendants). - void Remove(const SdfPath& pcpSitePath, PcpLifeboat* lifeboat, - bool specsAtPathOnly = false); + /// Assumptions: + /// - A computed prim index will be added exactly once + /// - Parent indices will be added before children + void Add(const PcpPrimIndex &primIndex); + + /// Remove dependency information for the given PcpPrimIndex. + /// Any layer stacks in use by any site are added to \p lifeboat, + /// if not \c NULL. + /// + /// Assumptions: + /// - The prim index has previously been added exactly once + void Remove(const PcpPrimIndex &primIndex, PcpLifeboat *lifeboat); /// Remove all dependencies. Any layer stacks in use by any site are - /// added to \p lifeboat, if not \c NULL. This method implicitly calls - /// \c Flush(). + /// added to \p lifeboat, if not \c NULL. void RemoveAll(PcpLifeboat* lifeboat); - /// Releases any layer stacks that no longer have any dependencies. - void Flush(); - /// @} /// \name Queries /// @{ - /// Returns the path of every \c PcpSite that uses the spec in \p layer - /// at \p path. If \p recursive is \c true then also returns the path - /// of every \c PcpSite that uses any descendant of \p path. If - /// \p primsOnly is \c true then recursion is limited to prim descendants. - /// If \p spooky is \c true then spooky dependencies will be returned - /// instead of normal dependencies. + /// Invokes \p fn for every \c PcpPrimIndex that uses + /// the site represented by (siteLayerStack, sitePath). /// - /// If \p sourceNodes is not \c NULL then it has elements corresponding - /// to the elements in the returned vector. If the vector returned from - /// this function is called pcpSites, then sourceNodes[i] is the node - /// in the prim index for pcpSites[i] that introduced the dependency - /// on the spec at \p layer and \p path. + /// The arguments to \p fn are: (depIndexPath, depSitePath). + /// + /// If \p recurse is \c true, then also runs the callback + /// of every \c PcpSite that uses any descendant of \p path. + /// depSitePath provides the descendent dependency path. /// - /// If \p spooky is \c true then spooky dependencies will be returned - /// instead of normal dependencies. - SdfPathVector Get(const SdfLayerHandle& layer, - const SdfPath& path, - bool recursive = false, - bool primsOnly = false, - bool spooky = false, - PcpNodeRefVector* sourceNodes = NULL) const; - - /// Returns the path of every \c PcpSite that uses the site given by - /// \p layerStack and \p path, via a dependency specified by - /// \p dependencyType. \p dependencyType is a bitwise-OR of - /// \c PcpDependencyType enum values. If \p recursive is \c true, - /// then we return the path of every \c PcpSite that uses any descendant - /// of \p path, via a dependency specified by \p dependencyType. - /// If \p spooky is \c true then spooky dependencies will be returned - /// instead of normal dependencies. - SdfPathVector Get(const PcpLayerStackPtr& layerStack, - const SdfPath& path, - unsigned int dependencyType, - bool recursive = false, - bool spooky = false) const; - - /// Returns every layer that the prim at \p path depends on. - /// If \p recursive is \c true then also returns every layer that any - /// descendant of \p path depends on. - SdfLayerHandleSet GetLayersUsedByPrim(const SdfPath& path, - bool recursive = false) const; + /// If \p recurse is \c false, depSitePath is always + /// the sitePath supplied and can be ignored. + template + void + ForEachDependencyOnSite( const PcpLayerStackPtr &siteLayerStack, + const SdfPath &sitePath, + bool recurse, + const FN &fn ) const + { + _LayerStackDepMap::const_iterator i = _deps.find(siteLayerStack); + if (i == _deps.end()) { + return; + } + const _SiteDepMap & siteDepMap = i->second; + if (recurse) { + BOOST_FOREACH(const _SiteDepMap::value_type& entry, + siteDepMap.FindSubtreeRange(sitePath)) { + for(const SdfPath &primIndexPath: entry.second) { + fn(primIndexPath, entry.first); + } + } + } else { + _SiteDepMap::const_iterator j = siteDepMap.find(sitePath); + if (j != siteDepMap.end()) { + for(const SdfPath &primIndexPath: j->second) { + fn(primIndexPath, sitePath); + } + } + } + } /// Returns all layers from all layer stacks with dependencies recorded /// against them. @@ -177,27 +137,112 @@ class Pcp_Dependencies : boost::noncopyable { bool UsesLayerStack(const PcpLayerStackPtr& layerStack) const; /// @} - /// \name Debugging - /// @{ - - /// Write the dependencies to \p s. - void DumpDependencies(std::ostream& s) const; - - /// Returns a string containing the dependencies. - std::string DumpDependencies() const; - - /// Verify that the internal data structures are consistent. - void CheckInvariants() const; - - /// @} - -private: - void _Add( - const SdfPath& pcpSitePath, SdfSite sdSite, const PcpNodeRef& node, - bool spooky); private: - boost::scoped_ptr _data; + // Map of site paths to dependencies, as cache paths. Stores cache + // paths as an unordered vector: for our datasets this is both more + // compact and faster than std::set. + typedef SdfPathTable _SiteDepMap; + + // Map of layery stacks to dependencies on that layerStack. + // Retains references to those layer stacks, which in turn + // retain references to their constituent layers. + typedef boost::unordered_map + _LayerStackDepMap; + + _LayerStackDepMap _deps; }; +template +static void +Pcp_ForEachDependentNode( const SdfPath &sitePath, + const SdfLayerHandle &layer, + const SdfPath &depIndexPath, + const PcpCache &cache, + const FN &fn ) +{ + PcpNodeRef nodeUsingSite; + + // Walk up as needed to find a containing prim index. + SdfPath indexPath; + const PcpPrimIndex *primIndex = nullptr; + for (indexPath = depIndexPath.GetAbsoluteRootOrPrimPath(); + indexPath != SdfPath(); + indexPath = indexPath.GetParentPath()) + { + primIndex = cache.FindPrimIndex(indexPath); + if (primIndex) { + break; + } + } + if (primIndex) { + // Find which node corresponds to (layer, oldPath). + TF_FOR_ALL(node, primIndex->GetNodeRange()) { + const PcpDependencyFlags flags = PcpClassifyNodeDependency(*node); + if (flags != PcpDependencyTypeNone && + node->GetLayerStack()->HasLayer(layer) && + sitePath.HasPrefix(node->GetPath())) + { + nodeUsingSite = *node; + fn(depIndexPath, nodeUsingSite, flags); + } + } + } + + TF_VERIFY( + nodeUsingSite, + "Unable to find node that introduced dependency on site " + "<%s>@%s@ for prim <%s>", + sitePath.GetText(), + layer->GetIdentifier().c_str(), + depIndexPath.GetText()); +} + +template +static void +Pcp_ForEachDependentNode( const SdfPath &sitePath, + const PcpLayerStackPtr &layerStack, + const SdfPath &depIndexPath, + const PcpCache &cache, + const FN &fn ) +{ + PcpNodeRef nodeUsingSite; + + // Walk up as needed to find a containing prim index. + SdfPath indexPath; + const PcpPrimIndex *primIndex = nullptr; + for (indexPath = depIndexPath.GetAbsoluteRootOrPrimPath(); + indexPath != SdfPath(); + indexPath = indexPath.GetParentPath()) + { + primIndex = cache.FindPrimIndex(indexPath); + if (primIndex) { + break; + } + } + if (primIndex) { + // Find which node corresponds to (layerStack, oldPath). + TF_FOR_ALL(node, primIndex->GetNodeRange()) { + const PcpDependencyFlags flags = PcpClassifyNodeDependency(*node); + if (flags != PcpDependencyTypeNone && + node->GetLayerStack() == layerStack && + sitePath.HasPrefix(node->GetPath())) + { + nodeUsingSite = *node; + fn(depIndexPath, nodeUsingSite, flags); + } + } + } + + TF_VERIFY( + nodeUsingSite, + "Unable to find node that introduced dependency on site " + "<%s>%s for prim <%s> in %s", + sitePath.GetText(), + TfStringify(layerStack->GetIdentifier()).c_str(), + depIndexPath.GetText(), + TfStringify(cache.GetLayerStack()->GetIdentifier()).c_str() + ); +} + #endif diff --git a/pxr/usd/lib/pcp/dependency.cpp b/pxr/usd/lib/pcp/dependency.cpp new file mode 100644 index 0000000000..a968cc6b80 --- /dev/null +++ b/pxr/usd/lib/pcp/dependency.cpp @@ -0,0 +1,142 @@ +// +// 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. +// +/// \file Dependency.cpp + +#include "pxr/usd/pcp/dependency.h" +#include "pxr/usd/pcp/node.h" +#include "pxr/usd/pcp/types.h" +#include "pxr/base/tf/enum.h" + +TF_REGISTRY_FUNCTION(TfEnum) +{ + TF_ADD_ENUM_NAME(PcpDependencyTypeNone, "non-dependency"); + TF_ADD_ENUM_NAME(PcpDependencyTypeRoot, "root dependency"); + TF_ADD_ENUM_NAME(PcpDependencyTypePurelyDirect, "purely-direct dependency"); + TF_ADD_ENUM_NAME(PcpDependencyTypePartlyDirect, "partly-direct dependency"); + TF_ADD_ENUM_NAME(PcpDependencyTypeDirect, "direct dependency"); + TF_ADD_ENUM_NAME(PcpDependencyTypeAncestral, "ancestral dependency"); + TF_ADD_ENUM_NAME(PcpDependencyTypeVirtual, "virtual dependency"); + TF_ADD_ENUM_NAME(PcpDependencyTypeNonVirtual, "non-virtual dependency"); + TF_ADD_ENUM_NAME(PcpDependencyTypeAnyNonVirtual, + "any non-virtual dependency"); + TF_ADD_ENUM_NAME(PcpDependencyTypeAnyIncludingVirtual, "any dependency"); +} + +PcpDependencyFlags +PcpClassifyNodeDependency(const PcpNodeRef &node) +{ + if (node.GetArcType() == PcpArcTypeRoot) { + return PcpDependencyTypeRoot; + } + + int flags = 0; + + // Inert nodes can represent virtual dependencies even though + // they do not contribute the scene description at their site. + // + // Examples: + // - relocates + // - arcs whose target prims are (currently) private + // - references/payloads without a prim or defaultPrim + // + // Tracking these dependencies is crucial for procedssing scene + // edits in the presence of spooky ancestral opinions, and for + // edits that resolve the condition causing the node to be inert, + // such as permissions. + // + if (node.IsInert()) { + switch(node.GetArcType()) { + case PcpArcTypeLocalInherit: + case PcpArcTypeGlobalInherit: + case PcpArcTypeLocalSpecializes: + case PcpArcTypeGlobalSpecializes: + // Special case: inert, propagated class-based arcs do not + // represent dependencies. + if (node.GetOriginNode() != node.GetParentNode()) { + return PcpDependencyTypeNone; + } + // Fall through. + default: + flags |= PcpDependencyTypeVirtual; + } + } + + // Classify as ancestral or direct: if there is any non-ancestral + // arc in the path to the root node, the node is considered a + // direct dependency. + bool anyDirect = false; + bool anyAncestral = false; + for (PcpNodeRef p = node; p.GetParentNode(); p = p.GetParentNode()) { + if (p.IsDueToAncestor()) { + anyAncestral = true; + } else { + anyDirect = true; + } + } + if (anyDirect) { + if (anyAncestral) { + flags |= PcpDependencyTypePartlyDirect; + } else { + flags |= PcpDependencyTypePurelyDirect; + } + } else { + if (anyAncestral) { + flags |= PcpDependencyTypeAncestral; + } + } + + if (!(flags & PcpDependencyTypeVirtual)) { + flags |= PcpDependencyTypeNonVirtual; + } + + return flags; +} + +std::string +PcpDependencyFlagsToString(const PcpDependencyFlags depFlags) +{ + std::set tags; + if (depFlags == PcpDependencyTypeNone) { + tags.insert("none"); + } + if (depFlags == PcpDependencyTypeRoot) { + tags.insert("root"); + } + if (depFlags & PcpDependencyTypePurelyDirect) { + tags.insert("purely-direct"); + } + if (depFlags & PcpDependencyTypePartlyDirect) { + tags.insert("partly-direct"); + } + if (depFlags & PcpDependencyTypeAncestral) { + tags.insert("ancestral"); + } + if (depFlags & PcpDependencyTypeVirtual) { + tags.insert("virtual"); + } + if (depFlags & PcpDependencyTypeNonVirtual) { + tags.insert("non-virtual"); + } + return TfStringJoin(tags, ", "); +} diff --git a/pxr/usd/lib/pcp/dependency.h b/pxr/usd/lib/pcp/dependency.h new file mode 100644 index 0000000000..9cab36a430 --- /dev/null +++ b/pxr/usd/lib/pcp/dependency.h @@ -0,0 +1,131 @@ +// +// 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 PCP_DEPENDENCY_H +#define PCP_DEPENDENCY_H + +#include "pxr/usd/pcp/mapFunction.h" +#include "pxr/usd/sdf/path.h" +#include + +class PcpNodeRef; + +/// \enum PcpDependencyType +/// +/// A classification of PcpPrimIndex->PcpSite dependencies +/// by composition structure. +/// +enum PcpDependencyType { + /// No type of dependency. + PcpDependencyTypeNone = 0, + + /// The root dependency of a cache on its root site. + /// This may be useful to either include, as when invalidating + /// caches in response to scene edits, or to exclude, as when + /// scanning dependency arcs to compensate for a namespace edit. + PcpDependencyTypeRoot = (1 << 0), + + /// Purely direct dependencies involve only arcs introduced + /// directly at this level of namespace. + PcpDependencyTypePurelyDirect = (1 << 1), + + /// Partly direct dependencies involve at least one arc introduced + /// directly at this level of namespace; they may also involve + /// ancestral arcs along the chain as well. + PcpDependencyTypePartlyDirect = (1 << 2), + + /// Ancestreal dependencies involve only arcs from ancestral + /// levels of namespace, and no direct arcs. + PcpDependencyTypeAncestral = (1 << 3), + + /// Virtual dependencies do not contribute scene description, + /// yet represent sites whose scene description (or ancestral + /// scene description) informed the structure of the cache. + /// + /// One case of this is when a reference or payload arc + /// does not specify a prim, and the target layerStack does + /// not provide defaultPrim metadata either. In that case + /// a virtual dependency to the root of that layer stack will + /// represent the latent dependency on that site's metadata. + /// + /// Another case of this is "spooky ancestral" dependencies from + /// relocates. These are referred to as "spooky" dependencies + /// because they can be seen as a form of action-at-a-distance. They + /// only occur as a result of relocation arcs. + PcpDependencyTypeVirtual = (1 << 4), + PcpDependencyTypeNonVirtual = (1 << 5), + + /// Combined mask value representing both pure and partly direct + /// deps. + PcpDependencyTypeDirect = + PcpDependencyTypePartlyDirect + | PcpDependencyTypePurelyDirect, + + /// Combined mask value representing any kind of dependency, + /// except virtual ones. + PcpDependencyTypeAnyNonVirtual = + PcpDependencyTypeRoot + | PcpDependencyTypeDirect + | PcpDependencyTypeAncestral + | PcpDependencyTypeNonVirtual, + + /// Combined mask value representing any kind of dependency. + PcpDependencyTypeAnyIncludingVirtual = + PcpDependencyTypeAnyNonVirtual + | PcpDependencyTypeVirtual, +}; + +/// A typedef for a bitmask of flags from PcpDependencyType. +typedef unsigned int PcpDependencyFlags; + +/// Description of a dependency. +struct PcpDependency { + /// The path in this PcpCache's root layer stack that depends + /// on the site. + SdfPath indexPath; + /// The site path. When using recurseDownNamespace, this may + /// be a path beneath the initial sitePath. + SdfPath sitePath; + /// The map function that applies to values from the site. + PcpMapFunction mapFunc; + + bool operator==(const PcpDependency &rhs) const { + return indexPath == rhs.indexPath && + sitePath == rhs.sitePath && + mapFunc == rhs.mapFunc; + } + bool operator!=(const PcpDependency &rhs) const { + return !(*this == rhs); + } +}; + +typedef std::vector PcpDependencyVector; + +/// Classify the dependency represented by a node, by analyzing +/// its structural role in its PcpPrimIndex. Returns a +/// bitmask of flags from PcpDependencyType. +PcpDependencyFlags PcpClassifyNodeDependency(const PcpNodeRef &n); + +std::string PcpDependencyFlagsToString(const PcpDependencyFlags flags); + +#endif diff --git a/pxr/usd/lib/pcp/diagnostic.cpp b/pxr/usd/lib/pcp/diagnostic.cpp index f8018ee1cd..20b2b9196b 100644 --- a/pxr/usd/lib/pcp/diagnostic.cpp +++ b/pxr/usd/lib/pcp/diagnostic.cpp @@ -26,6 +26,7 @@ #include "pxr/usd/pcp/cache.h" #include "pxr/usd/pcp/composeSite.h" #include "pxr/usd/pcp/debugCodes.h" +#include "pxr/usd/pcp/dependencies.h" #include "pxr/usd/pcp/layerStack.h" #include "pxr/usd/pcp/node.h" #include "pxr/usd/pcp/node_Iterator.h" @@ -36,6 +37,7 @@ #include "pxr/base/tf/diagnostic.h" #include "pxr/base/tf/enum.h" +#include "pxr/base/tf/stringUtils.h" #include #include @@ -71,6 +73,12 @@ std::string Pcp_Dump( : "NONE"); s += TfStringPrintf(" Type: %s\n", TfEnum::GetDisplayName(node.GetArcType()).c_str()); + + // Dependency info + s += " DependencyType: "; + const int depFlags = PcpClassifyNodeDependency(node); + s += PcpDependencyFlagsToString(depFlags) + "\n"; + s += TfStringPrintf(" Source path: <%s>\n", node.GetPath().GetText()); s += TfStringPrintf(" Source layer stack: %s\n", @@ -86,7 +94,7 @@ std::string Pcp_Dump( const PcpNodeRef originNode = node.GetOriginNode(); if (originNode != parentNode) { - s += TfStringPrintf(" Inherit origin node: %d\n", + s += TfStringPrintf(" Origin node: %d\n", TfMapLookupByValue(nodeToStrengthOrder, originNode, 0)); s += TfStringPrintf(" Sibling # at origin: %d\n", node.GetSiblingNumAtOrigin()); @@ -112,11 +120,9 @@ std::string Pcp_Dump( s += TfStringPrintf(" Permission: %s\n", TfEnum::GetDisplayName(node.GetPermission()).c_str()); s += TfStringPrintf(" Is restricted: %s\n", - _GetString(node.IsInert())); + _GetString(node.IsRestricted())); s += TfStringPrintf(" Is inert: %s\n", _GetString(node.IsInert())); - s += TfStringPrintf(" Contribute dependencies: %s\n", - _GetString(node.ShouldContributeDependencies())); s += TfStringPrintf(" Contribute specs: %s\n", _GetString(node.CanContributeSpecs())); s += TfStringPrintf(" Has specs: %s\n", @@ -129,11 +135,18 @@ std::string Pcp_Dump( const SdfPrimSpecHandleVector* specs = TfMapLookupPtr(nodeToPrimSpecs, node); if (specs) { + s += " Prim stack:\n"; TF_FOR_ALL(primIt, *specs) { const SdfPrimSpecHandle& primSpec = *primIt; - s += TfStringPrintf(" Prim: @%s@<%s>\n", - primSpec->GetLayer()->GetIdentifier().c_str(), - primSpec->GetPath().GetText()); + std::string layerPath; + SdfLayer::FileFormatArguments args; + SdfLayer::SplitIdentifier( primSpec->GetLayer()->GetIdentifier(), + &layerPath, &args ); + std::string basename = TfGetBaseName(layerPath); + s += TfStringPrintf(" <%s> %s - @%s@\n", + primSpec->GetPath().GetText(), + basename.c_str(), + primSpec->GetLayer()->GetIdentifier().c_str()); } } @@ -142,6 +155,7 @@ std::string Pcp_Dump( *childIt, nodeToStrengthOrder, nodeToPrimSpecs, includeInheritOriginInfo, includeMaps); } + s += "\n"; return s; } @@ -251,12 +265,7 @@ _WriteGraph( } if (not node.CanContributeSpecs()) { - if (node.ShouldContributeDependencies()) { - nodeDesc += "\\nONLY contributes specs to dependencies"; - } - else { - nodeDesc += "\\nCANNOT contribute specs"; - } + nodeDesc += "\\nCANNOT contribute specs"; } nodeDesc += TfStringPrintf("\\ndepth: %i", node.GetNamespaceDepth()); diff --git a/pxr/usd/lib/pcp/layerStack.cpp b/pxr/usd/lib/pcp/layerStack.cpp index acaf69ffdd..24ffa0a69e 100644 --- a/pxr/usd/lib/pcp/layerStack.cpp +++ b/pxr/usd/lib/pcp/layerStack.cpp @@ -749,3 +749,14 @@ operator<<(std::ostream& s, const PcpLayerStackPtr& x) return s << "@@"; } } + +std::ostream& +operator<<(std::ostream& s, const PcpLayerStackRefPtr& x) +{ + if (x) { + return s << x->GetIdentifier(); + } + else { + return s << "@NULL@"; + } +} diff --git a/pxr/usd/lib/pcp/layerStack.h b/pxr/usd/lib/pcp/layerStack.h index fde3b83b0c..94eb46947b 100644 --- a/pxr/usd/lib/pcp/layerStack.h +++ b/pxr/usd/lib/pcp/layerStack.h @@ -229,6 +229,7 @@ class PcpLayerStack : public TfRefBase, public TfWeakBase, boost::noncopyable { }; std::ostream& operator<<(std::ostream&, const PcpLayerStackPtr&); +std::ostream& operator<<(std::ostream&, const PcpLayerStackRefPtr&); /// Compose the relocation arcs in the given stack of layers, /// putting the results into the given sourceToTarget and targetToSource diff --git a/pxr/usd/lib/pcp/module.cpp b/pxr/usd/lib/pcp/module.cpp index 39fd914ac4..64b0b798e7 100644 --- a/pxr/usd/lib/pcp/module.cpp +++ b/pxr/usd/lib/pcp/module.cpp @@ -26,6 +26,7 @@ TF_WRAP_MODULE { TF_WRAP( PayloadDecorator ); + TF_WRAP( Dependency ); TF_WRAP( Cache ); TF_WRAP( Errors ); TF_WRAP( InstanceKey ); diff --git a/pxr/usd/lib/pcp/node.cpp b/pxr/usd/lib/pcp/node.cpp index 84d9a88615..fc495f0b42 100644 --- a/pxr/usd/lib/pcp/node.cpp +++ b/pxr/usd/lib/pcp/node.cpp @@ -128,15 +128,12 @@ PCP_DEFINE_API( PCP_DEFINE_API(SdfPermission, GetPermission, SetPermission, smallInts.permission); PCP_DEFINE_API(bool, IsCulled, SetCulled, smallInts.culled); PCP_DEFINE_API(bool, IsRestricted, SetRestricted, smallInts.permissionDenied); -PCP_DEFINE_API( - bool, ShouldContributeDependencies, SetShouldContributeDependencies, - smallInts.shouldContributeDependencies); PCP_DEFINE_SET_API(bool, SetInert, smallInts.inert); PCP_DEFINE_GET_NODE_API(size_t, _GetParentIndex, smallInts.arcParentIndex); PCP_DEFINE_GET_NODE_API(size_t, _GetOriginIndex, smallInts.arcOriginIndex); -PCP_DEFINE_GET_API(const PcpLayerStackPtr&, GetLayerStack, layerStack); +PCP_DEFINE_GET_API(const PcpLayerStackRefPtr&, GetLayerStack, layerStack); bool PcpNodeRef::HasSpecs() const diff --git a/pxr/usd/lib/pcp/node.h b/pxr/usd/lib/pcp/node.h index f976a69efa..d57a11f92b 100644 --- a/pxr/usd/lib/pcp/node.h +++ b/pxr/usd/lib/pcp/node.h @@ -187,7 +187,7 @@ class PcpNodeRef : const SdfPath& GetPath() const; /// Returns the layer stack for the site this node represents. - const PcpLayerStackPtr& GetLayerStack() const; + const PcpLayerStackRefPtr& GetLayerStack() const; /// Returns true if this node is a source of direct opinions. /// There should only be one direct node per prim index. @@ -229,11 +229,6 @@ class PcpNodeRef : void SetRestricted(bool restricted); bool IsRestricted() const; - /// Get/set whether this node should contribute specs for dependency - /// tracking even if it is not allowed to contribute opinions. - void SetShouldContributeDependencies(bool shouldContribute); - bool ShouldContributeDependencies() const; - /// Returns true if this node is allowed to contribute opinions /// for composition, false otherwise. bool CanContributeSpecs() const; diff --git a/pxr/usd/lib/pcp/primIndex.cpp b/pxr/usd/lib/pcp/primIndex.cpp index 4bb3f15fb3..86f9b6b698 100644 --- a/pxr/usd/lib/pcp/primIndex.cpp +++ b/pxr/usd/lib/pcp/primIndex.cpp @@ -71,17 +71,6 @@ PcpIsNewDefaultStandinBehaviorEnabled() //////////////////////////////////////////////////////////////////////// -size_t -PcpPrimIndexDependencies::Hash::operator()(const Site& site) const -{ - size_t hash = 0; - boost::hash_combine(hash, TfHash()(site.first)); - boost::hash_combine(hash, site.second.GetHash()); - return hash; -} - -//////////////////////////////////////////////////////////////////////// - PcpPrimIndex::PcpPrimIndex() { } @@ -645,7 +634,8 @@ struct Pcp_PrimIndexer { /// The various kinds of tasks. enum TaskType { - EvalRelocations, + EvalNodeRelocations, + EvalImpliedRelocations, EvalNodeReferences, EvalNodeInherits, EvalNodeSpecializes, @@ -685,6 +675,8 @@ struct Pcp_PrimIndexer // Remaining tasks, bucketed (somewhat) by type. typedef PcpNodeRefVector _TaskDataQueue; + _TaskDataQueue relocs; + _TaskDataQueue impliedRelocs; _TaskDataQueue refs; _TaskDataQueue inhs; _TaskDataQueue specializes; @@ -701,8 +693,6 @@ struct Pcp_PrimIndexer } }; - bool handledRelocations; - bool evaluateImpliedSpecializes; bool evaluateVariants; @@ -715,13 +705,12 @@ struct Pcp_PrimIndexer : ancestorRecursionDepth(0) , outputs(0) , previousFrame(0) - , handledRelocations(false) , evaluateImpliedSpecializes(true) , evaluateVariants(true) { } - static bool _NodeCanContributeTasks(const PcpNodeRef& n) + static bool _NodeContributesSpecs(const PcpNodeRef& n) { // Optimizations: // - If the node does not have specs or cannot contribute specs, @@ -732,7 +721,8 @@ struct Pcp_PrimIndexer // Add this node and its children to the task queues. void _AddTasksForNodeRecursively(const PcpNodeRef& n, - bool skipRefsPayloadsAndInherits) + bool skipCompletedNodes, + bool isUsd) { #ifdef PCP_DIAGNOSTIC_VALIDATION TF_VERIFY(seen.count(n) == 0, "Already processed <%s>", @@ -743,41 +733,54 @@ struct Pcp_PrimIndexer // Collect nodes in weak-to-strong order. struct _Collector { static void _CollectNodesWeakToStrong( - PcpNodeRefVector* nodes, const PcpNodeRef& node) + PcpNodeRefVector* allNodes, + PcpNodeRefVector* nodesWithSpecs, + const PcpNodeRef& node) { // Weak-to-strong traversal for any existing child nodes. TF_REVERSE_FOR_ALL(child, Pcp_GetChildrenRange(node)) { - _CollectNodesWeakToStrong(nodes, *child); + _CollectNodesWeakToStrong(allNodes, nodesWithSpecs, *child); } - if (_NodeCanContributeTasks(node)) { - nodes->push_back(node); + allNodes->push_back(node); + if (_NodeContributesSpecs(node)) { + nodesWithSpecs->push_back(node); } } }; - PcpNodeRefVector nodes; - _Collector::_CollectNodesWeakToStrong(&nodes, n); - if (nodes.empty()) { - return; + PcpNodeRefVector allNodes, nodesWithSpecs; + _Collector::_CollectNodesWeakToStrong(&allNodes, &nodesWithSpecs, n); + + if (!isUsd) { + impliedRelocs.insert(impliedRelocs.end(), + allNodes.begin(), allNodes.end()); } - // If the caller tells us the new node was already evaluated for - // references, payloads, and inherits (skipRefsPayloadsAndInherits) - // we do not need to re-scan it for those types of arcs. - if (not skipRefsPayloadsAndInherits) { + // If the caller tells us the new node and its children were + // already fully indexed, we do not need to re-scan them for + // these kinds of arcs. + if (not skipCompletedNodes) { // Add nodes to list of tasks. - inhs.insert(inhs.end(), nodes.begin(), nodes.end()); - specializes.insert(specializes.end(), nodes.begin(), nodes.end()); - - // Add nodes to list of reference tasks. We want to ensure these - // tasks are processed in strength order so that information from - // stronger references is available when processing weaker - // references to add decorators - refs.insert( - std::lower_bound(refs.begin(), refs.end(), nodes.front(), - _NodeStrengthComparator()), - nodes.begin(), nodes.end()); + if (!isUsd) { + relocs.insert(relocs.end(), allNodes.begin(), allNodes.end()); + } + inhs.insert(inhs.end(), + nodesWithSpecs.begin(), nodesWithSpecs.end()); + specializes.insert(specializes.end(), + nodesWithSpecs.begin(), nodesWithSpecs.end()); + + // Add nodesWithSpecs to list of reference tasks. We want + // to ensure these tasks are processed in strength order so + // that information from stronger references is available + // when processing weaker references to add decorators + if (not nodesWithSpecs.empty()) { + refs.insert( + std::lower_bound(refs.begin(), refs.end(), + nodesWithSpecs.front(), + _NodeStrengthComparator()), + nodesWithSpecs.begin(), nodesWithSpecs.end()); + } #ifdef PCP_DIAGNOSTIC_VALIDATION TF_VERIFY(boost::algorithm::is_sorted( @@ -788,14 +791,18 @@ struct Pcp_PrimIndexer // - If this indexer isn't evaluating variants, we can skip over // processing variant tasks. if (evaluateVariants) { - // Add nodes to list of variant tasks. We want to ensure these - // tasks are processed in strength order so that variant selections - // in stronger variants are available when processing weaker - // variants (see TrickyVariantSelectionInVariant museum case). - vars.insert( - std::lower_bound(vars.begin(), vars.end(), nodes.front(), - _NodeStrengthComparator()), - nodes.begin(), nodes.end()); + // Add nodesWithSpecs to list of variant tasks. We want + // to ensure these tasks are processed in strength order + // so that variant selections in stronger variants + // are available when processing weaker variants (see + // TrickyVariantSelectionInVariant museum case). + if (not nodesWithSpecs.empty()) { + vars.insert( + std::lower_bound(vars.begin(), vars.end(), + nodesWithSpecs.front(), + _NodeStrengthComparator()), + nodesWithSpecs.begin(), nodesWithSpecs.end()); + } #ifdef PCP_DIAGNOSTIC_VALIDATION TF_VERIFY(boost::algorithm::is_sorted( @@ -804,21 +811,24 @@ struct Pcp_PrimIndexer } // TODO: we should be able to skip the payload tasks when - // skipRefsPayloadsAndInherits is true, but first we'll need + // skipCompletedNodes is true, but first we'll need // to update _EvalNodePayload() to properly decide when to // include a payload arc, and also make sure that the graph's // HasPayload flag gets updated properly. In the meantime, // we just always add payload tasks to ensure that they // do get handled. // - // Add nodes to list of payload tasks. We want to ensure these + // Add nodesWithSpecs to list of payload tasks. We want to ensure these // tasks are processed in strength order so that information from // stronger payloads is available when processing weaker // payloads to add decorators - payloads.insert( - std::lower_bound(payloads.begin(), payloads.end(), - nodes.front(), _NodeStrengthComparator()), - nodes.begin(), nodes.end()); + if (not nodesWithSpecs.empty()) { + payloads.insert( + std::lower_bound(payloads.begin(), payloads.end(), + nodesWithSpecs.front(), + _NodeStrengthComparator()), + nodesWithSpecs.begin(), nodesWithSpecs.end()); + } } void AddImpliedClassTask(const PcpNodeRef &n) @@ -842,7 +852,7 @@ struct Pcp_PrimIndexer } void AddTasksForNode(const PcpNodeRef& n, - bool skipRefsPayloadsAndInherits = false, + bool skipCompletedNodes = false, bool skipImpliedSpecializes = false) { // Any time we add an edge to the graph, we may need to update @@ -884,7 +894,7 @@ struct Pcp_PrimIndexer // Recurse over all of the rest of the nodes. (We assume that any // embedded class hierarchies have already been propagated to // the top node n, letting us avoid redundant work.) - _AddTasksForNodeRecursively(n, skipRefsPayloadsAndInherits); + _AddTasksForNodeRecursively(n, skipCompletedNodes, inputs.usd); } // Select the next task to perform. @@ -918,9 +928,15 @@ struct Pcp_PrimIndexer // check variants, and so on. // Task PopTask() { - if (not inputs.usd and not handledRelocations) { - handledRelocations = true; - return Task(EvalRelocations); + if (not relocs.empty()) { + Task task(EvalNodeRelocations, relocs.back()); + relocs.pop_back(); + return task; + } + if (not impliedRelocs.empty()) { + Task task(EvalImpliedRelocations, impliedRelocs.back()); + impliedRelocs.pop_back(); + return task; } if (not refs.empty()) { Task refTask(EvalNodeReferences, refs.back()); @@ -1001,15 +1017,14 @@ _PrimSpecExistsUnderNode( return false; } -// Helper for enforcing permissions on newly added arcs, in _AddArc(). +// Mark an entire subtree of nodes as inert. static void -_MarkSubgraphToContributeDependenciesButNotSpecs(PcpNodeRef node) +_InertSubtree( + PcpNodeRef node) { node.SetInert(true); - node.SetShouldContributeDependencies(true); - - TF_FOR_ALL(it, Pcp_GetChildrenRange(node)) { - _MarkSubgraphToContributeDependenciesButNotSpecs(*it); + TF_FOR_ALL(child, Pcp_GetChildrenRange(node)) { + _InertSubtree(*child); } } @@ -1356,12 +1371,6 @@ _AddArc( TfStringify(site).c_str()); // Pass along the other outputs from the nested computation. - indexer->outputs->dependencies.sites.insert( - childOutputs.dependencies.sites.begin(), - childOutputs.dependencies.sites.end()); - indexer->outputs->spookyDependencies.sites.insert( - childOutputs.spookyDependencies.sites.begin(), - childOutputs.spookyDependencies.sites.end()); indexer->outputs->allErrors.insert( indexer->outputs->allErrors.end(), childOutputs.allErrors.begin(), @@ -1405,14 +1414,9 @@ _AddArc( // If we evaluated ancestral opinions, it it means the nested // call to Pcp_BuildPrimIndex() has already evaluated refs, payloads, // and inherits on this subgraph, so we can skip those tasks. - const bool skipRefsPayloadsAndInherits = includeAncestralOpinions; + const bool skipCompletedNodes = includeAncestralOpinions; indexer->AddTasksForNode( - newNode, skipRefsPayloadsAndInherits, skipImpliedSpecializes); - - // Record the dependency the arc represents. - indexer->outputs->dependencies.sites.insert( - std::make_pair(std::make_pair(site.layerStack, site.path), - origin.IsDueToAncestor() ? PcpAncestral : PcpDirect)); + newNode, skipCompletedNodes, skipImpliedSpecializes); // If requested, recursively check if there is a prim spec at the // targeted site or at any of its descendants. If there isn't, @@ -1428,8 +1432,7 @@ _AddArc( indexer->RecordError(err); } - // If the arc targets a site that is itself private, issue an error, - // but keep the nodes so that we can track dependencies. + // If the arc targets a site that is itself private, issue an error. if (newNode.GetPermission() == SdfPermissionPrivate) { PcpErrorArcPermissionDeniedPtr err = PcpErrorArcPermissionDenied::New(); err->rootSite = PcpSite(parent.GetRootNode().GetSite()); @@ -1438,9 +1441,10 @@ _AddArc( err->arcType = arcType; indexer->RecordError(err); - // Mark the new child subgraph to not contribute specs, but - // still contribute dependencies, in order to support processing - // later changes that relax the permissions. + // Mark the new child subtree as inert so that it does not + // contribute specs, but keep the node(s) to track the + // dependencies in order to support processing later changes + // that relax the permissions. // // Note, this is a complementary form of permissions enforcement // to that done by _EnforcePermissions(). That function enforces @@ -1448,14 +1452,15 @@ _AddArc( // ancestral arc, overrides are prohibited. This enforces the // equivalent constraint on direct arcs: you cannot employ an // arc directly to a private site. - _MarkSubgraphToContributeDependenciesButNotSpecs(newNode); + _InertSubtree(newNode); } // If the new node's path is the pseudo root, this is a special dependency - // placeholder for unresolved default-target references/payloads. We mark - // the node to contribute dependencies but not specs. + // placeholder for unresolved default-target references/payloads. + // Mark the node inert to node contribute opinions, but retain the + // nodes to represent the dependency. if (newNode.GetPath() == SdfPath::AbsoluteRootPath()) { - _MarkSubgraphToContributeDependenciesButNotSpecs(newNode); + _InertSubtree(newNode); } return newNode; @@ -1715,28 +1720,15 @@ _ElideSubtree( // new graph node for the relocation source, and recursively populate that // source via _AddArc(). static void -_EvalRelocationsRecursively( +_EvalNodeRelocations( + PcpPrimIndex *index, const PcpNodeRef &node, Pcp_PrimIndexer *indexer ) { - // First, recurse on existing children. We do this before - // potentially adding relocation source nodes below, since - // we do not want to process those added sources. - // - // Arbitrary-order traversal. - // - // NOTE: We need to grab a copy of the child list and not just - // a reference. The recursive call may cause more nodes to - // be added to the graph's node pool, which would invalidate - // the reference. - // - // XXX:optimization: Since relocations are sparse, it might be - // worth doing a pre-flight scan for relocations to short-circuit - // the copy. - const PcpNodeRefVector children = Pcp_GetChildren(node); - TF_FOR_ALL(child, children) { - _EvalRelocationsRecursively(*child, indexer); - } + PCP_GRAPH_PHASE( + node, + "Evaluating relocations under %s", + Pcp_FormatSite(node.GetSite()).c_str()); // Determine if this node was relocated, and from what source path. const SdfRelocatesMap & relocatesTargetToSource = @@ -1855,8 +1847,8 @@ _EvalRelocationsRecursively( arcSiblingNum, /* The direct site of a relocation source is not allowed to contribute opinions. However, note that it usually - has children that do contribute opinions, due to - ancestral opinions. */ + has node-children that do contribute opinions via + ancestral arcs. */ /* directNodeShouldContributeSpecs = */ false, /* includeAncestralOpinions = */ true, /* requirePrimAtTarget = */ false, @@ -1887,15 +1879,60 @@ _EvalRelocationsRecursively( } static void -_EvalRelocations( +_EvalImpliedRelocations( + PcpPrimIndex *index, const PcpNodeRef &node, Pcp_PrimIndexer *indexer ) { + if (node.GetArcType() != PcpArcTypeRelocate or node.IsDueToAncestor()) { + return; + } + PCP_GRAPH_PHASE( - node, "Evaluating relocations under %s", + node, + "Evaluating relocations implied by %s", Pcp_FormatSite(node.GetSite()).c_str()); - _EvalRelocationsRecursively(node, indexer); + if (PcpNodeRef parent = node.GetParentNode()) { + if (PcpNodeRef gp = parent.GetParentNode()) { + SdfPath gpRelocSource = + parent.GetMapToParent().MapSourceToTarget(node.GetPath()); + if (!TF_VERIFY(not gpRelocSource.IsEmpty())) { + return; + } + + PCP_GRAPH_PHASE( + node, + "Propagating relocate from %s to %s", + Pcp_FormatSite(node.GetSite()).c_str(), + gpRelocSource.GetText()); + + // Check if this has already been propagated. + TF_FOR_ALL(gpChildIt, Pcp_GetChildrenRange(gp)) { + const PcpNodeRef& gpChild = *gpChildIt; + if (gpChild.GetPath() == gpRelocSource && + gpChild.GetArcType() == PcpArcTypeRelocate) { + PCP_GRAPH_PHASE( + node, + "Relocate already exists -- skipping"); + return; + } + } + + _AddArc( PcpArcTypeRelocate, + /* parent = */ gp, + /* origin = */ node, + PcpLayerStackSite( gp.GetLayerStack(), + gpRelocSource ), + PcpMapExpression::Identity(), + /* arcSiblingNum = */ 0, + /* directNodeShouldContributeSpecs = */ false, + /* includeAncestralOpinions = */ false, + /* requirePrimAtTarget = */ false, + /* skipDuplicateNodes = */ false, + indexer ); + } + } } //////////////////////////////////////////////////////////////////////// @@ -2552,16 +2589,6 @@ _IsPropagatedSpecializesNode( node.GetSite() == node.GetOriginNode().GetSite()); } -static void -_InertSubtree( - PcpNodeRef node) -{ - node.SetInert(true); - TF_FOR_ALL(child, Pcp_GetChildrenRange(node)) { - _InertSubtree(*child); - } -} - static bool _IsNodeInSubtree( const PcpNodeRef& node, @@ -2872,23 +2899,6 @@ _ComposeVariantSelectionForNode( node.GetPath()); } - // Record dependencies on sites we examine to decide the - // variant selection. - // - // Optimization: If pathInNode is the same as the node path, - // we can rely on the fact that the node dependency will have - // already been recorded when the node was added. Otherwise, - // pathInNode has been affected by a relocation, so we must - // we must record a spooky dependency. - // - if (site != node.GetSite()) { - // Record the spooky site dependency. Do this even if there is - // no variant selection here, since that might change later. - outputs->spookyDependencies.sites.insert( - std::make_pair(std::make_pair(site.layerStack, site.path), - PcpDirect)); - } - // XXX: We should be able to skip this computation by checking // PcpNodeRef::HasVariantSelections here, but we need to be // careful about the case where site != node.GetSite(). I @@ -3041,9 +3051,9 @@ _ComposeVariantSelection( } // We want to look for variant selections in all nodes that have been - // added up to this point. Because Pcp follows all other arcs it - // encounters (except payloads) before variants, Pcp may pick up variant - // selections from weaker locations than the node we're processing. + // added up to this point. Note that Pcp may pick up variant + // selections from weaker locations than the node for which + // we are evaluating variants. // // See bug 106950 and TrickyVariantWeakerSelection for more details. // @@ -3250,10 +3260,6 @@ _EvalNodeVariants( node, "Found variant selection '%s' for set '%s'", vsel.c_str(), vset.c_str()); - // Verify that this is a valid selection among the options. - // If there isn't, this node must not provide the selected variant, - // but downstream nodes may. So, just skip it and move on. - // // XXX: There's a question as to whether Pcp should be responsible // for validating variant selections at some point. Currently, Csd // handles that during name children population and checks that @@ -3264,12 +3270,6 @@ _EvalNodeVariants( // that are provided by instances. Pcp currently doesn't know or // care whether the prim being constructed is a class, and it'd // be nice if it didn't have to. - if (vsetOptions.find(vsel) == vsetOptions.end()) { - PCP_GRAPH_MSG( - node, "Variant '%s' not in set '%s', skipping", - vsel.c_str(), vset.c_str()); - continue; - } // Add the variant arc. SdfPath varPath = node.GetSite() @@ -3289,7 +3289,7 @@ _EvalNodeVariants( /* arcSiblingNum = */ vsetNum, /* directNodeShouldContributeSpecs = */ true, /* includeAncestralOpinions = */ false, - /* requirePrimAtTarget = */ true, + /* requirePrimAtTarget = */ false, /* skipDuplicateNodes = */ false, indexer ); } @@ -3587,57 +3587,41 @@ _EnforcePermissions( } void -Pcp_BuildPrimStack( - PcpPrimIndex *index, - SdfSiteVector* dependencySites, - PcpNodeRefVector *dependencyNodes) +Pcp_RescanForSpecs(PcpPrimIndex *index, bool usd, bool updateHasSpecs) { - TfAutoMallocTag2 tag("Pcp", "Pcp_BuildPrimStack"); - - Pcp_CompressedSdSiteVector primSites; - TF_FOR_ALL(nodeIt, index->GetNodeRange()) { - PcpNodeRef node = *nodeIt; - if (not node.IsCulled() and - (node.ShouldContributeDependencies() or - node.CanContributeSpecs())) { - // Add prim specs in strength order (strong-to-weak). - const SdfLayerRefPtrVector& layers = - node.GetLayerStack()->GetLayers(); - const SdfPath& path = node.GetPath(); - for (size_t i = 0, n = layers.size(); i != n; ++i) { - if (layers[i]->HasSpec(path)) { - dependencySites->push_back(SdfSite(layers[i], path)); - dependencyNodes->push_back(node); - if (node.CanContributeSpecs()) { + TfAutoMallocTag2 tag("Pcp", "Pcp_RescanForSpecs"); + + if (usd) { + // USD does not retain prim stacks. + // We do need to update the HasSpecs flag on nodes, however. + if (updateHasSpecs) { + TF_FOR_ALL(nodeIt, index->GetNodeRange()) { + nodeIt->SetHasSpecs( + PcpComposeSiteHasPrimSpecs(nodeIt->GetSite())); + } + } + } else { + Pcp_CompressedSdSiteVector primSites; + TF_FOR_ALL(nodeIt, index->GetNodeRange()) { + PcpNodeRef node = *nodeIt; + bool nodeHasSpecs = false; + if (not node.IsCulled() and node.CanContributeSpecs()) { + // Add prim specs in strength order (strong-to-weak). + const SdfLayerRefPtrVector& layers = + node.GetLayerStack()->GetLayers(); + const SdfPath& path = node.GetPath(); + for (size_t i = 0, n = layers.size(); i != n; ++i) { + if (layers[i]->HasSpec(path)) { + nodeHasSpecs = true; primSites.push_back(node.GetCompressedSdSite(i)); } } } + if (updateHasSpecs) { + node.SetHasSpecs(nodeHasSpecs); + } } - } - - TF_VERIFY(dependencyNodes->size() == dependencySites->size()); - index->_primStack.swap(primSites); -} - -void -Pcp_UpdatePrimStack( - PcpPrimIndex* index, - SdfSiteVector* dependencySites, - PcpNodeRefVector* dependencyNodes) -{ - TfAutoMallocTag2 tag("Pcp", "Pcp_UpdatePrimStack"); - - // Rebuild the prim stack member of the prim index the same way we - // constructed it in the first place. - Pcp_BuildPrimStack(index, dependencySites, dependencyNodes); - - // If a new prim was added to a node that didn't have a prim - // before, we need to update that node's 'hasSpecs' flag. As it - // happens, dependencyNodes holds exactly the nodes that may need - // to be updated. - TF_FOR_ALL(it, *dependencyNodes) { - it->SetHasSpecs(true); + index->_primStack.swap(primSites); } } @@ -3905,22 +3889,6 @@ _BuildInitialPrimIndexFromAncestor( _CullSubtreesWithNoOpinions(rootNode, rootSite); } - // The child inherits the parent's dependencies as ancestral dependencies, - // with correspondingly updated site paths. - PcpPrimIndexDependencies ancestralDeps; - TF_FOR_ALL(dep, outputs->dependencies.sites) { - PcpPrimIndexDependencies::Site depSite = dep->first; - depSite.second = depSite.second.AppendChild(site.path.GetNameToken()); - ancestralDeps.sites.insert( std::make_pair(depSite, PcpAncestral) ); - } - outputs->dependencies.sites.swap(ancestralDeps.sites); - // Spooky dependencies do not represent sites composed into this prim, - // they just represent sites whose contents indirectly affected the - // composition structure of this prim (eg spooky variant selections). - TF_FOR_ALL(dep, outputs->spookyDependencies.sites) { - dep->second = PcpAncestral; - } - // Force the root node to inert if the caller has specified that the // direct root node should not contribute specs. Note that the node // may already be set to inert when applying instancing restrictions @@ -4005,8 +3973,11 @@ Pcp_BuildPrimIndex( while (tasksAreLeft) { Pcp_PrimIndexer::Task task = indexer.PopTask(); switch (task.type) { - case Pcp_PrimIndexer::EvalRelocations: - _EvalRelocations(outputs->primIndex.GetRootNode(), &indexer); + case Pcp_PrimIndexer::EvalNodeRelocations: + _EvalNodeRelocations(&outputs->primIndex, task.node, &indexer); + break; + case Pcp_PrimIndexer::EvalImpliedRelocations: + _EvalImpliedRelocations(&outputs->primIndex, task.node, &indexer); break; case Pcp_PrimIndexer::EvalNodeReferences: _EvalNodeReferences(&outputs->primIndex, task.node, &indexer); @@ -4099,35 +4070,8 @@ PcpComputePrimIndex( // // Note that we *must* do this after the graph is finalized, as // finalization will cause outstanding PcpNodeRefs to be invalidated. - if (not inputs.usd) { - Pcp_BuildPrimStack( - &outputs->primIndex, - &outputs->dependencySites, &outputs->dependencyNodes); - - // Record the spooky spec dependency. This is different from - // a normal spec dependency because the it cannot be extracted - // from the prim stack (as other spec dependencies), nor is it - // implicitly covered by the dependencies of namespace ancestors - // (because it is spooky). - // Add spooky dependency specs in arbitrary order. - TF_FOR_ALL(it, outputs->primIndex.GetNodeRange()) { - const PcpLayerStackSite& site = it->GetSite(); - const PcpPrimIndexDependencies::Site refSite( - site.layerStack, site.path); - - if (outputs->spookyDependencies.sites.count(refSite) > 0) { - SdfSiteVector spookyDependencySites; - PcpComposeSitePrimSites(site, &spookyDependencySites); - - outputs->spookyDependencySites.insert( - outputs->spookyDependencySites.end(), - spookyDependencySites.begin(), spookyDependencySites.end()); - outputs->spookyDependencyNodes.insert( - outputs->spookyDependencyNodes.end(), - spookyDependencySites.size(), *it); - } - } - } + Pcp_RescanForSpecs(&outputs->primIndex, inputs.usd, + /* updateHasSpecs */false ); } //////////////////////////////////////////////////////////////////////// diff --git a/pxr/usd/lib/pcp/primIndex.h b/pxr/usd/lib/pcp/primIndex.h index cf77183cc9..f83c7a8b42 100644 --- a/pxr/usd/lib/pcp/primIndex.h +++ b/pxr/usd/lib/pcp/primIndex.h @@ -54,27 +54,6 @@ class PcpPrimIndexOutputs; class PcpPayloadDecorator; class SdfPath; -// A set of sites that a given site depends on. Also notes if the type of -// dependency. The sites use a layer stack ref ptr so PcpLayerStackSite -// isn't used. -class PcpPrimIndexDependencies { -public: - typedef std::pair Site; - struct Hash { - size_t operator()(const Site& site) const; - }; - - /// Swap contents with \p r. - inline void swap(PcpPrimIndexDependencies &r) { sites.swap(r.sites); } - - typedef boost::unordered_map Map; - Map sites; -}; - -/// Free function version for generic code and ADL. -inline void -swap(PcpPrimIndexDependencies &l, PcpPrimIndexDependencies &r) { l.swap(r); } - /// \class PcpPrimIndex /// /// PcpPrimIndex is an index of the all sites of scene description that @@ -238,8 +217,8 @@ class PcpPrimIndex private: friend class PcpPrimIterator; friend struct Pcp_PrimIndexer; - friend void Pcp_BuildPrimStack( - PcpPrimIndex*, SdfSiteVector*, PcpNodeRefVector*); + friend void Pcp_RescanForSpecs(PcpPrimIndex*, bool usd, + bool updateHasSpecs); // The node graph representing the compositional structure of this prim. PcpPrimIndex_GraphRefPtr _graph; @@ -267,20 +246,6 @@ class PcpPrimIndexOutputs /// prim. PcpPrimIndex primIndex; - /// Dependencies found during prim indexing. Note that these dependencies - /// may be keeping structures (e.g., layer stacks) in the above prim index - /// alive and must live on at least as long as the prim index. - PcpPrimIndexDependencies dependencies; - SdfSiteVector dependencySites; - PcpNodeRefVector dependencyNodes; - - /// Spooky dependency specs are those that were consulted in the process - /// of building this prim index, but which are not a namespace ancestor - /// of this prim due to relocations. - PcpPrimIndexDependencies spookyDependencies; - SdfSiteVector spookyDependencySites; - PcpNodeRefVector spookyDependencyNodes; - /// List of all errors encountered during indexing. PcpErrorVector allErrors; @@ -291,12 +256,6 @@ class PcpPrimIndexOutputs /// Swap content with \p r. inline void swap(PcpPrimIndexOutputs &r) { primIndex.swap(r.primIndex); - dependencies.swap(r.dependencies); - dependencySites.swap(r.dependencySites); - dependencyNodes.swap(r.dependencyNodes); - spookyDependencies.swap(r.spookyDependencies); - spookyDependencySites.swap(r.spookyDependencySites); - spookyDependencyNodes.swap(r.spookyDependencyNodes); allErrors.swap(r.allErrors); std::swap(includedDiscoveredPayload, r.includedDiscoveredPayload); } @@ -364,7 +323,7 @@ class PcpPrimIndexInputs { PcpPrimIndexInputs& Cull(bool doCulling = true) { cull = doCulling; return *this; } - /// Whether the prim stack and its dependencies should be computed, and + /// Whether the prim stack should be computed, and /// whether relocates, inherits, permissions, symmetry, or payloads should /// be considered during prim index computation, PcpPrimIndexInputs& USD(bool doUSD = true) @@ -389,9 +348,7 @@ class PcpPrimIndexInputs { }; /// Compute an index for the given path. \p errors will contain any errors -/// encountered while performing this operation. Any encountered dependencies -/// on remote layer stacks will be appended to \p dependencies; it must not -/// be \c NULL because it's what keeps the layer stacks alive. +/// encountered while performing this operation. void PcpComputePrimIndex( const SdfPath& primPath, @@ -404,22 +361,8 @@ PcpComputePrimIndex( bool PcpIsNewDefaultStandinBehaviorEnabled(); -// Sets the prim stack in \p index and returns the sites of prims that -// \p index depends on in \p dependencySites, as well as the nodes from which -// these prims originated in \p dependencyNodes. -void -Pcp_BuildPrimStack( - PcpPrimIndex* index, - SdfSiteVector* dependencySites, - PcpNodeRefVector* dependencyNodes); - -// Updates the prim stack and related flags in \p index, and returns the sites -// of prims that \p index depends on in \p dependencySites, as well as the -// nodes from which these prims originated in \p dependencyNodes. +// Sets the prim stack in \p index. void -Pcp_UpdatePrimStack( - PcpPrimIndex* index, - SdfSiteVector* dependencySites, - PcpNodeRefVector* dependencyNodes); +Pcp_RescanForSpecs(PcpPrimIndex* index, bool usd); #endif diff --git a/pxr/usd/lib/pcp/primIndex_Graph.h b/pxr/usd/lib/pcp/primIndex_Graph.h index df41c6983a..10a7d40f22 100644 --- a/pxr/usd/lib/pcp/primIndex_Graph.h +++ b/pxr/usd/lib/pcp/primIndex_Graph.h @@ -256,7 +256,6 @@ class PcpPrimIndex_Graph , inert(false) , culled(false) , permissionDenied(false) - , shouldContributeDependencies(false) , arcType(PcpArcTypeRoot) , arcSiblingNumAtOrigin(0) , arcNamespaceDepth(0) @@ -289,7 +288,7 @@ class PcpPrimIndex_Graph // out the data in memory as tightly as possible. // The layer stack for this node. - PcpLayerStackPtr layerStack; + PcpLayerStackRefPtr layerStack; // Mapping function used to translate from this node directly // to the root node. This is essentially the composition of the // mapToParent for every arc between this node and the root. @@ -328,11 +327,6 @@ class PcpPrimIndex_Graph // node that was marked \c SdfPermissionPrivate, or we arrive // at this node from another node that was denied permission. bool permissionDenied:1; - // Whether this node should contribute specs for dependency - // tracking. This is set to true in cases where this node is - // not allowed to contribute opinions, but we still need to - // know about specs for dependency tracking. - bool shouldContributeDependencies:1; // The type of the arc to the parent node. PcpArcType arcType:4; // Index among sibling arcs at origin; lower is stronger diff --git a/pxr/usd/lib/pcp/site.cpp b/pxr/usd/lib/pcp/site.cpp index 35f3cc96b9..a2afe41444 100644 --- a/pxr/usd/lib/pcp/site.cpp +++ b/pxr/usd/lib/pcp/site.cpp @@ -40,7 +40,8 @@ PcpSite::PcpSite( const PcpLayerStackIdentifier & layerStackIdentifier_, // Do nothing } -PcpSite::PcpSite( const PcpLayerStackPtr & layerStack, const SdfPath & path_ ) : +PcpSite::PcpSite( const PcpLayerStackPtr & layerStack, + const SdfPath & path_ ) : path(path_) { if (layerStack) { @@ -94,7 +95,7 @@ PcpLayerStackSite::PcpLayerStackSite() // Do nothing } -PcpLayerStackSite::PcpLayerStackSite( const PcpLayerStackPtr & layerStack_, +PcpLayerStackSite::PcpLayerStackSite( const PcpLayerStackRefPtr & layerStack_, const SdfPath & path_ ) : layerStack(layerStack_), path(path_) diff --git a/pxr/usd/lib/pcp/site.h b/pxr/usd/lib/pcp/site.h index 2c4ed07129..fc56a7328a 100644 --- a/pxr/usd/lib/pcp/site.h +++ b/pxr/usd/lib/pcp/site.h @@ -32,7 +32,7 @@ #include #include -TF_DECLARE_WEAK_PTRS(PcpLayerStack); +TF_DECLARE_WEAK_AND_REF_PTRS(PcpLayerStack); class PcpLayerStackSite; /// \class PcpSite @@ -68,12 +68,12 @@ class PcpSite : boost::totally_ordered class PcpLayerStackSite : boost::totally_ordered { public: - PcpLayerStackPtr layerStack; + PcpLayerStackRefPtr layerStack; SdfPath path; PcpLayerStackSite(); - PcpLayerStackSite( const PcpLayerStackPtr &, const SdfPath & path ); + PcpLayerStackSite( const PcpLayerStackRefPtr &, const SdfPath & path ); bool operator==(const PcpLayerStackSite &rhs) const; diff --git a/pxr/usd/lib/pcp/statistics.cpp b/pxr/usd/lib/pcp/statistics.cpp index d89c3813db..0b6e5d14cb 100644 --- a/pxr/usd/lib/pcp/statistics.cpp +++ b/pxr/usd/lib/pcp/statistics.cpp @@ -337,8 +337,10 @@ class Pcp_Statistics static_assert(sizeof(PcpLayerStackPtr) == 16, "PcpLayerStackPtr must be of size 16"); - static_assert(sizeof(PcpLayerStackSite) == 24, - "PcpLayerStackSite must be of size 24"); + static_assert(sizeof(PcpLayerStackSite) == 16, + "PcpLayerStackSite must be of size 16"); + static_assert(sizeof(PcpPrimIndex) == 40, + "PcpPrimIndex must be of size 40"); // This object is 104 bytes when building against libstdc++ // and 88 for libc++ because std::vector is 40 bytes @@ -347,8 +349,8 @@ class Pcp_Statistics sizeof(PcpPrimIndex_Graph) == 88, "PcpPrimIndex_Graph must be of size 88 or 104"); - static_assert(sizeof(PcpPrimIndex_Graph::_Node) == 48, - "PcpPrimIndex_Graph::_Node must be of size 48"); + static_assert(sizeof(PcpPrimIndex_Graph::_Node) == 40, + "PcpPrimIndex_Graph::_Node must be of size 40"); static_assert(sizeof(PcpPrimIndex_Graph::_SharedData) == 32, "PcpPrimIndex_Graph::_SharedData must be of size 32"); } diff --git a/pxr/usd/lib/pcp/types.cpp b/pxr/usd/lib/pcp/types.cpp index 462105875d..debfb7ea63 100644 --- a/pxr/usd/lib/pcp/types.cpp +++ b/pxr/usd/lib/pcp/types.cpp @@ -51,7 +51,4 @@ TF_REGISTRY_FUNCTION(TfEnum) TF_ADD_ENUM_NAME(PcpRangeTypeWeakerThanRoot, "weaker than root"); TF_ADD_ENUM_NAME(PcpRangeTypeStrongerThanPayload, "stronger than payload"); TF_ADD_ENUM_NAME(PcpRangeTypeInvalid, "invalid"); - - TF_ADD_ENUM_NAME(PcpDirect, "direct dependency"); - TF_ADD_ENUM_NAME(PcpAncestral, "ancestral dependency"); } diff --git a/pxr/usd/lib/pcp/types.h b/pxr/usd/lib/pcp/types.h index 1b99034db7..b2db6898b8 100644 --- a/pxr/usd/lib/pcp/types.h +++ b/pxr/usd/lib/pcp/types.h @@ -135,15 +135,6 @@ struct PcpSiteTrackerSegment { /// site that we've already visited, we've found a cycle. typedef std::vector PcpSiteTracker; -/// \enum PcpDependencyType -/// -/// Defines the types of dependencies. -/// -enum PcpDependencyType { - PcpDirect = (1 << 0), - PcpAncestral = (1 << 1) -}; - // Internal type for Sd sites. struct Pcp_SdSiteRef : boost::totally_ordered { Pcp_SdSiteRef(const SdfLayerRefPtr& layer_, const SdfPath& path_) : diff --git a/pxr/usd/lib/pcp/wrapCache.cpp b/pxr/usd/lib/pcp/wrapCache.cpp index d65996a464..5da5e7894e 100644 --- a/pxr/usd/lib/pcp/wrapCache.cpp +++ b/pxr/usd/lib/pcp/wrapCache.cpp @@ -26,6 +26,7 @@ #include "pxr/usd/pcp/errors.h" #include "pxr/usd/pcp/layerStack.h" #include "pxr/usd/pcp/pyUtils.h" +#include "pxr/usd/pcp/types.h" #include "pxr/usd/sdf/primSpec.h" #include "pxr/base/tf/makePyConstructor.h" #include "pxr/base/tf/pyEnum.h" @@ -200,26 +201,19 @@ _RequestLayerMuting( PcpCache & cache, cache.RequestLayerMuting(layersToMute, layersToUnmute); } -static -SdfPathVector -_GetPathsUsingSite_1(const PcpCache& cache, - const SdfLayerHandle& layer, - const SdfPath& path, - PcpCache::UsingSite usingSite, - const SdfPath& fallbackAncestor) +static PcpDependencyVector +_FindDependentPaths(const PcpCache& cache, + const PcpLayerStackPtr& layerStack, + const SdfPath& path, + PcpDependencyFlags depMask, + bool recurseOnSite, + bool recurseOnIndex, + bool filterForExistingCachesOnly) { - return cache.GetPathsUsingSite(layer, path, usingSite, 0, fallbackAncestor); -} - -static -SdfPathVector -_GetPathsUsingSite_2(const PcpCache& cache, - const PcpLayerStackPtr& layerStack, - const SdfPath& path, - unsigned int dependencyType, - bool recursive) -{ - return cache.GetPathsUsingSite(layerStack, path, dependencyType, recursive); + return cache.FindDependentPaths(layerStack, path, depMask, + recurseOnSite, + recurseOnIndex, + filterForExistingCachesOnly); } static void @@ -232,19 +226,10 @@ _Reload( PcpCache & cache ) void wrapCache() -{ +{ class_, boost::noncopyable> - c("Cache", no_init); + ("Cache", no_init) - // Wrap PcpCache enums in the class' scope so they show up under - // Pcp.Cache. Need to do this here for enums that are default arguments - // to functions. - { - scope s = c; - TfPyWrapEnum(); - } - - c .def("__init__", make_constructor(_New, default_call_policies(), (arg("layerStackIdentifier"), @@ -297,26 +282,24 @@ wrapCache() args("stopProperty") = SdfSpecHandle(), args("includeStopProperty") = false)) - .def("GetPathsUsingSite", - &_GetPathsUsingSite_1, - (args("layer"), - args("path"), - args("usingSite") = PcpCache::UsingSiteOnly, - args("fallbackAncestor") = SdfPath())) - .def("GetPathsUsingSite", - &_GetPathsUsingSite_2, - (args("layerStack"), - args("path"), - args("dependencyType"), - args("recursive") = false)) + .def("FindDependentPaths", + &_FindDependentPaths, + (args("siteLayerStack"), + args("sitePath"), + args("dependencyType") = PcpDependencyTypeAnyNonVirtual, + args("recurseOnSite") = false, + args("recurseOnIndex") = false, + args("filterForExistingCachesOnly") = false), + return_value_policy()) + .def("FindAllLayerStacksUsingLayer", + &PcpCache::FindAllLayerStacksUsingLayer, + return_value_policy()) .def("IsInvalidAssetPath", &PcpCache::IsInvalidAssetPath) .def("IsInvalidSublayerIdentifier", &PcpCache::IsInvalidSublayerIdentifier) .def("PrintStatistics", &PcpCache::PrintStatistics) - .def("PrintDependencies", &PcpCache::PrintDependencies) - .def("CheckDependencies", &PcpCache::CheckDependencies) .def("Reload", &_Reload) ; } diff --git a/pxr/usd/lib/pcp/wrapDependency.cpp b/pxr/usd/lib/pcp/wrapDependency.cpp new file mode 100644 index 0000000000..a653f9c7f3 --- /dev/null +++ b/pxr/usd/lib/pcp/wrapDependency.cpp @@ -0,0 +1,65 @@ +// +// 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. +// +#include "pxr/usd/pcp/dependency.h" +#include "pxr/base/tf/pyEnum.h" +#include "pxr/base/tf/makePyConstructor.h" + +#include + +using namespace boost::python; +using std::string; + +static string +_DependencyRepr(const PcpDependency &dep) +{ + return TF_PY_REPR_PREFIX + "Cache.Dependency(" + + TfPyRepr(dep.indexPath) + ", " + + TfPyRepr(dep.sitePath) + ", " + + TfPyRepr(dep.mapFunc) + ")"; +} + +static PcpDependency* +_DependencyInit( + const SdfPath &indexPath, + const SdfPath &sitePath, + const PcpMapFunction &mapFunc) +{ + return new PcpDependency{indexPath, sitePath, mapFunc}; +} + +void +wrapDependency() +{ + class_("Dependency", no_init) + .def_readwrite("indexPath", &PcpDependency::indexPath) + .def_readwrite("sitePath", &PcpDependency::sitePath) + .def_readwrite("mapFunc", &PcpDependency::mapFunc) + .def("__repr__", &_DependencyRepr) + .def("__init__", make_constructor(_DependencyInit)) + .def(self == self) + .def(self != self) + ; + + TfPyWrapEnum(); +} diff --git a/pxr/usd/lib/pcp/wrapNode.cpp b/pxr/usd/lib/pcp/wrapNode.cpp index a1daa02fb5..fdd446ad1b 100644 --- a/pxr/usd/lib/pcp/wrapNode.cpp +++ b/pxr/usd/lib/pcp/wrapNode.cpp @@ -88,8 +88,6 @@ wrapNode() .add_property("isCulled", &This::IsCulled) .add_property("isRestricted", &This::IsRestricted) .add_property("permission", &This::GetPermission) - .add_property("shouldContributeDependencies", - &This::ShouldContributeDependencies) .def("GetRootNode", &::_GetRootNode) .def("GetOriginRootNode", &::_GetOriginRootNode) diff --git a/pxr/usd/lib/pcp/wrapTypes.cpp b/pxr/usd/lib/pcp/wrapTypes.cpp index 31c3f94af0..ad7a64fb1b 100644 --- a/pxr/usd/lib/pcp/wrapTypes.cpp +++ b/pxr/usd/lib/pcp/wrapTypes.cpp @@ -29,5 +29,4 @@ void wrapTypes() { TfPyWrapEnum(); - TfPyWrapEnum(); } diff --git a/pxr/usd/lib/usd/stage.cpp b/pxr/usd/lib/usd/stage.cpp index 1b2c8730d9..5363954be8 100644 --- a/pxr/usd/lib/usd/stage.cpp +++ b/pxr/usd/lib/usd/stage.cpp @@ -2824,31 +2824,23 @@ static void _AddDependentPaths(const SdfLayerHandle &layer, const SdfPath &path, const PcpCache &cache, SdfPathSet *output) { - // Use Pcp's LayerStack dependency facilities. We cannot use Pcp's spec - // dependency facilities, since we skip populating those in Usd mode. We - // may need to revisit this when we decide to tackle namespace editing. - const PcpLayerStackPtrVector& layerStacks = - cache.FindAllLayerStacksUsingLayer(layer); - - for (const auto& layerStack : layerStacks) { - // If this path is in the cache's LayerStack, we always add it. - if (layerStack == cache.GetLayerStack()) - output->insert(path.StripAllVariantSelections()); - - // Ask the cache for further dependencies and add any to the output. - SdfPathVector deps = cache.GetPathsUsingSite( - layerStack, path, PcpDirect | PcpAncestral, /*recursive*/ true); - output->insert(deps.begin(), deps.end()); - - TF_DEBUG(USD_CHANGES).Msg( - "Adding paths that use <%s> in layer @%s@%s: %s\n", - path.GetText(), layer->GetIdentifier().c_str(), - layerStack->GetIdentifier().rootLayer != layer ? - TfStringPrintf(" (stack root: @%s@)", - layerStack->GetIdentifier().rootLayer-> - GetIdentifier().c_str()).c_str() : "", - TfStringify(deps).c_str()); + // We include virtual dependencies so that we can process + // changes like adding missing defaultPrim metadata. + const PcpDependencyFlags depTypes = PcpDependencyTypeAnyIncludingVirtual; + + for (const PcpDependency& dep: + cache.FindDependentPaths(layer, path, depTypes, + /* recurseOnSite */ true, + /* recurseOnIndex */ true, + /* filterForExistingCachesOnly */ true)) { + output->insert(dep.indexPath); } + + TF_DEBUG(USD_CHANGES).Msg( + "Adding paths that use <%s> in layer @%s@: %s\n", + path.GetText(), + layer->GetIdentifier().c_str(), + TfStringify(*output).c_str()); } void From 9cb1a0f6e2a88a99292cf18298d7fd0f9952f5e2 Mon Sep 17 00:00:00 2001 From: blevin Date: Wed, 26 Oct 2016 11:02:21 -0700 Subject: [PATCH 328/380] Fix doxygen comment. (Internal change: 1667564) --- pxr/usd/lib/pcp/cache.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pxr/usd/lib/pcp/cache.h b/pxr/usd/lib/pcp/cache.h index 42180d3567..097259df9e 100644 --- a/pxr/usd/lib/pcp/cache.h +++ b/pxr/usd/lib/pcp/cache.h @@ -399,7 +399,7 @@ class PcpCache /// \param filterForExistingCachesOnly filters the results to only /// paths representing computed prim and property index caches; /// otherwise a recursively-expanded result can include - // un-computed paths that are expected to depend on the site + /// un-computed paths that are expected to depend on the site PcpDependencyVector FindDependentPaths(const PcpLayerStackPtr& siteLayerStack, const SdfPath& sitePath, From 32fe01a997ef3a67919d5dd721840342d8eaef41 Mon Sep 17 00:00:00 2001 From: takahito-tejima Date: Wed, 26 Oct 2016 11:02:31 -0700 Subject: [PATCH 329/380] [usdviewq] update axis, bbox and camera guide drawing Eliminates all glBegin/glEnd and other fixed pipeline calls. (Internal change: 1667610) --- pxr/usdImaging/lib/usdviewq/stageView.py | 484 +++++++++++++---------- 1 file changed, 275 insertions(+), 209 deletions(-) diff --git a/pxr/usdImaging/lib/usdviewq/stageView.py b/pxr/usdImaging/lib/usdviewq/stageView.py index 7c2a86971f..3a8fa2d170 100644 --- a/pxr/usdImaging/lib/usdviewq/stageView.py +++ b/pxr/usdImaging/lib/usdviewq/stageView.py @@ -491,6 +491,46 @@ def overrideFar(self, value): """To remove the override, set to None""" self._overrideFar = value +class GLSLProgram(): + def __init__(self, VS3, FS3, VS2, FS2, uniformDict): + from OpenGL import GL + self._glMajorVersion = int(GL.glGetString(GL.GL_VERSION)[0]) + + self.program = GL.glCreateProgram() + vertexShader = GL.glCreateShader(GL.GL_VERTEX_SHADER) + fragmentShader = GL.glCreateShader(GL.GL_FRAGMENT_SHADER) + + if (self._glMajorVersion >= 3): + vsSource = VS3 + fsSource = FS3 + else: + vsSource = VS2 + fsSource = FS2 + + GL.glShaderSource(vertexShader, vsSource) + GL.glCompileShader(vertexShader) + GL.glShaderSource(fragmentShader, fsSource) + GL.glCompileShader(fragmentShader) + GL.glAttachShader(self.program, vertexShader) + GL.glAttachShader(self.program, fragmentShader) + GL.glLinkProgram(self.program) + + if GL.glGetProgramiv(self.program, GL.GL_LINK_STATUS) == GL.GL_FALSE: + print GL.glGetShaderInfoLog(vertexShader) + print GL.glGetShaderInfoLog(fragmentShader) + print GL.glGetProgramInfoLog(self.program) + GL.glDeleteShader(vertexShader) + GL.glDeleteShader(fragmentShader) + GL.glDeleteProgram(self.program) + self.program = 0 + + GL.glDeleteShader(vertexShader) + GL.glDeleteShader(fragmentShader) + + self.uniformLocations = {} + for param in uniformDict: + self.uniformLocations[param] = GL.glGetUniformLocation(self.program, param) + class HUD(): class Group(): def __init__(self, name, w, h): @@ -506,7 +546,7 @@ def __init__(self): self._HUDLineSpacing = 15 self._HUDFont = QtGui.QFont("Menv Mono Numeric", 9) self._groups = {} - self._program = 0 + self._glslProgram = None self._glMajorVersion = 0 self._vao = 0 @@ -522,63 +562,36 @@ def compileProgram(self): (ctypes.c_float*len(st))(*st), GL.GL_STATIC_DRAW) GL.glBindBuffer(GL.GL_ARRAY_BUFFER, 0) - self._program = GL.glCreateProgram() - vertexShader = GL.glCreateShader(GL.GL_VERTEX_SHADER) - fragmentShader = GL.glCreateShader(GL.GL_FRAGMENT_SHADER) - - if (self._glMajorVersion >= 3): + self._glslProgram = GLSLProgram( # for OpenGL 3.1 or later - vsSource = """#version 140 - uniform vec4 rect; - in vec2 st; - out vec2 uv; - void main() { - gl_Position = vec4(rect.x + rect.z*st.x, - rect.y + rect.w*st.y, 0, 1); - uv = vec2(st.x, 1 - st.y); }""" - fsSource = """#version 140 - in vec2 uv; - out vec4 color; - uniform sampler2D tex; - void main() { color = texture(tex, uv); }""" - else: + """#version 140 + uniform vec4 rect; + in vec2 st; + out vec2 uv; + void main() { + gl_Position = vec4(rect.x + rect.z*st.x, + rect.y + rect.w*st.y, 0, 1); + uv = vec2(st.x, 1 - st.y); }""", + """#version 140 + in vec2 uv; + out vec4 color; + uniform sampler2D tex; + void main() { color = texture(tex, uv); }""", # for OpenGL 2.1 (osx compatibility profile) - vsSource = """#version 120 - uniform vec4 rect; - attribute vec2 st; - varying vec2 uv; - void main() { - gl_Position = vec4(rect.x + rect.z*st.x, - rect.y + rect.w*st.y, 0, 1); - uv = vec2(st.x, 1 - st.y); }""" - fsSource = """#version 120 - varying vec2 uv; - uniform sampler2D tex; - void main() { gl_FragColor = texture2D(tex, uv); }""" + """#version 120 + uniform vec4 rect; + attribute vec2 st; + varying vec2 uv; + void main() { + gl_Position = vec4(rect.x + rect.z*st.x, + rect.y + rect.w*st.y, 0, 1); + uv = vec2(st.x, 1 - st.y); }""", + """#version 120 + varying vec2 uv; + uniform sampler2D tex; + void main() { gl_FragColor = texture2D(tex, uv); }""", + ["rect", "tex"]) - GL.glShaderSource(vertexShader, vsSource) - GL.glCompileShader(vertexShader) - GL.glShaderSource(fragmentShader, fsSource) - GL.glCompileShader(fragmentShader) - GL.glAttachShader(self._program, vertexShader) - GL.glAttachShader(self._program, fragmentShader) - GL.glLinkProgram(self._program) - - if GL.glGetProgramiv(self._program, GL.GL_LINK_STATUS) == GL.GL_FALSE: - print GL.glGetShaderInfoLog(vertexShader) - print GL.glGetShaderInfoLog(fragmentShader) - print GL.glGetProgramInfoLog(self._program) - GL.glDeleteShader(vertexShader) - GL.glDeleteShader(fragmentShader) - GL.glDeleteProgram(self._program) - self._program = 0 - return False - - GL.glDeleteShader(vertexShader) - GL.glDeleteShader(fragmentShader) - - self._ulocRect = GL.glGetUniformLocation(self._program, "rect") - self._ulocTex = GL.glGetUniformLocation(self._program, "tex") return True def addGroup(self, name, w, h): @@ -627,27 +640,25 @@ def updateGroup(self, name, x, y, col, dic, keys = None): def draw(self, qglwidget): from OpenGL import GL - if (self._glMajorVersion == 0): - self._glMajorVersion = int(GL.glGetString(GL.GL_VERSION)[0]) + if (self._glslProgram == None): + self.compileProgram() - if (self._program == 0): - if (not self.compileProgram()): - self._program = 0 - return + if (self._glslProgram.program == 0): + return - GL.glUseProgram(self._program) + GL.glUseProgram(self._glslProgram.program) width = float(qglwidget.width()) height = float(qglwidget.height()) - if (self._glMajorVersion >= 4): + if (self._glslProgram._glMajorVersion >= 4): GL.glDisable(GL.GL_SAMPLE_ALPHA_TO_COVERAGE) GL.glDisable(GL.GL_DEPTH_TEST) GL.glBlendFunc(GL.GL_SRC_ALPHA, GL.GL_ONE_MINUS_SRC_ALPHA) GL.glEnable(GL.GL_BLEND) # requires PyOpenGL 3.0.2 or later for glGenVertexArrays. - if (self._glMajorVersion >= 3 and hasattr(GL, 'glGenVertexArrays')): + if (self._glslProgram._glMajorVersion >= 3 and hasattr(GL, 'glGenVertexArrays')): if (self._vao == 0): self._vao = GL.glGenVertexArrays(1) GL.glBindVertexArray(self._vao) @@ -665,12 +676,12 @@ def draw(self, qglwidget): tex = qglwidget.bindTexture(group.qimage, GL.GL_TEXTURE_2D, GL.GL_RGBA, QtOpenGL.QGLContext.NoBindOption) - GL.glUniform4f(self._ulocRect, + GL.glUniform4f(self._glslProgram.uniformLocations["rect"], 2*group.x/width - 1, 1 - 2*group.y/height - 2*group.h/height, 2*group.w/width, 2*group.h/height) - GL.glUniform1i(self._ulocTex, 0) + GL.glUniform1i(self._glslProgram.uniformLocations["tex"], 0) GL.glActiveTexture(GL.GL_TEXTURE0) GL.glBindTexture(GL.GL_TEXTURE_2D, tex) GL.glDrawArrays(GL.GL_TRIANGLE_STRIP, 0, 4) @@ -1071,6 +1082,12 @@ def __init__(self, parent=None, bboxCache=None, xformCache=None): self._glPrimitiveGeneratedQuery = None self._glTimeElapsedQuery = None + self._simpleGLSLProgram = None + self._axisVBO = None + self._bboxVBO = None + self._cameraGuidesVBO = None + self._vao = 0 + def InitRenderer(self): '''Create (or re-create) the imager. If you intend to disable rendering for this widget, you MUST have already set @@ -1111,13 +1128,123 @@ def ReloadStage(self, stage): self._cameraIsZup = UsdUtils.GetCamerasAreZup(stage) self.allSceneCameras = None + # simple GLSL program for axis/bbox drawings + def GetSimpleGLSLProgram(self): + if self._simpleGLSLProgram == None: + self._simpleGLSLProgram = GLSLProgram( + """#version 140 + uniform mat4 mvpMatrix; + in vec3 position; + void main() { gl_Position = vec4(position, 1)*mvpMatrix; }""", + """#version 140 + out vec4 outColor; + uniform vec4 color; + void main() { outColor = color; }""", + """#version 120 + uniform mat4 mvpMatrix; + attribute vec3 position; + void main() { gl_Position = vec4(position, 1)*mvpMatrix; }""", + """#version 120 + uniform vec4 color; + void main() { gl_FragColor = color; }""", + ["mvpMatrix", "color"]) + return self._simpleGLSLProgram + + def DrawAxis(self, viewProjectionMatrix): + from OpenGL import GL + import ctypes + + # grab the simple shader + glslProgram = self.GetSimpleGLSLProgram() + if (glslProgram.program == 0): + return + + # vao + if (glslProgram._glMajorVersion >= 3 and hasattr(GL, 'glGenVertexArrays')): + if (self._vao == 0): + self._vao = GL.glGenVertexArrays(1) + GL.glBindVertexArray(self._vao) + + # prep a vbo for axis + if (self._axisVBO is None): + self._axisVBO = GL.glGenBuffers(1) + GL.glBindBuffer(GL.GL_ARRAY_BUFFER, self._axisVBO) + data = [1, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0] + GL.glBufferData(GL.GL_ARRAY_BUFFER, len(data)*4, + (ctypes.c_float*len(data))(*data), GL.GL_STATIC_DRAW) + + GL.glBindBuffer(GL.GL_ARRAY_BUFFER, self._axisVBO) + GL.glEnableVertexAttribArray(0) + GL.glVertexAttribPointer(0, 3, GL.GL_FLOAT, False, 0, ctypes.c_void_p(0)) + + GL.glUseProgram(glslProgram.program) + mvpMatrix = Gf.Matrix4f().SetScale(self._dist/20.0) * viewProjectionMatrix + matrix = (ctypes.c_float*16).from_buffer_copy(mvpMatrix) + GL.glUniformMatrix4fv(glslProgram.uniformLocations["mvpMatrix"], + 1, GL.GL_TRUE, matrix) + + GL.glUniform4f(glslProgram.uniformLocations["color"], 1, 0, 0, 1) + GL.glDrawArrays(GL.GL_LINES, 0, 2) + GL.glUniform4f(glslProgram.uniformLocations["color"], 0, 1, 0, 1) + GL.glDrawArrays(GL.GL_LINES, 2, 2) + GL.glUniform4f(glslProgram.uniformLocations["color"], 0, 0, 1, 1) + GL.glDrawArrays(GL.GL_LINES, 4, 2) + + GL.glDisableVertexAttribArray(0) + GL.glBindBuffer(GL.GL_ARRAY_BUFFER, 0) + GL.glUseProgram(0) + + if (self._vao != 0): + GL.glBindVertexArray(0) + + def DrawBBox(self, viewProjectionMatrix): + from OpenGL import GL + col = self._clearColor + color = Gf.Vec3f(col[0]-.5 if col[0]>0.5 else col[0]+.5, + col[1]-.5 if col[1]>0.5 else col[1]+.5, + col[2]-.5 if col[2]>0.5 else col[2]+.5) + + # Draw axis-aligned bounding box + if self._showAABBox: + bsize = self._selectionBrange.max - self._selectionBrange.min + + trans = Gf.Transform() + trans.SetScale(0.5*bsize) + trans.SetTranslation(self._bbcenterForBoxDraw) + + self.drawWireframeCube(color, + Gf.Matrix4f(trans.GetMatrix()) * viewProjectionMatrix) + + # Draw oriented bounding box + if self._showOBBox: + bsize = self._selectionOrientedRange.max - self._selectionOrientedRange.min + center = bsize / 2. + self._selectionOrientedRange.min + trans = Gf.Transform() + trans.SetScale(0.5*bsize) + trans.SetTranslation(center) + + self.drawWireframeCube(color, + Gf.Matrix4f(trans.GetMatrix()) * + Gf.Matrix4f(self._selectionBBox.matrix) * + viewProjectionMatrix) + # XXX: # First pass at visualizing cameras in usdview-- just oracles for # now. Eventually the logic should live in usdImaging, where the delegate # would add the camera guide geometry to the GL buffers over the course over # its stage traversal, and get time samples accordingly. - def DrawCameraGuides(self): + def DrawCameraGuides(self, mvpMatrix): from OpenGL import GL + import ctypes + + # prep a vbo for camera guides + if (self._cameraGuidesVBO is None): + self._cameraGuidesVBO = GL.glGenBuffers(1) + + GL.glBindBuffer(GL.GL_ARRAY_BUFFER, self._cameraGuidesVBO) + data = [] for camera in self._allSceneCameras: # Don't draw guides for the active camera. if camera == self._cameraPrim or not (camera and camera.IsActive()): @@ -1138,43 +1265,36 @@ def DrawCameraGuides(self): # 7: right top far oraclePoints = frustum.ComputeCorners() - # XXX: - # Grabbed fallback oracleColor from CamCamera. - GL.glColor3f(0.82745, 0.39608, 0.1647) - # Near plane - GL.glBegin(GL.GL_LINE_LOOP) - GL.glVertex3f(*oraclePoints[0]) - GL.glVertex3f(*oraclePoints[1]) - GL.glVertex3f(*oraclePoints[3]) - GL.glVertex3f(*oraclePoints[2]) - GL.glEnd() - - # Far plane - GL.glBegin(GL.GL_LINE_LOOP) - GL.glVertex3f(*oraclePoints[4]) - GL.glVertex3f(*oraclePoints[5]) - GL.glVertex3f(*oraclePoints[7]) - GL.glVertex3f(*oraclePoints[6]) - GL.glEnd() - - # Lines between near and far planes. - GL.glBegin(GL.GL_LINES) - GL.glVertex3f(*oraclePoints[3]) - GL.glVertex3f(*oraclePoints[7]) - GL.glEnd() - GL.glBegin(GL.GL_LINES) - GL.glVertex3f(*oraclePoints[0]) - GL.glVertex3f(*oraclePoints[4]) - GL.glEnd() - GL.glBegin(GL.GL_LINES) - GL.glVertex3f(*oraclePoints[1]) - GL.glVertex3f(*oraclePoints[5]) - GL.glEnd() - GL.glBegin(GL.GL_LINES) - GL.glVertex3f(*oraclePoints[2]) - GL.glVertex3f(*oraclePoints[6]) - GL.glEnd() + indices = [0,1,1,3,3,2,2,0, # Near plane + 4,5,5,7,7,6,6,4, # Far plane + 3,7,0,4,1,5,2,6] # Lines between near and far planes. + data.extend([oraclePoints[i][j] for i in indices for j in range(3)]) + + GL.glBufferData(GL.GL_ARRAY_BUFFER, len(data)*4, + (ctypes.c_float*len(data))(*data), GL.GL_STATIC_DRAW) + + # grab the simple shader + glslProgram = self.GetSimpleGLSLProgram() + if (glslProgram.program == 0): + return + + GL.glEnableVertexAttribArray(0) + GL.glVertexAttribPointer(0, 3, GL.GL_FLOAT, False, 0, ctypes.c_void_p(0)) + + GL.glUseProgram(glslProgram.program) + matrix = (ctypes.c_float*16).from_buffer_copy(mvpMatrix) + GL.glUniformMatrix4fv(glslProgram.uniformLocations["mvpMatrix"], + 1, GL.GL_TRUE, matrix) + # Grabbed fallback oracleColor from CamCamera. + GL.glUniform4f(glslProgram.uniformLocations["color"], + 0.82745, 0.39608, 0.1647, 1) + + GL.glDrawArrays(GL.GL_LINES, 0, len(data)/3) + + GL.glDisableVertexAttribArray(0) + GL.glUseProgram(0) + GL.glBindBuffer(GL.GL_ARRAY_BUFFER, 0) def _updateBboxGuides(self): includedPurposes = set(self._bboxCache.GetIncludedPurposes()) @@ -1427,42 +1547,60 @@ def restoreViewState(self, viewState): self._freeCamera = self._freeCamera.clone() self.update() - - def setupOpenGLViewMatricesForFrustum(self, frustum): + def drawWireframeCube(self, col, mvpMatrix): from OpenGL import GL - import ctypes - GLMtx = ctypes.c_double * 16 - MakeGLMtx = lambda m: GLMtx.from_buffer_copy(m) + import ctypes, itertools - GL.glMatrixMode(GL.GL_PROJECTION) - GL.glLoadIdentity() - GL.glMultMatrixd(MakeGLMtx(frustum.ComputeProjectionMatrix())) + # grab the simple shader + glslProgram = self.GetSimpleGLSLProgram() + if (glslProgram.program == 0): + return + # vao + if (glslProgram._glMajorVersion >= 3 and hasattr(GL, 'glGenVertexArrays')): + if (self._vao == 0): + self._vao = GL.glGenVertexArrays(1) + GL.glBindVertexArray(self._vao) - GL.glMatrixMode(GL.GL_MODELVIEW) - GL.glLoadIdentity() - GL.glMultMatrixd(MakeGLMtx(frustum.ComputeViewMatrix())) + # prep a vbo for bbox + if (self._bboxVBO is None): + self._bboxVBO = GL.glGenBuffers(1) + GL.glBindBuffer(GL.GL_ARRAY_BUFFER, self._bboxVBO) + # create 12 edges + data = [] + p = list(itertools.product([-1,1],[-1,1],[-1,1])) + for i in p: + data.extend([i[0], i[1], i[2]]) + for i in p: + data.extend([i[1], i[2], i[0]]) + for i in p: + data.extend([i[2], i[0], i[1]]) + + GL.glBufferData(GL.GL_ARRAY_BUFFER, len(data)*4, + (ctypes.c_float*len(data))(*data), GL.GL_STATIC_DRAW) + + GL.glBindBuffer(GL.GL_ARRAY_BUFFER, self._bboxVBO) + GL.glEnableVertexAttribArray(0) + GL.glVertexAttribPointer(0, 3, GL.GL_FLOAT, False, 0, ctypes.c_void_p(0)) - def drawWireframeCube(self, size): - from OpenGL import GL + GL.glEnable(GL.GL_LINE_STIPPLE) + GL.glLineStipple(2,0xAAAA) - s = 0.5 * size + GL.glUseProgram(glslProgram.program) + matrix = (ctypes.c_float*16).from_buffer_copy(mvpMatrix) + GL.glUniformMatrix4fv(glslProgram.uniformLocations["mvpMatrix"], + 1, GL.GL_TRUE, matrix) + GL.glUniform4f(glslProgram.uniformLocations["color"], + col[0], col[1], col[2], 1) - GL.glBegin(GL.GL_LINES) - GL.glVertex3f( s, s, s); GL.glVertex3f(-s, s, s) - GL.glVertex3f(-s, s, s); GL.glVertex3f(-s,-s, s) - GL.glVertex3f(-s,-s, s); GL.glVertex3f( s,-s, s) - GL.glVertex3f( s,-s, s); GL.glVertex3f( s, s, s) + GL.glDrawArrays(GL.GL_LINES, 0, 24) - GL.glVertex3f(-s,-s,-s); GL.glVertex3f(-s, s,-s) - GL.glVertex3f(-s, s,-s); GL.glVertex3f( s, s,-s) - GL.glVertex3f( s, s,-s); GL.glVertex3f( s,-s,-s) - GL.glVertex3f( s,-s,-s); GL.glVertex3f(-s,-s,-s) + GL.glDisableVertexAttribArray(0) + GL.glBindBuffer(GL.GL_ARRAY_BUFFER, 0) + GL.glUseProgram(0) - GL.glVertex3f( s, s, s); GL.glVertex3f( s, s,-s) - GL.glVertex3f(-s, s, s); GL.glVertex3f(-s, s,-s) - GL.glVertex3f(-s,-s, s); GL.glVertex3f(-s,-s,-s) - GL.glVertex3f( s,-s, s); GL.glVertex3f( s,-s,-s) - GL.glEnd() + GL.glDisable(GL.GL_LINE_STIPPLE) + if (self._vao != 0): + GL.glBindVertexArray(0) def paintGL(self): if not self._stage or not self._renderer: @@ -1504,6 +1642,9 @@ def paintGL(self): frustum.ComputeProjectionMatrix(), Gf.Vec4d(0, 0, self.size().width(), self.size().height())) + viewProjectionMatrix = Gf.Matrix4f(frustum.ComputeViewMatrix() + * frustum.ComputeProjectionMatrix()) + # XXX: this is redundant for refEngine, but currently hdEngine # doesn't call glViewport. GL.glViewport(0, 0, self.size().width(), self.size().height()) @@ -1602,92 +1743,17 @@ def paintGL(self): self.renderSinglePass(self._renderModeDict[self.renderMode], self.drawSelHighlights) - # Axis bbox drawing - self.setupOpenGLViewMatricesForFrustum(frustum) - - # lights interfere with the correct coloring of bbox and axes - GL.glDisable(GL.GL_LIGHTING) - GL.glDisable(GL.GL_LIGHT0) - GL.glDisable(GL.GL_LIGHT1) - GL.glDisable(GL.GL_LIGHT2) - GL.glDisable(GL.GL_LIGHT3) - - GL.glBegin(GL.GL_LINES) - - GL.glColor3f(1.0,0.0,0.0) - GL.glVertex3f(0.0,0.0,0.0) - GL.glVertex3f(self._dist/20.0,0.0,0.0) - - GL.glColor3f(0.0,1.0,0.0) - GL.glVertex3f(0.0,0.0,0.0) - GL.glVertex3f(0.0,self._dist/20.0,0.0) - - GL.glColor3f(0.0,0.0,1.0) - GL.glVertex3f(0.0,0.0,0.0) - GL.glVertex3f(0.0,0.0,self._dist/20.0) - - GL.glEnd() + self.DrawAxis(viewProjectionMatrix) # XXX: # Draw camera guides-- no support for toggling guide visibility on # individual cameras until we move this logic directly into # usdImaging. if self._displayCameraOracles: - self.DrawCameraGuides() + self.DrawCameraGuides(viewProjectionMatrix) if self._showBBoxes: - col = self._clearColor - - # Draw axis-aligned bounding box - if self._showAABBox: - bsize = self._selectionBrange.max - self._selectionBrange.min - - GL.glPushAttrib(GL.GL_LINE_BIT) - GL.glEnable(GL.GL_LINE_STIPPLE) - GL.glLineStipple(2,0xAAAA) - GL.glColor3f(col[0]-.5 if col[0]>0.5 else col[0]+.5, - col[1]-.5 if col[1]>0.5 else col[1]+.5, - col[2]-.5 if col[2]>0.5 else col[2]+.5) - - GL.glPushMatrix() - - GL.glTranslatef(self._bbcenterForBoxDraw[0], - self._bbcenterForBoxDraw[1], - self._bbcenterForBoxDraw[2]) - GL.glScalef( bsize[0], bsize[1], bsize[2] ) - - self.drawWireframeCube(1.0) - - GL.glPopMatrix() - GL.glPopAttrib() - - # Draw oriented bounding box - if self._showOBBox: - import ctypes - GLMtx = ctypes.c_double * 16 - MakeGLMtx = lambda m: GLMtx.from_buffer_copy(m) - - bsize = self._selectionOrientedRange.max - self._selectionOrientedRange.min - center = bsize / 2. + self._selectionOrientedRange.min - - GL.glPushAttrib(GL.GL_LINE_BIT) - GL.glEnable(GL.GL_LINE_STIPPLE) - GL.glLineStipple(2,0xAAAA) - GL.glColor3f(col[0]-.2 if col[0]>0.5 else col[0]+.2, - col[1]-.2 if col[1]>0.5 else col[1]+.2, - col[2]-.2 if col[2]>0.5 else col[2]+.2) - - GL.glPushMatrix() - GL.glMultMatrixd(MakeGLMtx(self._selectionBBox.matrix)) - - GL.glTranslatef(center[0], center[1], center[2]) - GL.glScalef( bsize[0], bsize[1], bsize[2] ) - - self.drawWireframeCube(1.0) - - GL.glPopMatrix() - GL.glPopAttrib() - + self.DrawBBox(viewProjectionMatrix) else: GL.glClear(GL.GL_COLOR_BUFFER_BIT) From 1b6815ece7e00a251f745fadfb3a92f64a30eb4e Mon Sep 17 00:00:00 2001 From: superfunc Date: Wed, 26 Oct 2016 11:02:38 -0700 Subject: [PATCH 330/380] [Pxr] Add missing dependency (Internal change: 1667633) --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 30b539e13b..c7dc5df90e 100644 --- a/README.md +++ b/README.md @@ -59,6 +59,7 @@ Dependencies | [OpenImageIO](https://sites.google.com/site/openimageio/home) | 1.5.11 | | [Ptex](http://ptex.us/) | 2.0.30 | | [Pyside](http://wiki.qt.io/PySide) | 1.2.2 | +| [PyOpenGL](https://pypi.python.org/pypi/PyOpenGL/3.1.0) | 3.1.0 | Getting and Building the Code From 19fea8138791c65d5197d3fc2a1d6695bfcc8b54 Mon Sep 17 00:00:00 2001 From: screenblaster Date: Wed, 26 Oct 2016 11:02:47 -0700 Subject: [PATCH 331/380] Add 'dependency' to fix CMake build (Internal change: 1667647) --- pxr/usd/lib/pcp/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/pxr/usd/lib/pcp/CMakeLists.txt b/pxr/usd/lib/pcp/CMakeLists.txt index 8a4b680bd3..e28d909e16 100644 --- a/pxr/usd/lib/pcp/CMakeLists.txt +++ b/pxr/usd/lib/pcp/CMakeLists.txt @@ -21,6 +21,7 @@ pxr_shared_library(pcp cache changes composeSite + dependency diagnostic errors instanceKey From 0b5fa94477582a418f3ee55205c68f6917817d58 Mon Sep 17 00:00:00 2001 From: superfunc Date: Wed, 26 Oct 2016 11:02:57 -0700 Subject: [PATCH 332/380] [Arch] Remove explicit global ns scoping. This is being done as preliminary work for the introduction of configurable C++ namespaces into the pxr codebase. For this system to work, we don't want to have explicit global qualifications. This is broken up into per lib changes, so many will follow this doing the same thing. (Internal change: 1667717) --- pxr/base/lib/arch/error.cpp | 2 +- pxr/base/lib/arch/stackTrace.cpp | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/pxr/base/lib/arch/error.cpp b/pxr/base/lib/arch/error.cpp index 1162e18f5c..541252a655 100644 --- a/pxr/base/lib/arch/error.cpp +++ b/pxr/base/lib/arch/error.cpp @@ -36,7 +36,7 @@ Arch_Error(const char* cond, const char* funcName, size_t lineNo, const char* fi fprintf(stderr, " File: %s\n", fileName); fprintf(stderr, " Line: %zu\n", lineNo); abort(); - ::_exit(-1); + _exit(-1); } void diff --git a/pxr/base/lib/arch/stackTrace.cpp b/pxr/base/lib/arch/stackTrace.cpp index f945366220..c0e53f40ba 100644 --- a/pxr/base/lib/arch/stackTrace.cpp +++ b/pxr/base/lib/arch/stackTrace.cpp @@ -988,7 +988,7 @@ ArchLogStackTrace(const std::string& progname, const std::string& reason, #if defined(ARCH_OS_DARWIN) /* - * This function will use ::_LogStackTraceForPid(const char*), which uses + * This function will use _LogStackTraceForPid(const char*), which uses * the stacktrace script, to log the stack to a file. Then it reads the lines * back in and puts them into an output iterator. */ @@ -1000,7 +1000,7 @@ _LogStackTraceToOutputIterator(OutputIterator oi, size_t maxDepth, bool addEndl) char logfile[1024]; _GetStackTraceName(logfile, sizeof(logfile)); - ::_LogStackTraceForPid(logfile); + _LogStackTraceForPid(logfile); ifstream inFile(logfile); string line; @@ -1068,7 +1068,7 @@ ArchPrintStackTrace(ostream& oss, #if defined(ARCH_OS_DARWIN) - ::_LogStackTraceToOutputIterator(ostream_iterator(oss), numeric_limits::max(), true); + _LogStackTraceToOutputIterator(ostream_iterator(oss), numeric_limits::max(), true); #else From 8384ace466116c747428f9cbe91be8517bc110f3 Mon Sep 17 00:00:00 2001 From: superfunc Date: Wed, 26 Oct 2016 11:03:04 -0700 Subject: [PATCH 333/380] [Tf] Remove explicit global ns scoping. (Internal change: 1667718) --- pxr/base/lib/tf/debug.cpp | 2 +- pxr/base/lib/tf/dl.cpp | 16 ++-- pxr/base/lib/tf/mallocTag.cpp | 116 +++++++++++++------------- pxr/base/lib/tf/poolAllocator.cpp | 14 ++-- pxr/base/lib/tf/pyClassMethod.h | 2 +- pxr/base/lib/tf/regTest.cpp | 14 ++-- pxr/base/lib/tf/stringUtils.cpp | 10 +-- pxr/base/lib/tf/testenv/mallocTag.cpp | 14 ++-- pxr/base/lib/tf/testenv/notice.cpp | 16 ++-- pxr/base/lib/tf/wrapRefPtrTracker.cpp | 6 +- 10 files changed, 105 insertions(+), 105 deletions(-) diff --git a/pxr/base/lib/tf/debug.cpp b/pxr/base/lib/tf/debug.cpp index 55409124e6..f8438011fe 100644 --- a/pxr/base/lib/tf/debug.cpp +++ b/pxr/base/lib/tf/debug.cpp @@ -231,7 +231,7 @@ class ARCH_HIDDEN Tf_DebugSymbolRegistry : boost::noncopyable { set debugTokenSet(_debugTokens.begin(), _debugTokens.end()); if (debugTokenSet.count("help")) { - printf("%s", ::_helpMsg); + printf("%s", _helpMsg); exit(0); } diff --git a/pxr/base/lib/tf/dl.cpp b/pxr/base/lib/tf/dl.cpp index 779f4ee164..3a64171a55 100644 --- a/pxr/base/lib/tf/dl.cpp +++ b/pxr/base/lib/tf/dl.cpp @@ -37,13 +37,13 @@ static bool _opening = false, bool Tf_DlOpenIsActive() { - return ::_opening; + return _opening; } bool Tf_DlCloseIsActive() { - return ::_closing; + return _closing; } void* @@ -60,10 +60,10 @@ TfDlopen( (void*)dlerror(); // try to dlopen the dynamic library - bool state = ::_opening; - ::_opening = true; + bool state = _opening; + _opening = true; void* handle = dlopen(filename.c_str(), flag); - ::_opening = state; + _opening = state; TF_DEBUG(TF_DLOPEN).Msg("TfDlopen: [opened] '%s' (handle=%p)\n", filename.c_str(), handle); @@ -97,13 +97,13 @@ TfDlopen( int TfDlclose(void* handle) { - bool state = ::_closing; - ::_closing = true; + bool state = _closing; + _closing = true; TF_DEBUG(TF_DLCLOSE).Msg("TfDlclose: handle = %p\n", handle); int status = dlclose(handle); - ::_closing = state; + _closing = state; return status; } diff --git a/pxr/base/lib/tf/mallocTag.cpp b/pxr/base/lib/tf/mallocTag.cpp index 0cbf1333a9..b28ec142d4 100644 --- a/pxr/base/lib/tf/mallocTag.cpp +++ b/pxr/base/lib/tf/mallocTag.cpp @@ -550,7 +550,7 @@ Tf_MallocGlobalData::_MatchesTraceName(const std::string& name) static bool Tf_MatchesMallocTagTraceName(const string& name) { - return ::_mallocGlobalData->_MatchesTraceName(name); + return _mallocGlobalData->_MatchesTraceName(name); } void @@ -615,7 +615,7 @@ Tf_MallocGlobalData::_MatchesDebugName(const std::string& name) static bool Tf_MatchesMallocTagDebugName(const string& name) { - return ::_mallocGlobalData->_MatchesDebugName(name); + return _mallocGlobalData->_MatchesDebugName(name); } namespace { @@ -885,7 +885,7 @@ TfMallocTag::_ShouldNotTag(TfMallocTag::_ThreadData** tptr, _Tagging* statePtr) } // Helper function to retrieve the current path node from a _ThreadData -// object. Note that ::_mallocGlobalData->_mutex must be locked before calling +// object. Note that _mallocGlobalData->_mutex must be locked before calling // this function. inline Tf_MallocPathNode* TfMallocTag::_GetCurrentPathNodeNoLock(const TfMallocTag::_ThreadData* tptr) @@ -897,7 +897,7 @@ TfMallocTag::_GetCurrentPathNodeNoLock(const TfMallocTag::_ThreadData* tptr) // If the _ThreadData does not have any entries in its tag stack, return // the global root so that any memory allocations are assigned to that // node. - return ::_mallocGlobalData->_rootNode; + return _mallocGlobalData->_rootNode; } void @@ -905,7 +905,7 @@ TfMallocTag::SetDebugMatchList(const std::string& matchList) { if (TfMallocTag::IsInitialized()) { tbb::spin_mutex::scoped_lock lock(::_mallocGlobalData->_mutex); - ::_mallocGlobalData->_SetDebugNames(matchList); + _mallocGlobalData->_SetDebugNames(matchList); } } @@ -914,7 +914,7 @@ TfMallocTag::SetCapturedMallocStacksMatchList(const std::string& matchList) { if (TfMallocTag::IsInitialized()) { tbb::spin_mutex::scoped_lock lock(::_mallocGlobalData->_mutex); - ::_mallocGlobalData->_SetTraceNames(matchList); + _mallocGlobalData->_SetTraceNames(matchList); } } @@ -948,7 +948,7 @@ TfMallocTag::GetCapturedMallocStacks() void* TfMallocTag::_MallocWrapper(size_t nBytes, const void*) { - void* ptr = ::_mallocHook.Malloc(nBytes); + void* ptr = _mallocHook.Malloc(nBytes); _ThreadData* td; if (_ShouldNotTag(&td) or ARCH_UNLIKELY(not ptr)) @@ -963,12 +963,12 @@ TfMallocTag::_MallocWrapper(size_t nBytes, const void*) // Update malloc global data with bookkeeping information. This has to // happen while the mutex is held. if (_mallocGlobalData->_RegisterPathNodeForBlock(node, ptr, blockSize)) { - ::_mallocGlobalData->_CaptureMallocStack(node, ptr, blockSize); + _mallocGlobalData->_CaptureMallocStack(node, ptr, blockSize); node->_totalBytes += blockSize; node->_numAllocations++; node->_callSite->_totalBytes += blockSize; - ::_mallocGlobalData->_totalBytes += blockSize; + _mallocGlobalData->_totalBytes += blockSize; _mallocGlobalData->_maxTotalBytes = std::max(_mallocGlobalData->_totalBytes, @@ -999,7 +999,7 @@ TfMallocTag::_ReallocWrapper(void* oldPtr, size_t nBytes, const void*) { /* * If ptr is NULL, we want to make sure we don't double count, - * because a call to ::_mallocHook.Realloc(ptr, nBytes) could call + * because a call to _mallocHook.Realloc(ptr, nBytes) could call * through to our malloc. To avoid this, we'll explicitly short-circuit * ourselves rather than trust that the malloc library will do it. */ @@ -1017,7 +1017,7 @@ TfMallocTag::_ReallocWrapper(void* oldPtr, size_t nBytes, const void*) // If tagState is _TaggingDormant, we still need to unregister the oldPtr. // However, we won't need to register the newly realloc'd ptr later on. if (tagState == _TaggingDisabled) { - return ::_mallocHook.Realloc(oldPtr, nBytes); + return _mallocHook.Realloc(oldPtr, nBytes); } void* newPtr = NULL; @@ -1029,21 +1029,21 @@ TfMallocTag::_ReallocWrapper(void* oldPtr, size_t nBytes, const void*) size_t bytesFreed = info.blockSize; Tf_MallocPathNode* oldNode = - ::_mallocGlobalData->_allPathNodes[info.pathNodeIndex]; + _mallocGlobalData->_allPathNodes[info.pathNodeIndex]; _mallocGlobalData->_RunDebugHookForNode(oldNode, oldPtr, bytesFreed); // Check if we should release a malloc stack. This has to happen // while the mutex is held. - ::_mallocGlobalData->_ReleaseMallocStack(oldNode, oldPtr); + _mallocGlobalData->_ReleaseMallocStack(oldNode, oldPtr); oldNode->_totalBytes -= bytesFreed; oldNode->_numAllocations -= (_DECREMENT_ALLOCATION_COUNTS) ? 1 : 0; oldNode->_callSite->_totalBytes -= bytesFreed; - ::_mallocGlobalData->_totalBytes -= bytesFreed; + _mallocGlobalData->_totalBytes -= bytesFreed; } - newPtr = ::_mallocHook.Realloc(oldPtr, nBytes); + newPtr = _mallocHook.Realloc(oldPtr, nBytes); if (shouldNotTag or ARCH_UNLIKELY(not newPtr)) return newPtr; @@ -1056,13 +1056,13 @@ TfMallocTag::_ReallocWrapper(void* oldPtr, size_t nBytes, const void*) if (::_mallocGlobalData->_RegisterPathNodeForBlock( newNode, newPtr, blockSize)) { - ::_mallocGlobalData->_CaptureMallocStack( + _mallocGlobalData->_CaptureMallocStack( newNode, newPtr, blockSize); newNode->_totalBytes += blockSize; newNode->_numAllocations++; newNode->_callSite->_totalBytes += blockSize; - ::_mallocGlobalData->_totalBytes += blockSize; + _mallocGlobalData->_totalBytes += blockSize; _mallocGlobalData->_maxTotalBytes = std::max(_mallocGlobalData->_totalBytes, @@ -1084,7 +1084,7 @@ TfMallocTag::_ReallocWrapper(void* oldPtr, size_t nBytes, const void*) void* TfMallocTag::_MemalignWrapper(size_t alignment, size_t nBytes, const void*) { - void* ptr = ::_mallocHook.Memalign(alignment, nBytes); + void* ptr = _mallocHook.Memalign(alignment, nBytes); _ThreadData* td; if (_ShouldNotTag(&td) or ARCH_UNLIKELY(not ptr)) @@ -1097,13 +1097,13 @@ TfMallocTag::_MemalignWrapper(size_t alignment, size_t nBytes, const void*) // Update malloc global data with bookkeeping information. This has to // happen while the mutex is held. - ::_mallocGlobalData->_RegisterPathNodeForBlock(node, ptr, blockSize); - ::_mallocGlobalData->_CaptureMallocStack(node, ptr, blockSize); + _mallocGlobalData->_RegisterPathNodeForBlock(node, ptr, blockSize); + _mallocGlobalData->_CaptureMallocStack(node, ptr, blockSize); node->_totalBytes += blockSize; node->_numAllocations++; node->_callSite->_totalBytes += blockSize; - ::_mallocGlobalData->_totalBytes += blockSize; + _mallocGlobalData->_totalBytes += blockSize; _mallocGlobalData->_maxTotalBytes = std::max(_mallocGlobalData->_totalBytes, _mallocGlobalData->_maxTotalBytes); @@ -1125,7 +1125,7 @@ TfMallocTag::_FreeWrapper(void* ptr, const void*) _ThreadData* td; _Tagging tagState; if (_ShouldNotTag(&td, &tagState) and tagState == _TaggingDisabled) { - ::_mallocHook.Free(ptr); + _mallocHook.Free(ptr); return; } @@ -1135,27 +1135,27 @@ TfMallocTag::_FreeWrapper(void* ptr, const void*) if (::_mallocGlobalData->_UnregisterPathNodeForBlock(ptr, &info)) { size_t bytesFreed = info.blockSize; Tf_MallocPathNode* node = - ::_mallocGlobalData->_allPathNodes[info.pathNodeIndex]; + _mallocGlobalData->_allPathNodes[info.pathNodeIndex]; - ::_mallocGlobalData->_RunDebugHookForNode(node, ptr, bytesFreed); + _mallocGlobalData->_RunDebugHookForNode(node, ptr, bytesFreed); // Check if we should release a malloc stack. This has to happen // while the mutex is held. - ::_mallocGlobalData->_ReleaseMallocStack(node, ptr); + _mallocGlobalData->_ReleaseMallocStack(node, ptr); node->_totalBytes -= bytesFreed; node->_numAllocations -= (_DECREMENT_ALLOCATION_COUNTS) ? 1 : 0; node->_callSite->_totalBytes -= bytesFreed; - ::_mallocGlobalData->_totalBytes -= bytesFreed; + _mallocGlobalData->_totalBytes -= bytesFreed; } - ::_mallocHook.Free(ptr); + _mallocHook.Free(ptr); } void* TfMallocTag::_MallocWrapper_ptmalloc(size_t nBytes, const void*) { - void* ptr = ::_mallocHook.Malloc(nBytes); + void* ptr = _mallocHook.Malloc(nBytes); _ThreadData* td; if (_ShouldNotTag(&td)) @@ -1169,12 +1169,12 @@ TfMallocTag::_MallocWrapper_ptmalloc(size_t nBytes, const void*) // Check if we should capture a malloc stack. This has to happen while // the mutex is held. - ::_mallocGlobalData->_CaptureMallocStack(node, ptr, actualBytes); + _mallocGlobalData->_CaptureMallocStack(node, ptr, actualBytes); node->_totalBytes += actualBytes; node->_numAllocations++; node->_callSite->_totalBytes += actualBytes; - ::_mallocGlobalData->_totalBytes += actualBytes; + _mallocGlobalData->_totalBytes += actualBytes; _mallocGlobalData->_maxTotalBytes = std::max(_mallocGlobalData->_totalBytes, _mallocGlobalData->_maxTotalBytes); @@ -1189,7 +1189,7 @@ TfMallocTag::_ReallocWrapper_ptmalloc(void* oldPtr, size_t nBytes, const void*) { /* * If ptr is NULL, we want to make sure we don't double count, - * because a call to ::_mallocHook.Realloc(ptr, nBytes) could call + * because a call to _mallocHook.Realloc(ptr, nBytes) could call * through to our malloc. To avoid this, we'll explicitly short-circuit * ourselves rather than trust that the malloc library will do it. */ @@ -1204,7 +1204,7 @@ TfMallocTag::_ReallocWrapper_ptmalloc(void* oldPtr, size_t nBytes, const void*) size_t bytesFreed; _ExtractIndexAndGetSize(oldPtr, &bytesFreed, &index); - void* newPtr = ::_mallocHook.Realloc(oldPtr, nBytes); + void* newPtr = _mallocHook.Realloc(oldPtr, nBytes); _ThreadData* td; if (_ShouldNotTag(&td)) @@ -1217,28 +1217,28 @@ TfMallocTag::_ReallocWrapper_ptmalloc(void* oldPtr, size_t nBytes, const void*) _StoreIndexAndGetSize(newPtr, &actualBytes, newNode->_index); if (index) { - Tf_MallocPathNode* oldNode = ::_mallocGlobalData->_allPathNodes[index]; + Tf_MallocPathNode* oldNode = _mallocGlobalData->_allPathNodes[index]; _mallocGlobalData->_RunDebugHookForNode(oldNode, oldPtr, bytesFreed); // Check if we should release a malloc stack. This has to happen while // the mutex is held. - ::_mallocGlobalData->_ReleaseMallocStack(oldNode, oldPtr); + _mallocGlobalData->_ReleaseMallocStack(oldNode, oldPtr); oldNode->_totalBytes -= bytesFreed; oldNode->_numAllocations -= (_DECREMENT_ALLOCATION_COUNTS) ? 1 : 0; oldNode->_callSite->_totalBytes -= bytesFreed; - ::_mallocGlobalData->_totalBytes -= bytesFreed; + _mallocGlobalData->_totalBytes -= bytesFreed; } // Check if we should capture a malloc stack. This has to happen while // the mutex is held. - ::_mallocGlobalData->_CaptureMallocStack(newNode, newPtr, actualBytes); + _mallocGlobalData->_CaptureMallocStack(newNode, newPtr, actualBytes); newNode->_totalBytes += actualBytes; newNode->_numAllocations++; newNode->_callSite->_totalBytes += actualBytes; - ::_mallocGlobalData->_totalBytes += actualBytes; + _mallocGlobalData->_totalBytes += actualBytes; _mallocGlobalData->_maxTotalBytes = std::max(_mallocGlobalData->_totalBytes, _mallocGlobalData->_maxTotalBytes); @@ -1251,7 +1251,7 @@ TfMallocTag::_ReallocWrapper_ptmalloc(void* oldPtr, size_t nBytes, const void*) void* TfMallocTag::_MemalignWrapper_ptmalloc(size_t alignment, size_t nBytes, const void*) { - void* ptr = ::_mallocHook.Memalign(alignment, nBytes); + void* ptr = _mallocHook.Memalign(alignment, nBytes); _ThreadData* td; if (_ShouldNotTag(&td)) @@ -1265,12 +1265,12 @@ TfMallocTag::_MemalignWrapper_ptmalloc(size_t alignment, size_t nBytes, const vo // Check if we should capture a malloc stack. This has to happen while // the mutex is held. - ::_mallocGlobalData->_CaptureMallocStack(node, ptr, actualBytes); + _mallocGlobalData->_CaptureMallocStack(node, ptr, actualBytes); node->_totalBytes += actualBytes; node->_numAllocations++; node->_callSite->_totalBytes += actualBytes; - ::_mallocGlobalData->_totalBytes += actualBytes; + _mallocGlobalData->_totalBytes += actualBytes; _mallocGlobalData->_maxTotalBytes = std::max(_mallocGlobalData->_totalBytes, _mallocGlobalData->_maxTotalBytes); @@ -1295,21 +1295,21 @@ TfMallocTag::_FreeWrapper_ptmalloc(void* ptr, const void*) if (index && TfMallocTag::_doTagging) { tbb::spin_mutex::scoped_lock lock(::_mallocGlobalData->_mutex); - Tf_MallocPathNode* node = ::_mallocGlobalData->_allPathNodes[index]; + Tf_MallocPathNode* node = _mallocGlobalData->_allPathNodes[index]; - ::_mallocGlobalData->_RunDebugHookForNode(node, ptr, bytesFreed); + _mallocGlobalData->_RunDebugHookForNode(node, ptr, bytesFreed); // Check if we should release a malloc stack. This has to happen // while the mutex is held. - ::_mallocGlobalData->_ReleaseMallocStack(node, ptr); + _mallocGlobalData->_ReleaseMallocStack(node, ptr); node->_totalBytes -= bytesFreed; node->_numAllocations -= (_DECREMENT_ALLOCATION_COUNTS) ? 1 : 0; node->_callSite->_totalBytes -= bytesFreed; - ::_mallocGlobalData->_totalBytes -= bytesFreed; + _mallocGlobalData->_totalBytes -= bytesFreed; } - ::_mallocHook.Free(ptr); + _mallocHook.Free(ptr); } bool @@ -1329,7 +1329,7 @@ TfMallocTag::GetCallTree(CallTree* tree, bool skipRepeated) tree->root.siteName.clear(); tree->root.children.clear(); - if (Tf_MallocGlobalData* gd = ::_mallocGlobalData) { + if (Tf_MallocGlobalData* gd = _mallocGlobalData) { TfMallocTag::_TemporaryTaggingState tmpState(_TaggingDisabled); gd->_mutex.lock(); @@ -1368,7 +1368,7 @@ TfMallocTag::GetTotalBytes() return 0; tbb::spin_mutex::scoped_lock lock(::_mallocGlobalData->_mutex); - return ::_mallocGlobalData->_totalBytes; + return _mallocGlobalData->_totalBytes; } size_t @@ -1378,7 +1378,7 @@ TfMallocTag::GetMaxTotalBytes() return 0; tbb::spin_mutex::scoped_lock lock(::_mallocGlobalData->_mutex); - return ::_mallocGlobalData->_maxTotalBytes; + return _mallocGlobalData->_maxTotalBytes; } void @@ -1401,24 +1401,24 @@ TfMallocTag::_Initialize(std::string* errMsg) * need to lock anything. */ TF_AXIOM(!::_mallocGlobalData); - ::_mallocGlobalData = new Tf_MallocGlobalData(); + _mallocGlobalData = new Tf_MallocGlobalData(); // Note that we are *not* using the _TemporaryTaggingState object // here. We explicitly want the tagging set to enabled as the end // of this function so that all subsequent memory allocations are captured. _SetTagging(_TaggingDisabled); - bool usePtmalloc = ::_UsePtmalloc(); + bool usePtmalloc = _UsePtmalloc(); if (usePtmalloc) { // index 0 is reserved for untracked malloc/free's: - ::_mallocGlobalData->_allPathNodes.push_back(NULL); + _mallocGlobalData->_allPathNodes.push_back(NULL); } - Tf_MallocCallSite* site = ::_mallocGlobalData->_GetOrCreateCallSite("__root"); + Tf_MallocCallSite* site = _mallocGlobalData->_GetOrCreateCallSite("__root"); Tf_MallocPathNode* rootNode = new Tf_MallocPathNode(site); - ::_mallocGlobalData->_rootNode = rootNode; - (void) ::_mallocGlobalData->_RegisterPathNode(rootNode); + _mallocGlobalData->_rootNode = rootNode; + (void) _mallocGlobalData->_RegisterPathNode(rootNode); TfMallocTag::Tls::Find()->_tagStack.reserve(64); TfMallocTag::Tls::Find()->_tagStack.push_back(rootNode); @@ -1427,14 +1427,14 @@ TfMallocTag::_Initialize(std::string* errMsg) TfMallocTag::_doTagging = true; if (usePtmalloc) { - return ::_mallocHook.Initialize(_MallocWrapper_ptmalloc, + return _mallocHook.Initialize(_MallocWrapper_ptmalloc, _ReallocWrapper_ptmalloc, _MemalignWrapper_ptmalloc, _FreeWrapper_ptmalloc, errMsg); } else { - return ::_mallocHook.Initialize(_MallocWrapper, + return _mallocHook.Initialize(_MallocWrapper, _ReallocWrapper, _MemalignWrapper, _FreeWrapper, @@ -1462,7 +1462,7 @@ TfMallocTag::Auto::_Begin(const char* name) { tbb::spin_mutex::scoped_lock lock(::_mallocGlobalData->_mutex); - site = ::_mallocGlobalData->_GetOrCreateCallSite(name); + site = _mallocGlobalData->_GetOrCreateCallSite(name); if (_threadData->_callSiteOnStack.size() <= site->_index) { if (_threadData->_callSiteOnStack.capacity() == 0) @@ -1472,7 +1472,7 @@ TfMallocTag::Auto::_Begin(const char* name) if (_threadData->_tagStack.empty()) - thisNode = ::_mallocGlobalData->_rootNode->_GetOrCreateChild(site); + thisNode = _mallocGlobalData->_rootNode->_GetOrCreateChild(site); else thisNode = _threadData->_tagStack.back()->_GetOrCreateChild(site); diff --git a/pxr/base/lib/tf/poolAllocator.cpp b/pxr/base/lib/tf/poolAllocator.cpp index b11d123b77..f9d790f842 100644 --- a/pxr/base/lib/tf/poolAllocator.cpp +++ b/pxr/base/lib/tf/poolAllocator.cpp @@ -118,7 +118,7 @@ typedef std::pair _ChunkRecord; * Used by std::sort */ static bool -_RecordComparison (::_ChunkRecord a, ::_ChunkRecord b) +_RecordComparison (::_ChunkRecord a, _ChunkRecord b) { return a.first < b.first; } @@ -138,12 +138,12 @@ _AddressInChunk(void* addr, void* start, size_t bytesPerChunk) /* * Return v[i] owning addr. */ -static ::_ChunkRecord* +static _ChunkRecord* _LocateOwner(::_ChunkRecord v[], size_t n, void* addr, size_t bytesPerChunk) { TF_AXIOM(n > 0); - ::_ChunkRecord* owner = NULL; + _ChunkRecord* owner = NULL; if (n < 5) { for (size_t i = 0; i < n; i++) { @@ -212,13 +212,13 @@ TfPoolAllocator::Reclaim() chunksFreed = 0, nChunks = _chunks.size(); - ::_ChunkRecord* v = new ::_ChunkRecord[nChunks]; + _ChunkRecord* v = new _ChunkRecord[nChunks]; for (size_t i = 0; i < nChunks; i++) - v[i] = ::_ChunkRecord(_chunks[i], itemsPerChunk); + v[i] = _ChunkRecord(_chunks[i], itemsPerChunk); std::sort(&v[0], &v[nChunks], &::_RecordComparison); for (_PoolNode* node = _freeList; node; node = node->next) // (2) - ::_LocateOwner(v, nChunks, node, _bytesPerChunk)->second--; + _LocateOwner(v, nChunks, node, _bytesPerChunk)->second--; _PoolNode dummyNode; // (3) @@ -238,7 +238,7 @@ TfPoolAllocator::Reclaim() _chunks.clear(); // (4) for (size_t i = 0; i < nChunks; i++) { if (v[i].second == 0) { - :: delete [] reinterpret_cast(v[i].first); + delete [] reinterpret_cast(v[i].first); chunksFreed++; } else diff --git a/pxr/base/lib/tf/pyClassMethod.h b/pxr/base/lib/tf/pyClassMethod.h index 325427f684..4c146e9d71 100644 --- a/pxr/base/lib/tf/pyClassMethod.h +++ b/pxr/base/lib/tf/pyClassMethod.h @@ -65,7 +65,7 @@ struct _TfPyClassMethod : def_visitor<_TfPyClassMethod> if (PyCallable_Check(expect_non_null(callable))) return callable; - ::PyErr_Format( PyExc_TypeError, + PyErr_Format( PyExc_TypeError, "classmethod expects callable object; got an object of type %s, " "which is not callable", callable->ob_type->tp_name); diff --git a/pxr/base/lib/tf/regTest.cpp b/pxr/base/lib/tf/regTest.cpp index 977912bc99..2fca0c0957 100644 --- a/pxr/base/lib/tf/regTest.cpp +++ b/pxr/base/lib/tf/regTest.cpp @@ -118,36 +118,36 @@ TfRegTest::_Main(int argc, char *argv[]) string progName(argv[0]); if (argc < 2) { - ::_Usage(progName); + _Usage(progName); _PrintTestNames(); return 2; } if (argc < 2) { - ::_Usage(progName); + _Usage(progName); _PrintTestNames(); return 2; } - ::_testName = argv[1]; + _testName = argv[1]; if (_functionTable.find(::_testName) != _functionTable.end()) { if (argc > 2) { - cerr << progName << ": test function '" << ::_testName + cerr << progName << ": test function '" << _testName << "' takes no arguments." << endl; return 2; } TfErrorMark m; - return ::_HandleErrors(m, (*_functionTable[::_testName])()); + return _HandleErrors(m, (*_functionTable[::_testName])()); } else if (_functionTableWithArgs.find(::_testName) != _functionTableWithArgs.end()) { TfErrorMark m; - return ::_HandleErrors(m, + return _HandleErrors(m, (*_functionTableWithArgs[::_testName])(argc-1, argv+1)); } else { - cerr << progName << ": unknown test function " << ::_testName << ".\n"; + cerr << progName << ": unknown test function " << _testName << ".\n"; _PrintTestNames(); return 3; } diff --git a/pxr/base/lib/tf/stringUtils.cpp b/pxr/base/lib/tf/stringUtils.cpp index 18b4076266..e42ad2c899 100644 --- a/pxr/base/lib/tf/stringUtils.cpp +++ b/pxr/base/lib/tf/stringUtils.cpp @@ -509,7 +509,7 @@ TfQuotedStringTokenize(const string &source, const char *delimiters, quote.erase(); token.erase(); - while ((quoteIndex = ::_FindFirstOfNotEscaped(source, quotes, i)) < + while ((quoteIndex = _FindFirstOfNotEscaped(source, quotes, i)) < (delimIndex = source.find_first_of(delimiters, i))) { // Push the token from 'i' until the first quote. @@ -520,7 +520,7 @@ TfQuotedStringTokenize(const string &source, const char *delimiters, // escaped with a preceding backslash. j = quoteIndex; quote = source[j]; - j = ::_FindFirstOfNotEscaped(source, quote.c_str(), j + 1); + j = _FindFirstOfNotEscaped(source, quote.c_str(), j + 1); // If we've reached the end of the string, then we are // missing an end-quote. @@ -865,7 +865,7 @@ TfEscapeStringReplaceChar(const char** c, char** out) char n(0); size_t nd(0); for (nd = 0; isxdigit(*++(*c)); ++nd) - n = ((n * 16) + ::_HexToDecimal(**c)); + n = ((n * 16) + _HexToDecimal(**c)); --(*c); *(*out)++ = n; break; @@ -875,8 +875,8 @@ TfEscapeStringReplaceChar(const char** c, char** out) { char n(0); size_t nd(0); - for (nd = 0; ((nd < 3) && ::_IsOctalDigit(**c)); ++nd) - n = ((n * 8) + ::_OctalToDecimal(*(*c)++)); + for (nd = 0; ((nd < 3) && _IsOctalDigit(**c)); ++nd) + n = ((n * 8) + _OctalToDecimal(*(*c)++)); --(*c); *(*out)++ = n; break; diff --git a/pxr/base/lib/tf/testenv/mallocTag.cpp b/pxr/base/lib/tf/testenv/mallocTag.cpp index d7581017c3..136d1ca6e7 100644 --- a/pxr/base/lib/tf/testenv/mallocTag.cpp +++ b/pxr/base/lib/tf/testenv/mallocTag.cpp @@ -52,8 +52,8 @@ static void MyMalloc(size_t n) { void* ptr = malloc(n); std::lock_guard lock(_mutex); - ::_requests.push_back(ptr); - ::_total += n; + _requests.push_back(ptr); + _total += n; if (_total > _maxTotal) { _maxTotal = _total; } @@ -61,10 +61,10 @@ MyMalloc(size_t n) { static void FreeAll() { - for (size_t i = 0; i < ::_requests.size(); i++) + for (size_t i = 0; i < _requests.size(); i++) free(::_requests[i]); - ::_requests.clear(); - ::_total = 0; + _requests.clear(); + _total = 0; } @@ -120,7 +120,7 @@ static bool CloseEnough(int64_t a1, int64_t a2) { static bool MemCheck() { - int64_t m = ::_total, + int64_t m = _total, current = TfMallocTag::GetTotalBytes(); bool ok = CloseEnough(m, current); @@ -278,7 +278,7 @@ Test_TfMallocTag() if (!runme) return true; - ::_requests.reserve(1024); + _requests.reserve(1024); TF_AXIOM(TfMallocTag::GetTotalBytes() == 0); TF_AXIOM(MemCheck()); diff --git a/pxr/base/lib/tf/testenv/notice.cpp b/pxr/base/lib/tf/testenv/notice.cpp index 14edbc8986..9fd8f5f64e 100644 --- a/pxr/base/lib/tf/testenv/notice.cpp +++ b/pxr/base/lib/tf/testenv/notice.cpp @@ -205,14 +205,14 @@ void WorkTask() { ArchNap(10); - ::_DumpLog(&workerThreadLog, &workerThreadList, &workerThreadLock); + _DumpLog(&workerThreadLog, &workerThreadList, &workerThreadLock); workListener->Revoke(); workerThreadLog << "// WorkListener should not respond\n"; WorkerNotice("WorkerNotice 2").Send(); - ::_DumpLog(&workerThreadLog, &workerThreadList, &workerThreadLock); + _DumpLog(&workerThreadLog, &workerThreadList, &workerThreadLock); delete workListener; } @@ -235,19 +235,19 @@ _TestThreadedNotices() mainListener->Revoke(); - ::_DumpLog(&mainThreadLog, &mainThreadList, &mainThreadLock); + _DumpLog(&mainThreadLog, &mainThreadList, &mainThreadLock); mainThreadLog << "// MainListener::ProcessNotice should respond once\n"; MainNotice("Main notice 2").Send(); - ::_DumpLog(&mainThreadLog, &mainThreadList, &mainThreadLock); + _DumpLog(&mainThreadLog, &mainThreadList, &mainThreadLock); delete mainListener; mainThreadLog << "// MainListener should not respond\n"; MainNotice("main: Error!").Send(); - ::_DumpLog(&mainThreadLog, &mainThreadList, &mainThreadLock); + _DumpLog(&mainThreadLog, &mainThreadList, &mainThreadLock); cout << "\n--- Main Thread Log ---\n"; cout << mainThreadLog.str(); @@ -486,11 +486,11 @@ Test_TfNotice() printf("// Expect: nothing\n"); TestNotice("error!").Send(); - ::_TestThreadedNotices(); + _TestThreadedNotices(); - ::_TestSpoofedNotices(); + _TestSpoofedNotices(); - ::_TestNoticeBlock(); + _TestNoticeBlock(); return true; } diff --git a/pxr/base/lib/tf/wrapRefPtrTracker.cpp b/pxr/base/lib/tf/wrapRefPtrTracker.cpp index a265489467..ed4ba278c0 100644 --- a/pxr/base/lib/tf/wrapRefPtrTracker.cpp +++ b/pxr/base/lib/tf/wrapRefPtrTracker.cpp @@ -69,8 +69,8 @@ wrapRefPtrTracker() class_("RefPtrTracker", no_init) .def(TfPySingleton()) - .def("GetAllWatchedCountsReport", ::_ReportAllWatchedCounts) - .def("GetAllTracesReport", ::_ReportAllTraces) - .def("GetTracesReportForWatched", ::_ReportTracesForWatched) + .def("GetAllWatchedCountsReport", _ReportAllWatchedCounts) + .def("GetAllTracesReport", _ReportAllTraces) + .def("GetTracesReportForWatched", _ReportTracesForWatched) ; } From ac54093d00257ed65c21f307e3ee44ca66cce606 Mon Sep 17 00:00:00 2001 From: superfunc Date: Wed, 26 Oct 2016 11:03:12 -0700 Subject: [PATCH 334/380] [Plug] Remove explicit global ns scoping. (Internal change: 1667720) --- pxr/base/lib/plug/wrapPlugin.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pxr/base/lib/plug/wrapPlugin.cpp b/pxr/base/lib/plug/wrapPlugin.cpp index c8c06c5e46..1b86ac415e 100644 --- a/pxr/base/lib/plug/wrapPlugin.cpp +++ b/pxr/base/lib/plug/wrapPlugin.cpp @@ -74,7 +74,7 @@ void wrapPlugin() .add_property("isPythonModule", &This::IsPythonModule) .add_property("isResource", &This::IsResource) - .add_property("metadata", ::_GetMetadata) + .add_property("metadata", _GetMetadata) .add_property("name", make_function(&This::GetName, @@ -86,7 +86,7 @@ void wrapPlugin() make_function(&This::GetResourcePath, return_value_policy())) - .def("GetMetadataForType", ::_GetMetadataForType) + .def("GetMetadataForType", _GetMetadataForType) .def("DeclaresType", &This::DeclaresType, (arg("type"), arg("includeSubclasses") = false)) From d7a87cf39b407b00ed8bb7cc78d0ad03b3215976 Mon Sep 17 00:00:00 2001 From: superfunc Date: Wed, 26 Oct 2016 11:03:16 -0700 Subject: [PATCH 335/380] [Gf] Remove explicit global ns scoping. (Internal change: 1667721) --- pxr/base/lib/gf/colorRamp.cpp | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/pxr/base/lib/gf/colorRamp.cpp b/pxr/base/lib/gf/colorRamp.cpp index 7e111de6f8..da14f17d0f 100644 --- a/pxr/base/lib/gf/colorRamp.cpp +++ b/pxr/base/lib/gf/colorRamp.cpp @@ -148,18 +148,18 @@ _ShapeColorInterpExperiment( * target slope. */ if (alpha < slide) { - Cret[i] = ::_Stramp(alpha, - 0.,slide, - c0,cMid, - 0.,slope, - width0,widthMid0); + Cret[i] = _Stramp(alpha, + 0.,slide, + c0,cMid, + 0.,slope, + width0,widthMid0); } else { - Cret[i] = ::_Stramp(alpha, - slide,1., - cMid,c1, - slope,0., - widthMid1,width1); + Cret[i] = _Stramp(alpha, + slide,1., + cMid,c1, + slope,0., + widthMid1,width1); } } From ae3407b222f5d5b709c6fc7dfe2280c08bd8bf21 Mon Sep 17 00:00:00 2001 From: superfunc Date: Wed, 26 Oct 2016 11:03:20 -0700 Subject: [PATCH 336/380] [Sdf] Remove explicit global ns scoping. (Internal change: 1667722) --- pxr/usd/lib/sdf/wrapLayerOffset.cpp | 2 +- pxr/usd/lib/sdf/wrapPath.cpp | 2 +- pxr/usd/lib/sdf/wrapPayload.cpp | 2 +- pxr/usd/lib/sdf/wrapReference.cpp | 2 +- pxr/usd/lib/sdf/wrapTypes.cpp | 8 ++++---- 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/pxr/usd/lib/sdf/wrapLayerOffset.cpp b/pxr/usd/lib/sdf/wrapLayerOffset.cpp index e040fd3897..f1257ce1ef 100644 --- a/pxr/usd/lib/sdf/wrapLayerOffset.cpp +++ b/pxr/usd/lib/sdf/wrapLayerOffset.cpp @@ -81,7 +81,7 @@ void wrapLayerOffset() .def( self * self ) .def( self * double() ) - .def("__repr__", ::_Repr) + .def("__repr__", _Repr) ; diff --git a/pxr/usd/lib/sdf/wrapPath.cpp b/pxr/usd/lib/sdf/wrapPath.cpp index 082f43997c..d9f05cd5f4 100644 --- a/pxr/usd/lib/sdf/wrapPath.cpp +++ b/pxr/usd/lib/sdf/wrapPath.cpp @@ -278,7 +278,7 @@ void wrapPath() { .def(self > self) .def(self <= self) .def(self >= self) - .def("__repr__", ::_Repr) + .def("__repr__", _Repr) .def("__hash__", &This::GetHash) ; diff --git a/pxr/usd/lib/sdf/wrapPayload.cpp b/pxr/usd/lib/sdf/wrapPayload.cpp index a4aa92396b..40a56f613a 100644 --- a/pxr/usd/lib/sdf/wrapPayload.cpp +++ b/pxr/usd/lib/sdf/wrapPayload.cpp @@ -86,7 +86,7 @@ void wrapPayload() .def(self <= self) .def(self >= self) - .def("__repr__", ::_Repr) + .def("__repr__", _Repr) ; diff --git a/pxr/usd/lib/sdf/wrapReference.cpp b/pxr/usd/lib/sdf/wrapReference.cpp index c0092fc96d..d3be9dcb17 100644 --- a/pxr/usd/lib/sdf/wrapReference.cpp +++ b/pxr/usd/lib/sdf/wrapReference.cpp @@ -119,7 +119,7 @@ void wrapReference() .def(self <= self) .def(self >= self) - .def("__repr__", ::_Repr) + .def("__repr__", _Repr) ; diff --git a/pxr/usd/lib/sdf/wrapTypes.cpp b/pxr/usd/lib/sdf/wrapTypes.cpp index 4c2bc9f27e..21cab7dbc7 100644 --- a/pxr/usd/lib/sdf/wrapTypes.cpp +++ b/pxr/usd/lib/sdf/wrapTypes.cpp @@ -417,8 +417,8 @@ void wrapTypes() .def(self == self) .def(self != self) - .def("__repr__", ::_UnregisteredValueRepr) - .def("__hash__", ::_UnregisteredValueHash) + .def("__repr__", _UnregisteredValueRepr) + .def("__hash__", _UnregisteredValueHash) ; VtValueFromPython(); @@ -525,7 +525,7 @@ void wrapTypes() class_("ValueBlock") .def(self == self) .def(self != self) - .def("__repr__", ::_SdfValueBlockRepr) - .def("__hash__", ::_SdfValueBlockHash); + .def("__repr__", _SdfValueBlockRepr) + .def("__hash__", _SdfValueBlockHash); VtValueFromPython(); } From db98d73f0b4cb7c08f2e3773f1e421c6f67caf65 Mon Sep 17 00:00:00 2001 From: superfunc Date: Wed, 26 Oct 2016 11:03:27 -0700 Subject: [PATCH 337/380] [Usd] Remove explicit global ns scoping. (Internal change: 1667724) --- pxr/usd/lib/usd/stage.cpp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/pxr/usd/lib/usd/stage.cpp b/pxr/usd/lib/usd/stage.cpp index 5363954be8..3af3484d66 100644 --- a/pxr/usd/lib/usd/stage.cpp +++ b/pxr/usd/lib/usd/stage.cpp @@ -371,7 +371,7 @@ UsdStage::UsdStage(const SdfLayerRefPtr& rootLayer, _mallocTagID = TfMallocTag::IsInitialized() ? strdup(::_StageTag(rootLayer->GetIdentifier()).c_str()) : - ::_dormantMallocTagID; + _dormantMallocTagID; _cache->SetVariantFallbacks(GetGlobalVariantFallbacks()); } @@ -383,7 +383,7 @@ UsdStage::~UsdStage() _rootLayer ? _rootLayer->GetIdentifier().c_str() : "", _sessionLayer ? _sessionLayer->GetIdentifier().c_str() : ""); Close(); - if (_mallocTagID != ::_dormantMallocTagID){ + if (_mallocTagID != _dormantMallocTagID){ free(const_cast(_mallocTagID)); } } @@ -497,7 +497,7 @@ UsdStage::_InstantiateStage(const SdfLayerRefPtr &rootLayer, boost::optional tag; if (TfMallocTag::IsInitialized()){ - tag = boost::in_place("Usd", ::_StageTag(rootLayer->GetIdentifier())); + tag = boost::in_place("Usd", _StageTag(rootLayer->GetIdentifier())); } // Debug timing info @@ -565,7 +565,7 @@ _CreateNewLayer(const std::string &identifier) UsdStageRefPtr UsdStage::CreateNew(const std::string& identifier) { - TfAutoMallocTag2 tag("Usd", ::_StageTag(identifier)); + TfAutoMallocTag2 tag("Usd", _StageTag(identifier)); if (SdfLayerRefPtr layer = _CreateNewLayer(identifier)) return Open(layer, _CreateAnonymousSessionLayer(layer)); @@ -577,7 +577,7 @@ UsdStageRefPtr UsdStage::CreateNew(const std::string& identifier, const SdfLayerHandle& sessionLayer) { - TfAutoMallocTag2 tag("Usd", ::_StageTag(identifier)); + TfAutoMallocTag2 tag("Usd", _StageTag(identifier)); if (SdfLayerRefPtr layer = _CreateNewLayer(identifier)) return Open(layer, sessionLayer); @@ -589,7 +589,7 @@ UsdStageRefPtr UsdStage::CreateNew(const std::string& identifier, const ArResolverContext& pathResolverContext) { - TfAutoMallocTag2 tag("Usd", ::_StageTag(identifier)); + TfAutoMallocTag2 tag("Usd", _StageTag(identifier)); if (SdfLayerRefPtr layer = _CreateNewLayer(identifier)) return Open(layer, pathResolverContext); @@ -602,7 +602,7 @@ UsdStage::CreateNew(const std::string& identifier, const SdfLayerHandle& sessionLayer, const ArResolverContext& pathResolverContext) { - TfAutoMallocTag2 tag("Usd", ::_StageTag(identifier)); + TfAutoMallocTag2 tag("Usd", _StageTag(identifier)); if (SdfLayerRefPtr layer = _CreateNewLayer(identifier)) return Open(layer, sessionLayer, pathResolverContext); @@ -687,7 +687,7 @@ _OpenLayer( UsdStageRefPtr UsdStage::Open(const std::string& filePath, InitialLoadSet load) { - TfAutoMallocTag2 tag("Usd", ::_StageTag(filePath)); + TfAutoMallocTag2 tag("Usd", _StageTag(filePath)); SdfLayerRefPtr rootLayer = _OpenLayer(filePath); if (not rootLayer) { @@ -703,7 +703,7 @@ UsdStage::Open(const std::string& filePath, const ArResolverContext& pathResolverContext, InitialLoadSet load) { - TfAutoMallocTag2 tag("Usd", ::_StageTag(filePath)); + TfAutoMallocTag2 tag("Usd", _StageTag(filePath)); SdfLayerRefPtr rootLayer = _OpenLayer(filePath, pathResolverContext); if (not rootLayer) { From 2e52583c1e4dc2b492e1f3084dd6f6f7477e6893 Mon Sep 17 00:00:00 2001 From: superfunc Date: Wed, 26 Oct 2016 11:03:30 -0700 Subject: [PATCH 338/380] [Pcp] Remove explicit global ns scoping. (Internal change: 1667725) --- pxr/usd/lib/pcp/diagnostic.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pxr/usd/lib/pcp/diagnostic.cpp b/pxr/usd/lib/pcp/diagnostic.cpp index 20b2b9196b..5dcaf7c607 100644 --- a/pxr/usd/lib/pcp/diagnostic.cpp +++ b/pxr/usd/lib/pcp/diagnostic.cpp @@ -553,13 +553,13 @@ Pcp_GraphOutputManager::_OutputGraph() const _nextGraphFileIndex++; // Write the graph and label out to the file. - ::_WriteGraphHeader(f); + _WriteGraphHeader(f); f << "\tlabel = <" << currentGraph.dotGraphLabel << ">\n"; f << "\tlabelloc = b\n"; f << currentGraph.dotGraph; - ::_WriteGraphFooter(f); + _WriteGraphFooter(f); } void @@ -579,7 +579,7 @@ Pcp_GraphOutputManager::_UpdateCurrentDotGraph() std::stringstream ss; - ::_WriteGraph( + _WriteGraph( ss, currentGraph.index->GetRootNode(), /* includeInheritOriginInfo = */ true, From 5f1d755be59d79bfcd61bc82940fe2c0e1b2c863 Mon Sep 17 00:00:00 2001 From: blevin Date: Wed, 26 Oct 2016 11:03:34 -0700 Subject: [PATCH 339/380] Pcp: Now that we can cull nodes that have variant selections (see commit 6645f2f) we no longer need the hasVariantSelections flag. (Internal change: 1667792) --- pxr/usd/lib/pcp/diagnostic.cpp | 2 -- pxr/usd/lib/pcp/node.cpp | 3 --- pxr/usd/lib/pcp/node.h | 5 ----- pxr/usd/lib/pcp/primIndex.cpp | 19 ------------------- pxr/usd/lib/pcp/primIndex_Graph.h | 5 ----- 5 files changed, 34 deletions(-) diff --git a/pxr/usd/lib/pcp/diagnostic.cpp b/pxr/usd/lib/pcp/diagnostic.cpp index 5dcaf7c607..3d5b30109d 100644 --- a/pxr/usd/lib/pcp/diagnostic.cpp +++ b/pxr/usd/lib/pcp/diagnostic.cpp @@ -129,8 +129,6 @@ std::string Pcp_Dump( _GetString(node.HasSpecs())); s += TfStringPrintf(" Has symmetry: %s\n", _GetString(node.HasSymmetry())); - s += TfStringPrintf(" Has variant selection: %s\n", - _GetString(node.HasVariantSelections())); const SdfPrimSpecHandleVector* specs = TfMapLookupPtr(nodeToPrimSpecs, node); diff --git a/pxr/usd/lib/pcp/node.cpp b/pxr/usd/lib/pcp/node.cpp index fc495f0b42..0850191a23 100644 --- a/pxr/usd/lib/pcp/node.cpp +++ b/pxr/usd/lib/pcp/node.cpp @@ -122,9 +122,6 @@ PCP_DEFINE_GET_API(const PcpMapExpression&, GetMapToParent, mapToParent); PCP_DEFINE_GET_API(const PcpMapExpression&, GetMapToRoot, mapToRoot); PCP_DEFINE_API(bool, HasSymmetry, SetHasSymmetry, smallInts.hasSymmetry); -PCP_DEFINE_API( - bool, HasVariantSelections, SetHasVariantSelections, - smallInts.hasVariantSelections); PCP_DEFINE_API(SdfPermission, GetPermission, SetPermission, smallInts.permission); PCP_DEFINE_API(bool, IsCulled, SetCulled, smallInts.culled); PCP_DEFINE_API(bool, IsRestricted, SetRestricted, smallInts.permissionDenied); diff --git a/pxr/usd/lib/pcp/node.h b/pxr/usd/lib/pcp/node.h index d57a11f92b..9df148a1e3 100644 --- a/pxr/usd/lib/pcp/node.h +++ b/pxr/usd/lib/pcp/node.h @@ -201,11 +201,6 @@ class PcpNodeRef : void SetHasSymmetry(bool hasSymmetry); bool HasSymmetry() const; - /// Get/set whether this node provides any variant selection opinions, - /// either directly or from a namespace ancestor. - void SetHasVariantSelections(bool hasVariantSelections); - bool HasVariantSelections() const; - /// Get/set the permission for this node. This indicates whether specs /// on this node can be accessed from other nodes. void SetPermission(SdfPermission perm); diff --git a/pxr/usd/lib/pcp/primIndex.cpp b/pxr/usd/lib/pcp/primIndex.cpp index 86f9b6b698..83479cd031 100644 --- a/pxr/usd/lib/pcp/primIndex.cpp +++ b/pxr/usd/lib/pcp/primIndex.cpp @@ -1295,9 +1295,6 @@ _AddArc( // Determine whether this node has any symmetry information. newNode.SetHasSymmetry(PcpComposeSiteHasSymmetry(site)); } - - newNode.SetHasVariantSelections( - PcpComposeSiteHasVariantSelections(site)); } PCP_GRAPH_UPDATE( @@ -2659,7 +2656,6 @@ _PropagateNodeToParent( if (newNode) { newNode.SetInert(srcNode.IsInert()); newNode.SetHasSymmetry(srcNode.HasSymmetry()); - newNode.SetHasVariantSelections(srcNode.HasVariantSelections()); newNode.SetPermission(srcNode.GetPermission()); newNode.SetRestricted(srcNode.IsRestricted()); @@ -2899,14 +2895,6 @@ _ComposeVariantSelectionForNode( node.GetPath()); } - // XXX: We should be able to skip this computation by checking - // PcpNodeRef::HasVariantSelections here, but we need to be - // careful about the case where site != node.GetSite(). I - // think the logic should be: - // if (site.layerStack == node.GetLayerStack() and - // site.path.HasPrefix(node.GetPath()) and - // not node.HasVariantSelections()) { return false; } - if (PcpComposeSiteVariantSelection(site, vset, vsel)) { *nodeWithVsel = node; return true; @@ -3657,13 +3645,6 @@ _ConvertNodeForChild( node.SetHasSymmetry(PcpComposeSiteHasSymmetry(node.GetSite())); } } - - // If the parent had variant selections, it will be inherited by - // the child. Otherwise, we recompute it here. - if (not node.HasVariantSelections()) { - node.SetHasVariantSelections( - PcpComposeSiteHasVariantSelections(node.GetSite())); - } } // Arbitrary-order traversal. diff --git a/pxr/usd/lib/pcp/primIndex_Graph.h b/pxr/usd/lib/pcp/primIndex_Graph.h index 10a7d40f22..b2cfd2130f 100644 --- a/pxr/usd/lib/pcp/primIndex_Graph.h +++ b/pxr/usd/lib/pcp/primIndex_Graph.h @@ -252,7 +252,6 @@ class PcpPrimIndex_Graph /* The equivalent initializations to the memset(). , permission(SdfPermissionPublic) , hasSymmetry(false) - , hasVariantSelections(false) , inert(false) , culled(false) , permissionDenied(false) @@ -309,10 +308,6 @@ class PcpPrimIndex_Graph // or at any of its namespace ancestors contain symmetry // information. bool hasSymmetry:1; - // Whether this node contains variant selections. This implies - // that prims at this node's site or at any of its namespace - // ancestors contain variant selections. - bool hasVariantSelections:1; // Whether this node is inert. This is set to true in cases // where a node is needed to represent a structural dependency // but no opinions are allowed to be added. From 1aaa67a6aef484dfb9f57eeb60d249c2e17744e5 Mon Sep 17 00:00:00 2001 From: mattyjams Date: Wed, 26 Oct 2016 11:04:20 -0700 Subject: [PATCH 340/380] add GetTerminals() method to UsdShadeSubgraph for getting all terminals of a subgraph (Internal change: 1668043) --- pxr/usd/lib/usdShade/schema.usda | 1 + pxr/usd/lib/usdShade/subgraph.cpp | 23 +++++++++++++++++++++-- pxr/usd/lib/usdShade/subgraph.h | 5 +++++ pxr/usd/lib/usdShade/wrapSubgraph.cpp | 3 +++ 4 files changed, 30 insertions(+), 2 deletions(-) diff --git a/pxr/usd/lib/usdShade/schema.usda b/pxr/usd/lib/usdShade/schema.usda index 88498b7082..db522b9488 100644 --- a/pxr/usd/lib/usdShade/schema.usda +++ b/pxr/usd/lib/usdShade/schema.usda @@ -51,6 +51,7 @@ class Subgraph "Subgraph" ( string extraIncludes = """ #include #include "pxr/usd/usd/editTarget.h" +#include "pxr/usd/usd/relationship.h" #include "pxr/usd/usdShade/interfaceAttribute.h" #include "pxr/usd/usdShade/parameter.h" """ diff --git a/pxr/usd/lib/usdShade/subgraph.cpp b/pxr/usd/lib/usdShade/subgraph.cpp index 503aae2670..4f4003947b 100644 --- a/pxr/usd/lib/usdShade/subgraph.cpp +++ b/pxr/usd/lib/usdShade/subgraph.cpp @@ -117,7 +117,8 @@ UsdShadeSubgraph::GetSchemaAttributeNames(bool includeInherited) TF_DEFINE_PRIVATE_TOKENS( _tokens, (subgraph) - ((terminal, "terminal:")) + ((TerminalNamespaceName, "terminal")) + ((TerminalNamespacePrefix, "terminal:")) ); @@ -181,7 +182,7 @@ UsdShadeSubgraph::GetInterfaceAttributes( static TfToken _GetTerminalRelName(const TfToken& name) { - return TfToken(_tokens->terminal.GetString() + name.GetString()); + return TfToken(_tokens->TerminalNamespacePrefix.GetString() + name.GetString()); } UsdRelationship @@ -213,3 +214,21 @@ UsdShadeSubgraph::GetTerminal( const TfToken& relName = _GetTerminalRelName(terminalName); return prim.GetRelationship(relName); } + +UsdRelationshipVector +UsdShadeSubgraph::GetTerminals() const +{ + UsdRelationshipVector terminals; + + const UsdPrim& prim = GetPrim(); + const std::vector& terminalNamespaceProperties = + prim.GetPropertiesInNamespace(_tokens->TerminalNamespaceName.GetString()); + + for (const UsdProperty& property : terminalNamespaceProperties) { + if (const UsdRelationship& relationship = property.As()) { + terminals.push_back(relationship); + } + } + + return terminals; +} diff --git a/pxr/usd/lib/usdShade/subgraph.h b/pxr/usd/lib/usdShade/subgraph.h index 6c7bfab742..80fee2dd23 100644 --- a/pxr/usd/lib/usdShade/subgraph.h +++ b/pxr/usd/lib/usdShade/subgraph.h @@ -32,6 +32,7 @@ #include #include "pxr/usd/usd/editTarget.h" +#include "pxr/usd/usd/relationship.h" #include "pxr/usd/usdShade/interfaceAttribute.h" #include "pxr/usd/usdShade/parameter.h" @@ -239,6 +240,10 @@ class UsdShadeSubgraph : public UsdTyped /// UsdRelationship GetTerminal( const TfToken& terminalName) const; + + /// Get all terminals of a subgraph + /// + UsdRelationshipVector GetTerminals() const; }; #endif diff --git a/pxr/usd/lib/usdShade/wrapSubgraph.cpp b/pxr/usd/lib/usdShade/wrapSubgraph.cpp index bc6b743f8f..bb3bc56738 100644 --- a/pxr/usd/lib/usdShade/wrapSubgraph.cpp +++ b/pxr/usd/lib/usdShade/wrapSubgraph.cpp @@ -115,5 +115,8 @@ WRAP_CUSTOM { .def("GetTerminal", &UsdShadeSubgraph::GetTerminal, (arg("terminalName"))) + .def("GetTerminals", + &UsdShadeSubgraph::GetTerminals, + return_value_policy()) ; } From 8a30425453abd574f503e1150cfe9a0986a043e9 Mon Sep 17 00:00:00 2001 From: takahito-tejima Date: Wed, 26 Oct 2016 11:04:27 -0700 Subject: [PATCH 341/380] [garch] fixing GL context corruption in GarchGLDebugWindow when GLF_ENABLE_DEBUG_OUTPUT is false, GarchGLPlatformDebugContext silently returns and doesn't make current any GL contexts. There was a bug in the GLX implementation which destroys GL context even in that case. (Internal change: 1668060) --- .../lib/garch/glPlatformDebugContext.cpp | 1 + .../lib/garch/glPlatformDebugWindowGLX.cpp | 26 ++++++++++++++----- .../lib/garch/glPlatformDebugWindowGLX.h | 3 ++- 3 files changed, 23 insertions(+), 7 deletions(-) diff --git a/pxr/imaging/lib/garch/glPlatformDebugContext.cpp b/pxr/imaging/lib/garch/glPlatformDebugContext.cpp index 9e96b6a652..e72eebe90e 100644 --- a/pxr/imaging/lib/garch/glPlatformDebugContext.cpp +++ b/pxr/imaging/lib/garch/glPlatformDebugContext.cpp @@ -219,6 +219,7 @@ GarchGLPlatformDebugContext::~GarchGLPlatformDebugContext() void GarchGLPlatformDebugContext::makeCurrent() { + // note: if not enabled, returns without making context current. if (not GarchGLPlatformDebugContext::IsEnabledDebugOutput()) { return; } diff --git a/pxr/imaging/lib/garch/glPlatformDebugWindowGLX.cpp b/pxr/imaging/lib/garch/glPlatformDebugWindowGLX.cpp index b2c4909c60..b6ff688096 100644 --- a/pxr/imaging/lib/garch/glPlatformDebugWindowGLX.cpp +++ b/pxr/imaging/lib/garch/glPlatformDebugWindowGLX.cpp @@ -37,6 +37,7 @@ Garch_GLPlatformDebugWindow::Garch_GLPlatformDebugWindow(GarchGLDebugWindow *w) : _running(false) , _callback(w) , _display(NULL) + , _glContext(NULL) { } @@ -101,10 +102,15 @@ Garch_GLPlatformDebugWindow::Init(const char *title, GLXContext tmpCtx = glXCreateContextAttribsARB(_display, fbc[0], 0, true, attribs); glXMakeCurrent(_display, _window, tmpCtx); - // switch to the debug context - _glContext.reset(new GarchGLPlatformDebugContext(4, 5, true, true)); - _glContext->makeCurrent(); - glXDestroyContext(_display, tmpCtx); + if (GarchGLPlatformDebugContext::IsEnabledDebugOutput()) { + // switch to the debug context + _glDebugContext.reset(new GarchGLPlatformDebugContext(4, 5, true, true)); + _glDebugContext->makeCurrent(); + glXDestroyContext(_display, tmpCtx); + } else { + // continue to use the GL context + _glContext = tmpCtx; + } _callback->OnInitializeGL(); } @@ -178,7 +184,11 @@ Garch_GLPlatformDebugWindow::Run() } } } - _glContext->makeCurrent(); + if (_glDebugContext) { + _glDebugContext->makeCurrent(); + } else { + glXMakeCurrent(_display, _window, _glContext); + } // XXX: this should be constant interval _callback->OnIdle(); @@ -192,7 +202,11 @@ Garch_GLPlatformDebugWindow::Run() _callback->OnUninitializeGL(); glXMakeCurrent(_display, 0, 0); - _glContext.reset(); + if (_glDebugContext) { + _glDebugContext.reset(); + } else { + glXDestroyContext(_display, _glContext); + } XDestroyWindow(_display, _window); XCloseDisplay(_display); } diff --git a/pxr/imaging/lib/garch/glPlatformDebugWindowGLX.h b/pxr/imaging/lib/garch/glPlatformDebugWindowGLX.h index 08370c6fb5..e1ca674604 100644 --- a/pxr/imaging/lib/garch/glPlatformDebugWindowGLX.h +++ b/pxr/imaging/lib/garch/glPlatformDebugWindowGLX.h @@ -47,7 +47,8 @@ class Garch_GLPlatformDebugWindow GarchGLDebugWindow *_callback; Display *_display; Window _window; - boost::scoped_ptr _glContext; + GLXContext _glContext; + boost::scoped_ptr _glDebugContext; }; #endif // GARCH_GLPLATFORM_DEBUG_WINDOW_GLX_H From 8dbf89127b808e17ed653267a630591bfe0ef02f Mon Sep 17 00:00:00 2001 From: blevin Date: Wed, 26 Oct 2016 11:04:36 -0700 Subject: [PATCH 342/380] Follow-up to change 1667509: Usd actualy does want to process dependent paths that do not have PcpCache entries, since e.g. it does not cache PcpPropertyIndex entries. (Internal change: 1668175) --- pxr/usd/lib/usd/stage.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pxr/usd/lib/usd/stage.cpp b/pxr/usd/lib/usd/stage.cpp index 3af3484d66..97da5104d7 100644 --- a/pxr/usd/lib/usd/stage.cpp +++ b/pxr/usd/lib/usd/stage.cpp @@ -2832,7 +2832,7 @@ _AddDependentPaths(const SdfLayerHandle &layer, const SdfPath &path, cache.FindDependentPaths(layer, path, depTypes, /* recurseOnSite */ true, /* recurseOnIndex */ true, - /* filterForExistingCachesOnly */ true)) { + /* filterForExistingCachesOnly */ false)) { output->insert(dep.indexPath); } From 17b2bc79ab24329b14c681c88fce882adc414e1e Mon Sep 17 00:00:00 2001 From: blevin Date: Wed, 26 Oct 2016 11:05:14 -0700 Subject: [PATCH 343/380] Address review notes -- add comments. (Internal change: 1668179) --- pxr/usd/lib/usd/stage.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/pxr/usd/lib/usd/stage.cpp b/pxr/usd/lib/usd/stage.cpp index 97da5104d7..857491c879 100644 --- a/pxr/usd/lib/usd/stage.cpp +++ b/pxr/usd/lib/usd/stage.cpp @@ -2827,12 +2827,15 @@ _AddDependentPaths(const SdfLayerHandle &layer, const SdfPath &path, // We include virtual dependencies so that we can process // changes like adding missing defaultPrim metadata. const PcpDependencyFlags depTypes = PcpDependencyTypeAnyIncludingVirtual; + // Do not filter dependencies against the indexes cached in PcpCache, + // because Usd does not cache PcpPropertyIndex entries. + const bool filterForExistingCachesOnly = false; for (const PcpDependency& dep: cache.FindDependentPaths(layer, path, depTypes, /* recurseOnSite */ true, /* recurseOnIndex */ true, - /* filterForExistingCachesOnly */ false)) { + filterForExistingCachesOnly)) { output->insert(dep.indexPath); } From c4e9633f8a2eec0316f4b2e55ebe680e786e1bc4 Mon Sep 17 00:00:00 2001 From: sunyab Date: Wed, 26 Oct 2016 11:05:22 -0700 Subject: [PATCH 344/380] Add missing wrapDependency.cpp to CMakeLists.txt (Internal change: 1668202) --- pxr/usd/lib/pcp/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/pxr/usd/lib/pcp/CMakeLists.txt b/pxr/usd/lib/pcp/CMakeLists.txt index e28d909e16..7a6ff5be26 100644 --- a/pxr/usd/lib/pcp/CMakeLists.txt +++ b/pxr/usd/lib/pcp/CMakeLists.txt @@ -60,6 +60,7 @@ pxr_shared_library(pcp PYMODULE_CPPFILES module.cpp wrapCache.cpp + wrapDependency.cpp wrapErrors.cpp wrapInstanceKey.cpp wrapPrimIndex.cpp From ede400a8bc9e788169c9e2c1267a3d9fa34ad533 Mon Sep 17 00:00:00 2001 From: pixar-oss Date: Wed, 26 Oct 2016 11:05:31 -0700 Subject: [PATCH 345/380] Early exit for model/assembly-related checks that aren't meant to be performed on master prims or within the master prim hierarchy. (Internal change: 1668226) --- third_party/katana/lib/usdKatana/utils.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/third_party/katana/lib/usdKatana/utils.cpp b/third_party/katana/lib/usdKatana/utils.cpp index e6880243d8..8680cd06b9 100644 --- a/third_party/katana/lib/usdKatana/utils.cpp +++ b/third_party/katana/lib/usdKatana/utils.cpp @@ -1030,7 +1030,7 @@ PxrUsdKatanaUtils::ConvertUsdMaterialPathToKatLocation( bool PxrUsdKatanaUtils::ModelGroupIsAssembly(const UsdPrim &prim) { - if (not (prim.IsGroup() and prim.GetParent())) + if (not (prim.IsGroup() and prim.GetParent()) or prim.IsInMaster()) return false; // XXX with bug/102670, this test will be trivial: prim.IsAssembly() @@ -1086,7 +1086,7 @@ PxrUsdKatanaUtils::ModelGroupNeedsProxy(const UsdPrim &prim) bool PxrUsdKatanaUtils::IsModelAssemblyOrComponent(const UsdPrim& prim) { - if (not prim.IsModel()) { + if (not prim.IsModel() or prim.IsInMaster()) { return false; } @@ -1167,7 +1167,7 @@ PxrUsdKatanaUtils::IsAttributeVarying(const UsdAttribute& attr, double currentT std::string PxrUsdKatanaUtils::GetModelInstanceName(const UsdPrim& prim) { - if (not prim) { + if (not prim or prim.IsInMaster()) { return std::string(); } From 3865571be125e8c753dd48acf03aae7fdd08ea44 Mon Sep 17 00:00:00 2001 From: George ElKoura Date: Wed, 26 Oct 2016 22:18:57 -0700 Subject: [PATCH 346/380] Starting work on appveyor support. --- appveyor.yml | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 appveyor.yml diff --git a/appveyor.yml b/appveyor.yml new file mode 100644 index 0000000000..15e5a0b854 --- /dev/null +++ b/appveyor.yml @@ -0,0 +1,24 @@ + +clone_folder: c:\projects\USD + +branches: + only: + - dev_win_ip_g + +platform: + - x64 + +configuration: + - 14 2015 + +build_script: + - cd c:\projects\OpenSubdiv + - mkdir build + - cd build + - cmake --version + - cmake -G "Visual Studio %Configuration%" \ + -D "PXR_BUILD_ALEMBIC_PLUGIN:bool=FALSE" \ + -D "PXR_BUILD_KATANA_PLUGIN:bool=FALSE" \ + -D "PXR_BUILD_MAYA_PLUGIN:bool=FALSE" \ + .. + - cmake --build . --config Release From aeda6ce96641033662230fa1db417b3c87b79278 Mon Sep 17 00:00:00 2001 From: George ElKoura Date: Wed, 26 Oct 2016 22:22:06 -0700 Subject: [PATCH 347/380] Oops, fixed yyp path. --- appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/appveyor.yml b/appveyor.yml index 15e5a0b854..ac074f3e14 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -12,7 +12,7 @@ configuration: - 14 2015 build_script: - - cd c:\projects\OpenSubdiv + - cd c:\projects\USD - mkdir build - cd build - cmake --version From 7bb3741b93e733f5dc459b3fddbcdac4b45ae841 Mon Sep 17 00:00:00 2001 From: George ElKoura Date: Wed, 26 Oct 2016 22:29:00 -0700 Subject: [PATCH 348/380] Add boost discovery for appveyor. --- appveyor.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/appveyor.yml b/appveyor.yml index ac074f3e14..dbf4ad1d4b 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -20,5 +20,8 @@ build_script: -D "PXR_BUILD_ALEMBIC_PLUGIN:bool=FALSE" \ -D "PXR_BUILD_KATANA_PLUGIN:bool=FALSE" \ -D "PXR_BUILD_MAYA_PLUGIN:bool=FALSE" \ + -D "BOOST_ROOT:string=c:/Libraries/boost_1_62_0" \ + -D "BOOST_LIBRARYDIR:string=c:/Libraries/boost_1_62_0/lib64-msvc-14.0" \ + -D "Boost_USE_STATIC_LIBS:INT=0" \ .. - cmake --build . --config Release From 95df078076db91b81e13662a5b008ac9fb7445b5 Mon Sep 17 00:00:00 2001 From: George ElKoura Date: Wed, 26 Oct 2016 22:42:15 -0700 Subject: [PATCH 349/380] Merge error fix. --- pxr/usd/lib/pcp/statistics.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pxr/usd/lib/pcp/statistics.cpp b/pxr/usd/lib/pcp/statistics.cpp index 0ad525b90b..03b5bb78b1 100644 --- a/pxr/usd/lib/pcp/statistics.cpp +++ b/pxr/usd/lib/pcp/statistics.cpp @@ -352,9 +352,9 @@ class Pcp_Statistics sizeof(PcpPrimIndex_Graph) == 88, "PcpPrimIndex_Graph must be of size 88 or 104"); -#endif static_assert(sizeof(PcpPrimIndex_Graph::_Node) == 40, "PcpPrimIndex_Graph::_Node must be of size 40"); +#endif static_assert(sizeof(PcpPrimIndex_Graph::_SharedData) == 32, "PcpPrimIndex_Graph::_SharedData must be of size 32"); From 03c1947622f417724b7de8fe68e91cd4fd4f7353 Mon Sep 17 00:00:00 2001 From: George ElKoura Date: Wed, 26 Oct 2016 22:49:26 -0700 Subject: [PATCH 350/380] Build double-conversion. --- appveyor.yml | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index dbf4ad1d4b..8deb100626 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -12,16 +12,30 @@ configuration: - 14 2015 build_script: + + # double-conversion + - git clone https://github.com/google/double-conversion.git c:/projects/double-conversion + - cd c:\projects\double-conversion + - mkdir bld + - cd bld + - cmake -G "Visual Studio %Configuration%" .. + - cmake --build . --config Release + + + # USD - cd c:\projects\USD - mkdir build + - dir C:/Libraries/boost_1_59_0 - cd build - cmake --version - cmake -G "Visual Studio %Configuration%" \ -D "PXR_BUILD_ALEMBIC_PLUGIN:bool=FALSE" \ -D "PXR_BUILD_KATANA_PLUGIN:bool=FALSE" \ -D "PXR_BUILD_MAYA_PLUGIN:bool=FALSE" \ - -D "BOOST_ROOT:string=c:/Libraries/boost_1_62_0" \ - -D "BOOST_LIBRARYDIR:string=c:/Libraries/boost_1_62_0/lib64-msvc-14.0" \ + -D "BOOST_ROOT:string=c:/Libraries/boost_1_59_0" \ + -D "BOOST_LIBRARYDIR:string=c:/Libraries/boost_1_59_0/lib64-msvc-14.0" \ -D "Boost_USE_STATIC_LIBS:INT=0" \ + -D "DOUBLE_CONVERSION_LIBRARY:string=c:/projects/double-conversion/bld/double-conversion/Release/double-conversion.lib" \ + -D "DOUBLE_CONVERSION_INCLUDE_DIR:string=c:/projects/double-conversion" \ .. - cmake --build . --config Release From 140d214435627c2c2af959891b5f7a419b4c84f9 Mon Sep 17 00:00:00 2001 From: George ElKoura Date: Wed, 26 Oct 2016 22:51:29 -0700 Subject: [PATCH 351/380] Fix for appveyor --- appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/appveyor.yml b/appveyor.yml index 8deb100626..dfe4dd0b9c 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -25,7 +25,7 @@ build_script: # USD - cd c:\projects\USD - mkdir build - - dir C:/Libraries/boost_1_59_0 + - dir c:\Libraries\boost_1_59_0 - cd build - cmake --version - cmake -G "Visual Studio %Configuration%" \ From 466ac563b0da0567ef4c1a2d81336519bae7c675 Mon Sep 17 00:00:00 2001 From: George ElKoura Date: Wed, 26 Oct 2016 23:13:00 -0700 Subject: [PATCH 352/380] Attempt at getting TBB. --- appveyor.yml | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/appveyor.yml b/appveyor.yml index dfe4dd0b9c..5654bd81b7 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -21,11 +21,17 @@ build_script: - cmake -G "Visual Studio %Configuration%" .. - cmake --build . --config Release + # TBB + - cd c:\projects + - mkdir tbb44 + - appveyor DownloadFile https://www.threadingbuildingblocks.org/sites/default/files/software_releases/windows/tbb44_20160526oss_win_0.zip -FileName tbb.zip + - 7z x tbb.zip + - dir + # USD - cd c:\projects\USD - mkdir build - - dir c:\Libraries\boost_1_59_0 - cd build - cmake --version - cmake -G "Visual Studio %Configuration%" \ From 8e0a8a53f8926986413c4baed91deb9f428f17a0 Mon Sep 17 00:00:00 2001 From: George ElKoura Date: Wed, 26 Oct 2016 23:13:32 -0700 Subject: [PATCH 353/380] More fixes from the last merge. --- pxr/usd/lib/pcp/wrapDependency.cpp | 3 ++- pxr/usd/lib/usd/stage.cpp | 4 ---- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/pxr/usd/lib/pcp/wrapDependency.cpp b/pxr/usd/lib/pcp/wrapDependency.cpp index a653f9c7f3..98b6ba8528 100644 --- a/pxr/usd/lib/pcp/wrapDependency.cpp +++ b/pxr/usd/lib/pcp/wrapDependency.cpp @@ -21,11 +21,12 @@ // KIND, either express or implied. See the Apache License for the specific // language governing permissions and limitations under the Apache License. // +#include + #include "pxr/usd/pcp/dependency.h" #include "pxr/base/tf/pyEnum.h" #include "pxr/base/tf/makePyConstructor.h" -#include using namespace boost::python; using std::string; diff --git a/pxr/usd/lib/usd/stage.cpp b/pxr/usd/lib/usd/stage.cpp index cbddd838d3..fb30d05e24 100644 --- a/pxr/usd/lib/usd/stage.cpp +++ b/pxr/usd/lib/usd/stage.cpp @@ -384,10 +384,6 @@ UsdStage::~UsdStage() _rootLayer ? _rootLayer->GetIdentifier().c_str() : "", _sessionLayer ? _sessionLayer->GetIdentifier().c_str() : ""); Close(); - - if (_mallocTagID != _dormantMallocTagID){ - free(const_cast(_mallocTagID)); - } } void From fcc6b8350b5eae5b7a208493d0e54c8268c4072f Mon Sep 17 00:00:00 2001 From: George ElKoura Date: Wed, 26 Oct 2016 23:15:30 -0700 Subject: [PATCH 354/380] More appveyor. --- appveyor.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/appveyor.yml b/appveyor.yml index 5654bd81b7..54f2fe49a3 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -24,6 +24,7 @@ build_script: # TBB - cd c:\projects - mkdir tbb44 + - cd tbb44 - appveyor DownloadFile https://www.threadingbuildingblocks.org/sites/default/files/software_releases/windows/tbb44_20160526oss_win_0.zip -FileName tbb.zip - 7z x tbb.zip - dir From 1dfcdf5fe8944568b4b42fe6fd0b61e7116c694e Mon Sep 17 00:00:00 2001 From: George ElKoura Date: Wed, 26 Oct 2016 23:18:18 -0700 Subject: [PATCH 355/380] Try to find TBB in the build. --- appveyor.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/appveyor.yml b/appveyor.yml index 54f2fe49a3..8459e40d4f 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -44,5 +44,8 @@ build_script: -D "Boost_USE_STATIC_LIBS:INT=0" \ -D "DOUBLE_CONVERSION_LIBRARY:string=c:/projects/double-conversion/bld/double-conversion/Release/double-conversion.lib" \ -D "DOUBLE_CONVERSION_INCLUDE_DIR:string=c:/projects/double-conversion" \ + -D "TBB_LIBRARY:string=c:/projects/tbb44_20160526oss/lib/intel64/vc14/" \ + -D "TBB_LIBRARIES:string=c:/projects/tbb44_20160526oss/lib/intel64/vc14/tbb.lib" \ + -D "TBB_INCLUDE_DIRS:string=c:/projects/tbb44_20160526oss/include" \ .. - cmake --build . --config Release From 9fc7bd3331a7f27cc21c750ff3c49508cfcd4ef7 Mon Sep 17 00:00:00 2001 From: George ElKoura Date: Wed, 26 Oct 2016 23:19:59 -0700 Subject: [PATCH 356/380] More TBB fixes for appveyor. --- appveyor.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index 8459e40d4f..6675e4e9ea 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -44,8 +44,8 @@ build_script: -D "Boost_USE_STATIC_LIBS:INT=0" \ -D "DOUBLE_CONVERSION_LIBRARY:string=c:/projects/double-conversion/bld/double-conversion/Release/double-conversion.lib" \ -D "DOUBLE_CONVERSION_INCLUDE_DIR:string=c:/projects/double-conversion" \ - -D "TBB_LIBRARY:string=c:/projects/tbb44_20160526oss/lib/intel64/vc14/" \ - -D "TBB_LIBRARIES:string=c:/projects/tbb44_20160526oss/lib/intel64/vc14/tbb.lib" \ - -D "TBB_INCLUDE_DIRS:string=c:/projects/tbb44_20160526oss/include" \ + -D "TBB_LIBRARY:string=c:/projects/tbb/tbb44_20160526oss/lib/intel64/vc14/" \ + -D "TBB_LIBRARIES:string=c:/projects/tbb/tbb44_20160526oss/lib/intel64/vc14/tbb.lib" \ + -D "TBB_INCLUDE_DIRS:string=c:/projects/tbb/tbb44_20160526oss/include" \ .. - cmake --build . --config Release From 18b9f71e003ba7a1f7e7028128c4bde3f6650949 Mon Sep 17 00:00:00 2001 From: George ElKoura Date: Wed, 26 Oct 2016 23:21:59 -0700 Subject: [PATCH 357/380] Disable imaging for now on appveyor. --- appveyor.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/appveyor.yml b/appveyor.yml index 6675e4e9ea..5a5ad0a911 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -39,6 +39,7 @@ build_script: -D "PXR_BUILD_ALEMBIC_PLUGIN:bool=FALSE" \ -D "PXR_BUILD_KATANA_PLUGIN:bool=FALSE" \ -D "PXR_BUILD_MAYA_PLUGIN:bool=FALSE" \ + -D "PXR_BUILD_IMAGING:bool=FASLE" \ -D "BOOST_ROOT:string=c:/Libraries/boost_1_59_0" \ -D "BOOST_LIBRARYDIR:string=c:/Libraries/boost_1_59_0/lib64-msvc-14.0" \ -D "Boost_USE_STATIC_LIBS:INT=0" \ From 797025063a81c8d63294d9b83960492d0c21876d Mon Sep 17 00:00:00 2001 From: George ElKoura Date: Wed, 26 Oct 2016 23:27:07 -0700 Subject: [PATCH 358/380] Try to figure out what's going wrong with TBB on appveyor. --- appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/appveyor.yml b/appveyor.yml index 5a5ad0a911..122e20c9fd 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -28,7 +28,7 @@ build_script: - appveyor DownloadFile https://www.threadingbuildingblocks.org/sites/default/files/software_releases/windows/tbb44_20160526oss_win_0.zip -FileName tbb.zip - 7z x tbb.zip - dir - + - dir c:\projects\tbb\tbb44_20160526oss\include\tbb # USD - cd c:\projects\USD From 5809c2694441bd83f9cb715872d424b85dc10c89 Mon Sep 17 00:00:00 2001 From: George ElKoura Date: Wed, 26 Oct 2016 23:29:05 -0700 Subject: [PATCH 359/380] Try again for TBB. --- appveyor.yml | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index 122e20c9fd..30dac32cad 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -23,12 +23,10 @@ build_script: # TBB - cd c:\projects - - mkdir tbb44 - - cd tbb44 + - mkdir tbb + - cd tbb - appveyor DownloadFile https://www.threadingbuildingblocks.org/sites/default/files/software_releases/windows/tbb44_20160526oss_win_0.zip -FileName tbb.zip - 7z x tbb.zip - - dir - - dir c:\projects\tbb\tbb44_20160526oss\include\tbb # USD - cd c:\projects\USD From f12c83fb6fa6749052b527d2176085442e4dc9f7 Mon Sep 17 00:00:00 2001 From: George ElKoura Date: Thu, 27 Oct 2016 00:14:14 -0700 Subject: [PATCH 360/380] More breakage from the latest dev merge. --- pxr/usd/lib/pcp/wrapDependency.cpp | 2 +- pxr/usd/lib/usdShade/subgraph.h | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/pxr/usd/lib/pcp/wrapDependency.cpp b/pxr/usd/lib/pcp/wrapDependency.cpp index 98b6ba8528..2766d57b47 100644 --- a/pxr/usd/lib/pcp/wrapDependency.cpp +++ b/pxr/usd/lib/pcp/wrapDependency.cpp @@ -23,10 +23,10 @@ // #include -#include "pxr/usd/pcp/dependency.h" #include "pxr/base/tf/pyEnum.h" #include "pxr/base/tf/makePyConstructor.h" +#include "pxr/usd/pcp/dependency.h" using namespace boost::python; using std::string; diff --git a/pxr/usd/lib/usdShade/subgraph.h b/pxr/usd/lib/usdShade/subgraph.h index 3267b620fe..d36a6e2797 100644 --- a/pxr/usd/lib/usdShade/subgraph.h +++ b/pxr/usd/lib/usdShade/subgraph.h @@ -254,6 +254,7 @@ class UsdShadeSubgraph : public UsdTyped /// Get all terminals of a subgraph /// + USDSHADE_API UsdRelationshipVector GetTerminals() const; }; From fd103535fbddf67b533c926dcd0b7f4a103ed9d2 Mon Sep 17 00:00:00 2001 From: George ElKoura Date: Thu, 27 Oct 2016 00:22:42 -0700 Subject: [PATCH 361/380] Add symbol visibility missing from last dev merge. --- pxr/usd/lib/pcp/cache.h | 1 + 1 file changed, 1 insertion(+) diff --git a/pxr/usd/lib/pcp/cache.h b/pxr/usd/lib/pcp/cache.h index cd11a7db3a..0aac84542c 100644 --- a/pxr/usd/lib/pcp/cache.h +++ b/pxr/usd/lib/pcp/cache.h @@ -407,6 +407,7 @@ class PcpCache /// paths representing computed prim and property index caches; /// otherwise a recursively-expanded result can include /// un-computed paths that are expected to depend on the site + PCP_API PcpDependencyVector FindDependentPaths(const PcpLayerStackPtr& siteLayerStack, const SdfPath& sitePath, From e2d2c6f3eca104c82aae79bd1e0f0d5db3a07d19 Mon Sep 17 00:00:00 2001 From: George ElKoura Date: Thu, 27 Oct 2016 19:48:09 -0700 Subject: [PATCH 362/380] Applying patch for Jamie for third party code. --- third_party/katana/lib/usdKatana/readGprim.cpp | 2 +- third_party/katana/lib/usdKatana/readPoints.cpp | 2 +- third_party/maya/lib/px_vp20/utils_legacy.h | 5 ++++- third_party/maya/lib/pxrUsdMayaGL/batchRenderer.h | 1 + third_party/maya/lib/usdMaya/meshUtil.h | 2 ++ 5 files changed, 9 insertions(+), 3 deletions(-) diff --git a/third_party/katana/lib/usdKatana/readGprim.cpp b/third_party/katana/lib/usdKatana/readGprim.cpp index f7ee2b5d55..4de03150ad 100644 --- a/third_party/katana/lib/usdKatana/readGprim.cpp +++ b/third_party/katana/lib/usdKatana/readGprim.cpp @@ -122,7 +122,7 @@ _ConvertGeomAttr( return FnKat::Attribute(); } - const double currentTime = data.GetUsdInArgs()->GetCurrentTime(); + const double currentTime = data.GetUsdInArgs()->GetCurrentTimeD(); const std::vector& motionSampleTimes = data.GetMotionSampleTimes(usdAttr); // Flag to check if we discovered the topology is varying, in diff --git a/third_party/katana/lib/usdKatana/readPoints.cpp b/third_party/katana/lib/usdKatana/readPoints.cpp index 480590a6de..6c957172f4 100644 --- a/third_party/katana/lib/usdKatana/readPoints.cpp +++ b/third_party/katana/lib/usdKatana/readPoints.cpp @@ -81,7 +81,7 @@ PxrUsdKatanaReadPoints( } // normals - FnKat::Attribute normalsAttr = _GetNormalsAttr(points, currentTime); + FnKat::Attribute normalsAttr = PxrUsdKatanaGeomGetNormalAttr(points, data); if (normalsAttr.isValid()) { // XXX RfK doesn't support uniform curve normals. diff --git a/third_party/maya/lib/px_vp20/utils_legacy.h b/third_party/maya/lib/px_vp20/utils_legacy.h index ae467881d1..e77b6123ad 100644 --- a/third_party/maya/lib/px_vp20/utils_legacy.h +++ b/third_party/maya/lib/px_vp20/utils_legacy.h @@ -25,7 +25,7 @@ #define __PX_VP20_UTILS_LEGACY_H__ /// \file utils_legacy.h - +#include "px_vp20/api.h" #include "pxr/base/gf/matrix4d.h" #include @@ -37,6 +37,7 @@ class px_LegacyViewportUtils public: /// Get the view and projection matrices used for selection from the given /// M3dView \p view. + PX_VP20_API static void GetViewSelectionMatrices(M3dView& view, GfMatrix4d* viewMatrix, GfMatrix4d* projectionMatrix); @@ -44,7 +45,9 @@ class px_LegacyViewportUtils private: /// Creating instances of this class is disallowed by making the /// constructor private. + PX_VP20_API px_LegacyViewportUtils(); + PX_VP20_API ~px_LegacyViewportUtils(); }; diff --git a/third_party/maya/lib/pxrUsdMayaGL/batchRenderer.h b/third_party/maya/lib/pxrUsdMayaGL/batchRenderer.h index 6055814e6d..e601bf3e23 100644 --- a/third_party/maya/lib/pxrUsdMayaGL/batchRenderer.h +++ b/third_party/maya/lib/pxrUsdMayaGL/batchRenderer.h @@ -28,6 +28,7 @@ #ifndef PXRUSDMAYAGL_BATCHRENDERER_H #define PXRUSDMAYAGL_BATCHRENDERER_H +#include "pxrUsdMayaGL/api.h" #include "pxrUsdMayaGL/softSelectHelper.h" #include "pxr/base/arch/hash.h" diff --git a/third_party/maya/lib/usdMaya/meshUtil.h b/third_party/maya/lib/usdMaya/meshUtil.h index 45e235a0fe..f56bc46c2b 100644 --- a/third_party/maya/lib/usdMaya/meshUtil.h +++ b/third_party/maya/lib/usdMaya/meshUtil.h @@ -27,6 +27,7 @@ #ifndef PXRUSDMAYA_MESH_UTIL_H #define PXRUSDMAYA_MESH_UTIL_H +#include "usdMaya/api.h" #include "pxr/base/tf/staticTokens.h" #include "pxr/base/tf/token.h" @@ -41,6 +42,7 @@ class UsdGeomMesh; ((DisplayOpacityColorSetName, "displayOpacity")) TF_DECLARE_PUBLIC_TOKENS(PxrUsdMayaMeshColorSetTokens, + USDMAYA_API, PXRUSDMAYA_MESH_COLOR_SET_TOKENS); From 15c90e6ee6c723aa8bf2933eaca38698d784060a Mon Sep 17 00:00:00 2001 From: George ElKoura Date: Thu, 27 Oct 2016 19:57:34 -0700 Subject: [PATCH 363/380] Start on OpenEXR --- appveyor.yml | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/appveyor.yml b/appveyor.yml index 30dac32cad..9f930104c9 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -28,6 +28,15 @@ build_script: - appveyor DownloadFile https://www.threadingbuildingblocks.org/sites/default/files/software_releases/windows/tbb44_20160526oss_win_0.zip -FileName tbb.zip - 7z x tbb.zip + # OpenEXR + - git clone https://github.com/openexr/openexr.git c:/projects/openexr + - cd c:\projects\openexr\IlmBase + - mkdir build + - cd build + - cmake -G "Visual Studio %Configuration%" .. + - cmake --build . --config Release + + # USD - cd c:\projects\USD - mkdir build From 12e6213937ad032fd0051d07aacd0cce06ac0bf0 Mon Sep 17 00:00:00 2001 From: George ElKoura Date: Thu, 27 Oct 2016 20:09:48 -0700 Subject: [PATCH 364/380] More on IlmBase --- appveyor.yml | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index 9f930104c9..5d06c53f1c 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -28,13 +28,15 @@ build_script: - appveyor DownloadFile https://www.threadingbuildingblocks.org/sites/default/files/software_releases/windows/tbb44_20160526oss_win_0.zip -FileName tbb.zip - 7z x tbb.zip - # OpenEXR + # IlmBase - git clone https://github.com/openexr/openexr.git c:/projects/openexr - cd c:\projects\openexr\IlmBase - mkdir build - cd build - - cmake -G "Visual Studio %Configuration%" .. - - cmake --build . --config Release + - cmake -G "Visual Studio %Configuration%" -DCMAKE_INSTALL_PREFIX="c:/projects/openexr" + - cmake --build . --target install --config Release + - cd c:\projects/openexr + - dir # USD @@ -55,5 +57,8 @@ build_script: -D "TBB_LIBRARY:string=c:/projects/tbb/tbb44_20160526oss/lib/intel64/vc14/" \ -D "TBB_LIBRARIES:string=c:/projects/tbb/tbb44_20160526oss/lib/intel64/vc14/tbb.lib" \ -D "TBB_INCLUDE_DIRS:string=c:/projects/tbb/tbb44_20160526oss/include" \ + -D "OPENEXR_LIBRARY_DIR:string=c:/OpenEXR" \ + -D "OPENEXR_INCLUDE_DIR:string=c:/IlmBase/include" \ + -D "OPENEXR_Half_LIBRARY:string=c:/IlmBase/lib/Half.lib" \ .. - cmake --build . --config Release From 0627a7b2dd6101cccaf78e55257dc3439371a318 Mon Sep 17 00:00:00 2001 From: George ElKoura Date: Thu, 27 Oct 2016 20:14:34 -0700 Subject: [PATCH 365/380] Some more experiments --- appveyor.yml | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index 5d06c53f1c..fbd1f03b97 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -18,8 +18,12 @@ build_script: - cd c:\projects\double-conversion - mkdir bld - cd bld - - cmake -G "Visual Studio %Configuration%" .. - - cmake --build . --config Release + - cmake -G "Visual Studio %Configuration%" \ + -DCMAKE_INSTALL_PREFIX="c:/packages/double-conversion" \ + .. + - cmake --build . --target install --config Release + - cd c:\packages\double-conversion + - dir # TBB - cd c:\projects @@ -33,7 +37,9 @@ build_script: - cd c:\projects\openexr\IlmBase - mkdir build - cd build - - cmake -G "Visual Studio %Configuration%" -DCMAKE_INSTALL_PREFIX="c:/projects/openexr" + - cmake -G "Visual Studio %Configuration%" \ + -DCMAKE_INSTALL_PREFIX="c:/packages/openexr" \ + .. - cmake --build . --target install --config Release - cd c:\projects/openexr - dir From 7a4d88d702981feab79000b94251d98cd1e98cf6 Mon Sep 17 00:00:00 2001 From: George ElKoura Date: Thu, 27 Oct 2016 20:17:18 -0700 Subject: [PATCH 366/380] Moving towards caching dependencies --- appveyor.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index fbd1f03b97..25d804a0ff 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -41,7 +41,7 @@ build_script: -DCMAKE_INSTALL_PREFIX="c:/packages/openexr" \ .. - cmake --build . --target install --config Release - - cd c:\projects/openexr + - cd c:\packages\openexr - dir @@ -58,8 +58,8 @@ build_script: -D "BOOST_ROOT:string=c:/Libraries/boost_1_59_0" \ -D "BOOST_LIBRARYDIR:string=c:/Libraries/boost_1_59_0/lib64-msvc-14.0" \ -D "Boost_USE_STATIC_LIBS:INT=0" \ - -D "DOUBLE_CONVERSION_LIBRARY:string=c:/projects/double-conversion/bld/double-conversion/Release/double-conversion.lib" \ - -D "DOUBLE_CONVERSION_INCLUDE_DIR:string=c:/projects/double-conversion" \ + -D "DOUBLE_CONVERSION_LIBRARY:string=c:/packages/double-conversion/lib/double-conversion.lib" \ + -D "DOUBLE_CONVERSION_INCLUDE_DIR:string=c:/packages" \ -D "TBB_LIBRARY:string=c:/projects/tbb/tbb44_20160526oss/lib/intel64/vc14/" \ -D "TBB_LIBRARIES:string=c:/projects/tbb/tbb44_20160526oss/lib/intel64/vc14/tbb.lib" \ -D "TBB_INCLUDE_DIRS:string=c:/projects/tbb/tbb44_20160526oss/include" \ From fc707565fabf26e4a273d65533118f4a46695cb2 Mon Sep 17 00:00:00 2001 From: George ElKoura Date: Thu, 27 Oct 2016 20:23:30 -0700 Subject: [PATCH 367/380] More fixes --- appveyor.yml | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index 25d804a0ff..e8b4057a71 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -22,8 +22,6 @@ build_script: -DCMAKE_INSTALL_PREFIX="c:/packages/double-conversion" \ .. - cmake --build . --target install --config Release - - cd c:\packages\double-conversion - - dir # TBB - cd c:\projects @@ -31,6 +29,7 @@ build_script: - cd tbb - appveyor DownloadFile https://www.threadingbuildingblocks.org/sites/default/files/software_releases/windows/tbb44_20160526oss_win_0.zip -FileName tbb.zip - 7z x tbb.zip + - # IlmBase - git clone https://github.com/openexr/openexr.git c:/projects/openexr @@ -41,7 +40,7 @@ build_script: -DCMAKE_INSTALL_PREFIX="c:/packages/openexr" \ .. - cmake --build . --target install --config Release - - cd c:\packages\openexr + - cd c:\packages\openexr\include - dir @@ -54,7 +53,7 @@ build_script: -D "PXR_BUILD_ALEMBIC_PLUGIN:bool=FALSE" \ -D "PXR_BUILD_KATANA_PLUGIN:bool=FALSE" \ -D "PXR_BUILD_MAYA_PLUGIN:bool=FALSE" \ - -D "PXR_BUILD_IMAGING:bool=FASLE" \ + -D "PXR_BUILD_IMAGING:bool=FALSE" \ -D "BOOST_ROOT:string=c:/Libraries/boost_1_59_0" \ -D "BOOST_LIBRARYDIR:string=c:/Libraries/boost_1_59_0/lib64-msvc-14.0" \ -D "Boost_USE_STATIC_LIBS:INT=0" \ From 38c22aa9a1a805f4ebf59dcf97c0c8350a181bfe Mon Sep 17 00:00:00 2001 From: George ElKoura Date: Thu, 27 Oct 2016 20:30:58 -0700 Subject: [PATCH 368/380] Win64 required --- appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/appveyor.yml b/appveyor.yml index e8b4057a71..3beaa6a536 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -9,7 +9,7 @@ platform: - x64 configuration: - - 14 2015 + - 14 2015 Win64 build_script: From 96ef53e506bffd6e813dd865f2303683f145b1a2 Mon Sep 17 00:00:00 2001 From: George ElKoura Date: Thu, 27 Oct 2016 20:41:04 -0700 Subject: [PATCH 369/380] Require boost 1.60 --- appveyor.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index 3beaa6a536..76e130c0c6 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -54,8 +54,8 @@ build_script: -D "PXR_BUILD_KATANA_PLUGIN:bool=FALSE" \ -D "PXR_BUILD_MAYA_PLUGIN:bool=FALSE" \ -D "PXR_BUILD_IMAGING:bool=FALSE" \ - -D "BOOST_ROOT:string=c:/Libraries/boost_1_59_0" \ - -D "BOOST_LIBRARYDIR:string=c:/Libraries/boost_1_59_0/lib64-msvc-14.0" \ + -D "BOOST_ROOT:string=c:/Libraries/boost_1_60_0" \ + -D "BOOST_LIBRARYDIR:string=c:/Libraries/boost_1_60_0/lib64-msvc-14.0" \ -D "Boost_USE_STATIC_LIBS:INT=0" \ -D "DOUBLE_CONVERSION_LIBRARY:string=c:/packages/double-conversion/lib/double-conversion.lib" \ -D "DOUBLE_CONVERSION_INCLUDE_DIR:string=c:/packages" \ From e50c2383371c924ca34d490cdab32265d53607f8 Mon Sep 17 00:00:00 2001 From: George ElKoura Date: Thu, 27 Oct 2016 20:48:00 -0700 Subject: [PATCH 370/380] Double-conversion experiment --- appveyor.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/appveyor.yml b/appveyor.yml index 76e130c0c6..4ae15d0d68 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -22,6 +22,11 @@ build_script: -DCMAKE_INSTALL_PREFIX="c:/packages/double-conversion" \ .. - cmake --build . --target install --config Release + - cd c:\packages\double-conversion + - dir + - cd c:\packages\double-conversion\include + - dir + - asdfafsd # TBB - cd c:\projects From 8e28f8d27d03915012d32e62970f0b17da0048cc Mon Sep 17 00:00:00 2001 From: George ElKoura Date: Thu, 27 Oct 2016 20:50:00 -0700 Subject: [PATCH 371/380] More fixes. --- appveyor.yml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index 4ae15d0d68..07baaba9c6 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -26,7 +26,9 @@ build_script: - dir - cd c:\packages\double-conversion\include - dir - - asdfafsd + - cd c:\packages\double-conversion\lib + - dir + - sdfadf # TBB - cd c:\projects @@ -63,7 +65,7 @@ build_script: -D "BOOST_LIBRARYDIR:string=c:/Libraries/boost_1_60_0/lib64-msvc-14.0" \ -D "Boost_USE_STATIC_LIBS:INT=0" \ -D "DOUBLE_CONVERSION_LIBRARY:string=c:/packages/double-conversion/lib/double-conversion.lib" \ - -D "DOUBLE_CONVERSION_INCLUDE_DIR:string=c:/packages" \ + -D "DOUBLE_CONVERSION_INCLUDE_DIR:string=c:/packages/double-conversion/include" \ -D "TBB_LIBRARY:string=c:/projects/tbb/tbb44_20160526oss/lib/intel64/vc14/" \ -D "TBB_LIBRARIES:string=c:/projects/tbb/tbb44_20160526oss/lib/intel64/vc14/tbb.lib" \ -D "TBB_INCLUDE_DIRS:string=c:/projects/tbb/tbb44_20160526oss/include" \ From 9d2af4f32e85b5aa7496dd3ffed9b39144b68e8a Mon Sep 17 00:00:00 2001 From: George ElKoura Date: Thu, 27 Oct 2016 20:53:01 -0700 Subject: [PATCH 372/380] Next steps... --- appveyor.yml | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index 07baaba9c6..bacb892771 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -22,13 +22,6 @@ build_script: -DCMAKE_INSTALL_PREFIX="c:/packages/double-conversion" \ .. - cmake --build . --target install --config Release - - cd c:\packages\double-conversion - - dir - - cd c:\packages\double-conversion\include - - dir - - cd c:\packages\double-conversion\lib - - dir - - sdfadf # TBB - cd c:\projects @@ -49,6 +42,9 @@ build_script: - cmake --build . --target install --config Release - cd c:\packages\openexr\include - dir + - cd c:\packages\openexr\lib + - dir + -sdfadsf # USD @@ -69,8 +65,8 @@ build_script: -D "TBB_LIBRARY:string=c:/projects/tbb/tbb44_20160526oss/lib/intel64/vc14/" \ -D "TBB_LIBRARIES:string=c:/projects/tbb/tbb44_20160526oss/lib/intel64/vc14/tbb.lib" \ -D "TBB_INCLUDE_DIRS:string=c:/projects/tbb/tbb44_20160526oss/include" \ - -D "OPENEXR_LIBRARY_DIR:string=c:/OpenEXR" \ - -D "OPENEXR_INCLUDE_DIR:string=c:/IlmBase/include" \ + -D "OPENEXR_LIBRARY_DIR:string=c:/packages/openexr" \ + -D "OPENEXR_INCLUDE_DIR:string=c:/packages/openexr/include" \ -D "OPENEXR_Half_LIBRARY:string=c:/IlmBase/lib/Half.lib" \ .. - cmake --build . --config Release From cb7fbabfbd769db0c6bcf1281906069161017d65 Mon Sep 17 00:00:00 2001 From: George ElKoura Date: Thu, 27 Oct 2016 20:53:35 -0700 Subject: [PATCH 373/380] Sigh --- appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/appveyor.yml b/appveyor.yml index bacb892771..ca156347bd 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -44,7 +44,7 @@ build_script: - dir - cd c:\packages\openexr\lib - dir - -sdfadsf + - sdfadsf # USD From 6ab0c75659d1ec44daf83bcf3248d871930b3cda Mon Sep 17 00:00:00 2001 From: George ElKoura Date: Thu, 27 Oct 2016 20:56:44 -0700 Subject: [PATCH 374/380] Closer... --- appveyor.yml | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index ca156347bd..287df9c14f 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -24,7 +24,7 @@ build_script: - cmake --build . --target install --config Release # TBB - - cd c:\projects + - cd c:\packages - mkdir tbb - cd tbb - appveyor DownloadFile https://www.threadingbuildingblocks.org/sites/default/files/software_releases/windows/tbb44_20160526oss_win_0.zip -FileName tbb.zip @@ -40,11 +40,6 @@ build_script: -DCMAKE_INSTALL_PREFIX="c:/packages/openexr" \ .. - cmake --build . --target install --config Release - - cd c:\packages\openexr\include - - dir - - cd c:\packages\openexr\lib - - dir - - sdfadsf # USD @@ -62,11 +57,11 @@ build_script: -D "Boost_USE_STATIC_LIBS:INT=0" \ -D "DOUBLE_CONVERSION_LIBRARY:string=c:/packages/double-conversion/lib/double-conversion.lib" \ -D "DOUBLE_CONVERSION_INCLUDE_DIR:string=c:/packages/double-conversion/include" \ - -D "TBB_LIBRARY:string=c:/projects/tbb/tbb44_20160526oss/lib/intel64/vc14/" \ - -D "TBB_LIBRARIES:string=c:/projects/tbb/tbb44_20160526oss/lib/intel64/vc14/tbb.lib" \ - -D "TBB_INCLUDE_DIRS:string=c:/projects/tbb/tbb44_20160526oss/include" \ + -D "TBB_LIBRARY:string=c:/packages/tbb/tbb44_20160526oss/lib/intel64/vc14/" \ + -D "TBB_LIBRARIES:string=c:/packages/tbb/tbb44_20160526oss/lib/intel64/vc14/tbb.lib" \ + -D "TBB_INCLUDE_DIRS:string=c:/packages/tbb/tbb44_20160526oss/include" \ -D "OPENEXR_LIBRARY_DIR:string=c:/packages/openexr" \ -D "OPENEXR_INCLUDE_DIR:string=c:/packages/openexr/include" \ - -D "OPENEXR_Half_LIBRARY:string=c:/IlmBase/lib/Half.lib" \ + -D "OPENEXR_Half_LIBRARY:string=c:/packages/openexr/lib/Half.lib" \ .. - cmake --build . --config Release From 87ca053b4d55df519169917314b19418702a7f1c Mon Sep 17 00:00:00 2001 From: George ElKoura Date: Thu, 27 Oct 2016 21:16:29 -0700 Subject: [PATCH 375/380] Trying to add a badge for appveyor --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index a462ace699..4e2fc108af 100644 --- a/README.md +++ b/README.md @@ -15,6 +15,7 @@ Build Status | | master | dev | | ----- | ------ | --- | | Linux | [![Build Status](https://travis-ci.org/PixarAnimationStudios/USD.svg?branch=master)](https://travis-ci.org/PixarAnimationStudios/USD) | [![Build Status](https://travis-ci.org/PixarAnimationStudios/USD.svg?branch=dev)](https://travis-ci.org/PixarAnimationStudios/USD) | +| Windows | N/A | [![Build status](https://ci.appveyor.com/api/projects/status/knuwy0hfhewn1o34/branch/dev_win_ip_g?svg=true)](https://ci.appveyor.com/project/c64kernal/usd/branch/dev_win_ip_g) | Additional Documentation ------------------------ From ccdb0db34d77fea03497edf511fa43eb66ea383c Mon Sep 17 00:00:00 2001 From: George ElKoura Date: Fri, 28 Oct 2016 08:29:17 -0700 Subject: [PATCH 376/380] Applying another patch for Jamie. --- third_party/katana/lib/usdKatana/readBasisCurves.cpp | 2 +- third_party/katana/lib/usdKatana/readPrim.cpp | 4 ++-- third_party/maya/lib/usdMaya/UserTaggedAttribute.h | 10 +++++++++- .../maya/lib/usdMaya/wrapUserTaggedAttribute.cpp | 6 +++--- 4 files changed, 15 insertions(+), 7 deletions(-) diff --git a/third_party/katana/lib/usdKatana/readBasisCurves.cpp b/third_party/katana/lib/usdKatana/readBasisCurves.cpp index 6923cdd6f1..cd4aa67abb 100644 --- a/third_party/katana/lib/usdKatana/readBasisCurves.cpp +++ b/third_party/katana/lib/usdKatana/readBasisCurves.cpp @@ -137,7 +137,7 @@ PxrUsdKatanaReadBasisCurves( // Construct the 'geometry' attribute. // - _SetCurveAttrs(attrs, basisCurves, data.GetUsdInArgs()->GetCurrentTime()); + _SetCurveAttrs(attrs, basisCurves, data.GetUsdInArgs()->GetCurrentTimeD()); // position attrs.set("geometry.point.P", diff --git a/third_party/katana/lib/usdKatana/readPrim.cpp b/third_party/katana/lib/usdKatana/readPrim.cpp index 888ded8788..a9fe1ce887 100644 --- a/third_party/katana/lib/usdKatana/readPrim.cpp +++ b/third_party/katana/lib/usdKatana/readPrim.cpp @@ -369,7 +369,7 @@ _AddExtraAttributesOrNamespaces( { const std::string& rootLocation = data.GetUsdInArgs()->GetRootLocationPath(); - const double currentTime = data.GetUsdInArgs()->GetCurrentTime(); + const double currentTime = data.GetUsdInArgs()->GetCurrentTimeD(); const PxrUsdKatanaUsdInArgs::StringListMap& extraAttributesOrNamespaces = data.GetUsdInArgs()->GetExtraAttributesOrNamespaces(); @@ -581,7 +581,7 @@ PxrUsdKatanaGeomGetPrimvarGroup( // Resolve the value VtValue vtValue; if (not primvar->ComputeFlattened( - &vtValue, data.GetUsdInArgs()->GetCurrentTime())) + &vtValue, data.GetUsdInArgs()->GetCurrentTimeD())) { continue; } diff --git a/third_party/maya/lib/usdMaya/UserTaggedAttribute.h b/third_party/maya/lib/usdMaya/UserTaggedAttribute.h index 319072cd2b..c9cb053835 100644 --- a/third_party/maya/lib/usdMaya/UserTaggedAttribute.h +++ b/third_party/maya/lib/usdMaya/UserTaggedAttribute.h @@ -27,6 +27,7 @@ #ifndef PXRUSDMAYA_USERTAGGEDATTRIBUTE_H #define PXRUSDMAYA_USERTAGGEDATTRIBUTE_H +#include "usdMaya/api.h" #include "pxr/base/tf/iterator.h" #include "pxr/base/tf/token.h" #include "pxr/base/tf/staticTokens.h" @@ -42,7 +43,7 @@ ((USDAttrTypePrimvar, "primvar")) \ ((USDAttrTypeUsdRi, "usdRi")) -TF_DECLARE_PUBLIC_TOKENS(PxrUsdMayaUserTaggedAttributeTokens, +TF_DECLARE_PUBLIC_TOKENS(PxrUsdMayaUserTaggedAttributeTokens, USDMAYA_API, PXRUSDMAYA_ATTR_TOKENS); /// \brief Represents a single attribute tagged for USD export, and describes @@ -55,6 +56,7 @@ class PxrUsdMayaUserTaggedAttribute { const TfToken _interpolation; public: + USDMAYA_API PxrUsdMayaUserTaggedAttribute( MPlug plug, const std::string& name, @@ -62,25 +64,31 @@ class PxrUsdMayaUserTaggedAttribute { const TfToken& interpolation); /// \brief Gets all of the exported attributes for the given node. + USDMAYA_API static std::vector GetUserTaggedAttributesForNode(const MDagPath& dagPath); /// \brief Gets the plug for the Maya attribute to be exported. + USDMAYA_API MPlug GetMayaPlug() const; /// \brief Gets the name of the Maya attribute that will be exported; /// the name will not contain the name of the node. + USDMAYA_API std::string GetMayaName() const; /// \brief Gets the name of the USD attribute to which the Maya attribute /// will be exported. + USDMAYA_API std::string GetUsdName() const; /// \brief Gets the type of the USD attribute to export: whether it is a /// regular attribute, primvar, etc. + USDMAYA_API TfToken GetUsdType() const; /// \brief Gets the interpolation for primvars. + USDMAYA_API TfToken GetUsdInterpolation() const; }; diff --git a/third_party/maya/lib/usdMaya/wrapUserTaggedAttribute.cpp b/third_party/maya/lib/usdMaya/wrapUserTaggedAttribute.cpp index 5f30714c11..caa08c52f0 100644 --- a/third_party/maya/lib/usdMaya/wrapUserTaggedAttribute.cpp +++ b/third_party/maya/lib/usdMaya/wrapUserTaggedAttribute.cpp @@ -21,6 +21,9 @@ // KIND, either express or implied. See the Apache License for the specific // language governing permissions and limitations under the Apache License. // +#include +#include + #include "usdMaya/UserTaggedAttribute.h" #include "pxr/base/tf/pyContainerConversions.h" @@ -32,9 +35,6 @@ #include #include -#include -#include - #include static std::vector From 32d3ba6bb0f044fc49bf1e4ed87747e4ae7686e6 Mon Sep 17 00:00:00 2001 From: George ElKoura Date: Sat, 29 Oct 2016 23:07:30 -0700 Subject: [PATCH 377/380] Small patch for OS X --- pxr/base/lib/gf/matrixData.h | 1 + pxr/base/lib/vt/valueFromPython.h | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/pxr/base/lib/gf/matrixData.h b/pxr/base/lib/gf/matrixData.h index f63c10a1ac..919dc70f03 100644 --- a/pxr/base/lib/gf/matrixData.h +++ b/pxr/base/lib/gf/matrixData.h @@ -25,6 +25,7 @@ #define GF_MATRIX_DATA_H #include "pxr/base/gf/api.h" +#include /// \class GfMatrixData /// diff --git a/pxr/base/lib/vt/valueFromPython.h b/pxr/base/lib/vt/valueFromPython.h index 23b074b52f..4a7da19c38 100644 --- a/pxr/base/lib/vt/valueFromPython.h +++ b/pxr/base/lib/vt/valueFromPython.h @@ -26,6 +26,7 @@ /// \file vt/valueFromPython.h +#include #include "pxr/base/vt/value.h" #include "pxr/base/vt/api.h" @@ -33,7 +34,6 @@ #include "pxr/base/tf/pyUtils.h" #include "pxr/base/tf/singleton.h" -#include #include #include #include "pxr/base/tf/hashmap.h" From d475d823ce1322849ad2b6ce586fc26f532d6269 Mon Sep 17 00:00:00 2001 From: George ElKoura Date: Sun, 30 Oct 2016 00:08:21 -0700 Subject: [PATCH 378/380] Experiment with /MP to see if it makes AppVeyor builds go faster. --- cmake/defaults/msvcdefaults.cmake | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/cmake/defaults/msvcdefaults.cmake b/cmake/defaults/msvcdefaults.cmake index 5c0475c21f..ba02b09002 100644 --- a/cmake/defaults/msvcdefaults.cmake +++ b/cmake/defaults/msvcdefaults.cmake @@ -92,7 +92,8 @@ if (${PXR_HYBRID_BUILD_MODE}) add_definitions("/Ob0") # Enable minimum builds - add_definitions("/Gm") + #add_definitions("/Gm") + add_definitions("/MP") else() # Enable multi-processor compilation add_definitions("/MP") From 9494e1ae366df1ee699c399335ec4d600e79f0b7 Mon Sep 17 00:00:00 2001 From: George ElKoura Date: Sun, 30 Oct 2016 09:20:11 -0700 Subject: [PATCH 379/380] Revert /MP for now. --- cmake/defaults/msvcdefaults.cmake | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/cmake/defaults/msvcdefaults.cmake b/cmake/defaults/msvcdefaults.cmake index ba02b09002..5c0475c21f 100644 --- a/cmake/defaults/msvcdefaults.cmake +++ b/cmake/defaults/msvcdefaults.cmake @@ -92,8 +92,7 @@ if (${PXR_HYBRID_BUILD_MODE}) add_definitions("/Ob0") # Enable minimum builds - #add_definitions("/Gm") - add_definitions("/MP") + add_definitions("/Gm") else() # Enable multi-processor compilation add_definitions("/MP") From b496d5d21a83218d6c9e133efebfab53d298e4a6 Mon Sep 17 00:00:00 2001 From: George ElKoura Date: Tue, 1 Nov 2016 23:45:52 -0700 Subject: [PATCH 380/380] Patches to arch for other platforms. --- pxr/base/lib/arch/attributes.h | 9 ++++----- pxr/base/lib/arch/debugger.cpp | 8 ++++---- pxr/base/lib/arch/env.cpp | 2 ++ pxr/base/lib/arch/fileSystem.cpp | 4 ++-- pxr/base/lib/arch/mallocHook.cpp | 3 ++- pxr/base/lib/arch/nap.cpp | 4 ++-- pxr/base/lib/arch/stackTrace.cpp | 3 +++ pxr/base/lib/arch/testenv/testArchAbi.cpp | 2 +- pxr/base/lib/arch/testenv/testError.cpp | 6 +++--- 9 files changed, 23 insertions(+), 18 deletions(-) mode change 100644 => 100755 pxr/base/lib/arch/stackTrace.cpp diff --git a/pxr/base/lib/arch/attributes.h b/pxr/base/lib/arch/attributes.h index 14cff02dc5..459f4e7316 100644 --- a/pxr/base/lib/arch/attributes.h +++ b/pxr/base/lib/arch/attributes.h @@ -30,6 +30,7 @@ /// This file allows you to define architecture-specific or compiler-specific /// options to be used outside lib/arch. +#include "pxr/base/arch/defines.h" #include "pxr/base/arch/export.h" /*! @@ -129,7 +130,7 @@ __attribute__((constructor(_priority))) \ static void _name(__VA_ARGS__) -# define ARCH_CONSTRUCTOR(_priority, tag, name) __attribute__((constructor(_priority))) +# define ARCH_CONSTRUCTOR(_priority) __attribute__((constructor(_priority))) /// Macro to indicate a function should be executed by the dynamic loader when /// the dynamic object (library or program) is unloaded. @@ -139,9 +140,7 @@ /// run first. /// /// \hideinitializer -# define ARCH_DESTRUCTOR(_priority, _name, ...) \ - __attribute__((destructor(_priority))) \ - static void _name(__VA_ARGS__) +# define ARCH_DESTRUCTOR(_priority) __attribute__((destructor(_priority))) #elif defined(ARCH_COMPILER_MSVC) @@ -241,4 +240,4 @@ // ARCH_DESTRUCTOR. #endif // defined(ARCH_COMPILER_GCC) || defined(ARCH_COMPILER_CLANG) -#endif // ARCH_ATTRIBUTES_H +#endif // ARCH_ATTRIBUTES_H diff --git a/pxr/base/lib/arch/debugger.cpp b/pxr/base/lib/arch/debugger.cpp index 8f6ee3b7fd..91c2e25fe0 100644 --- a/pxr/base/lib/arch/debugger.cpp +++ b/pxr/base/lib/arch/debugger.cpp @@ -458,7 +458,7 @@ Arch_InitDebuggerAttach() // Compute the length of the string. size_t n = 0; - for (char* i = e; *i; ++i) { + for (const char* i = e; *i; ++i) { if (i[0] == '%' and i[1] == 'p') { n += _decimalPidLength; ++i; @@ -487,7 +487,7 @@ Arch_InitDebuggerAttach() // Build the command string. char* a = _archDebuggerAttachArgs[2]; - for (char* i = e; *i; ++i) { + for (const char* i = e; *i; ++i) { if (i[0] == '%' and i[1] == 'p') { // Write the process id. sprintf(a, "%d", (int)getpid()); @@ -551,9 +551,9 @@ ArchDebuggerWait(bool wait) bool ArchDebuggerAttach() { - return + return #if defined(ARCH_OS_LINUX) || defined(ARCH_OS_DARWIN) - Arch_DebuggerIsAttachedPosix() or + Arch_DebuggerIsAttachedPosix() or #endif Arch_DebuggerAttach(); } diff --git a/pxr/base/lib/arch/env.cpp b/pxr/base/lib/arch/env.cpp index 7aa8df232a..714cc15dfd 100644 --- a/pxr/base/lib/arch/env.cpp +++ b/pxr/base/lib/arch/env.cpp @@ -26,6 +26,8 @@ #include +#include + std::string ArchGetEnv(const std::string &name) { #if defined(ARCH_OS_WINDOWS) diff --git a/pxr/base/lib/arch/fileSystem.cpp b/pxr/base/lib/arch/fileSystem.cpp index 35166b1c9a..5e28259169 100644 --- a/pxr/base/lib/arch/fileSystem.cpp +++ b/pxr/base/lib/arch/fileSystem.cpp @@ -289,7 +289,7 @@ ArchMakeTmpFile(const std::string& tmpdir, ARCH_ERROR(errorMsg.c_str()); return -1; } - + // Close the file ::CloseHandle(fileHandle); @@ -347,7 +347,7 @@ ArchMakeTmpSubdir(const std::string& tmpdir, retstr = sTemplate; } #else - strcpy(cTemplate, sTemplate.size() + 1, sTemplate.c_str()); + strncpy(cTemplate, sTemplate.c_str(), sTemplate.size() + 1); // Open the tmpdir. char *tmpSubdir = mkdtemp(cTemplate); diff --git a/pxr/base/lib/arch/mallocHook.cpp b/pxr/base/lib/arch/mallocHook.cpp index 4ceb4e9467..1cc8aec5fb 100644 --- a/pxr/base/lib/arch/mallocHook.cpp +++ b/pxr/base/lib/arch/mallocHook.cpp @@ -37,10 +37,11 @@ # include #else # include +#endif /* defined ARCH_OS_DARWIN */ + #if not defined(__MALLOC_HOOK_VOLATILE) #define __MALLOC_HOOK_VOLATILE #endif /* not defined __MALLOC_HOOK_VOLATILE */ -#endif /* defined(ARCH_OS_LINUX) */ using std::string; diff --git a/pxr/base/lib/arch/nap.cpp b/pxr/base/lib/arch/nap.cpp index dbd542ded0..7f989c1c87 100644 --- a/pxr/base/lib/arch/nap.cpp +++ b/pxr/base/lib/arch/nap.cpp @@ -50,7 +50,7 @@ ArchNap(size_t hundredths) // Note: neither tv_sec and tv_nsec can be negative, // because hundredths is unsigned and tv_nsec is big enough to avoid // overflow if hundredths == 99. - + if (rec.tv_sec == 0 && rec.tv_nsec == 0) { rec.tv_sec = 0; rec.tv_nsec = 1; @@ -89,7 +89,7 @@ int ArchNanoSleep(const struct timespec *req, struct timespec *rem) CloseHandle(timer); return 0; #else - return nanosleep(usec); + return nanosleep(req, 0); #endif } diff --git a/pxr/base/lib/arch/stackTrace.cpp b/pxr/base/lib/arch/stackTrace.cpp old mode 100644 new mode 100755 index 4d339a8c36..3b0098bd65 --- a/pxr/base/lib/arch/stackTrace.cpp +++ b/pxr/base/lib/arch/stackTrace.cpp @@ -45,6 +45,7 @@ #include "pxr/base/arch/debugger.h" #include "pxr/base/arch/demangle.h" #include "pxr/base/arch/error.h" +#include "pxr/base/arch/errno.h" #include "pxr/base/arch/fileSystem.h" #include "pxr/base/arch/inttypes.h" #include "pxr/base/arch/symbols.h" @@ -1049,6 +1050,7 @@ ArchLogStackTrace(const std::string& progname, const std::string& reason, } if (fd != -1) { +#ifdef ARCH_OS_WINDOWS FILE* fout = ArchFdOpen(fd, "w"); fprintf(stderr, "The stack can be found in %s:%s\n" "--------------------------------------------------------------" @@ -1063,6 +1065,7 @@ ArchLogStackTrace(const std::string& progname, const std::string& reason, NULL : sessionLog.c_str(), false /* crashing hard? */); } +#endif } else { /* we couldn't open the tmp file, so write the stack trace to stderr */ diff --git a/pxr/base/lib/arch/testenv/testArchAbi.cpp b/pxr/base/lib/arch/testenv/testArchAbi.cpp index aab4aa9af6..caa75fb240 100644 --- a/pxr/base/lib/arch/testenv/testArchAbi.cpp +++ b/pxr/base/lib/arch/testenv/testArchAbi.cpp @@ -55,7 +55,7 @@ main(int argc, char** argv) // Up two directories. path = path.substr(0, path.rfind('/', path.rfind('/') - 1)); path += "/tests/lib/libtestArchAbiPlugin.so"; - void* plugin = ArchOpenLibrary(path.c_str(), ARCH_LIBRARY_LAZY); + void* plugin = ArchLibraryOpen(path.c_str(), ARCH_LIBRARY_LAZY); if (not plugin) { error += dlerror(); } diff --git a/pxr/base/lib/arch/testenv/testError.cpp b/pxr/base/lib/arch/testenv/testError.cpp index 90129d0da5..2ea10630be 100644 --- a/pxr/base/lib/arch/testenv/testError.cpp +++ b/pxr/base/lib/arch/testenv/testError.cpp @@ -29,9 +29,9 @@ #include #include #include -#if defined(ARCH_OS_LINUX) +#if defined(ARCH_OS_LINUX) || defined(ARCH_OS_DARWIN) #include -##include +#include #endif #include #include @@ -43,7 +43,7 @@ crash(int sig) { } int main() -{ +{ (void) signal(SIGABRT,crash); #if !defined(ARCH_OS_WINDOWS)