bool UsdGeomPrimvarsAPI::HasPossiblyInheritedPrimvar(const TfToken &name) const { TRACE_FUNCTION(); UsdPrim prim = GetPrim(); if (!prim) { TF_CODING_ERROR("HasPossiblyInheritedPrimvar called on invalid prim: %s", UsdDescribe(prim).c_str()); return false; } UsdGeomPrimvar pv = GetPrimvar(name); if (pv.HasAuthoredValue()){ return true; } const TfToken attrName = UsdGeomPrimvar::_MakeNamespaced(name); if (attrName.IsEmpty()) { return false; } for (prim = prim.GetParent(); prim && !prim.IsPseudoRoot(); prim = prim.GetParent()) { UsdAttribute attr = prim.GetAttribute(attrName); if (attr.HasAuthoredValue() && UsdGeomPrimvar::IsPrimvar(attr)) { // Only constant primvars can be inherited. // Non-constant interpolation blocks inheritance. return UsdGeomPrimvar(attr).GetInterpolation() == UsdGeomTokens->constant; } } return false; }
static void _DoAddNewPrimSpec( const SdfLayerHandle& destLayer, const _SpecDataEntry& specData) { // Need to determine whether this property is considered inert when // being initially created based on fields being copied in. This mimics // what's done in the SdfPrimSpec constructor. TfToken type; SdfSpecifier specifier = SdfSpecifierOver; for (const _FieldValuePair& fieldValue : specData.dataToCopy) { if (fieldValue.second.IsEmpty()) { continue; } if (fieldValue.first == SdfFieldKeys->TypeName) { type = fieldValue.second.Get<TfToken>(); } else if (fieldValue.first == SdfFieldKeys->Specifier) { specifier = fieldValue.second.Get<SdfSpecifier>(); } } const bool inert = (specifier == SdfSpecifierOver && type.IsEmpty()); Sdf_ChildrenUtils<Sdf_PrimChildPolicy>::CreateSpec( destLayer, specData.dstPath, SdfSpecTypePrim, /* inert = */ inert); }
UsdGeomXformOp::UsdGeomXformOp( UsdPrim const& prim, UsdGeomXformOp::Type const opType, UsdGeomXformOp::Precision const precision, TfToken const &opSuffix, bool isInverseOp) : _opType(opType) , _isInverseOp(isInverseOp) { // Determine the typeName of the xformOp attribute to be created. const SdfValueTypeName &typeName = GetValueTypeName(opType, precision); if (!typeName) { TF_CODING_ERROR("Invalid xform-op: incompatible combination of " "opType (%s) and precision (%s).", TfEnum::GetName(opType).c_str(), TfEnum::GetName(precision).c_str()); return; } TfToken attrName = UsdGeomXformOp::GetOpName(opType, opSuffix, // isInverseOp is handled below /*isInverseOp*/ false); // attrName can never be empty. TF_VERIFY(!attrName.IsEmpty()); // Create an attribute in the xformOp: namespace with the // computed typeName. _attr = prim.CreateAttribute(attrName, typeName, /* custom */ false); // If a problem occurred, an error should already have been issued, // and _attr will be invalid, which is what we want }
PXR_NAMESPACE_CLOSE_SCOPE // ===================================================================== // // Feel free to add custom code below this line. It will be preserved by // the code generator. // // Just remember to wrap code in the appropriate delimiters: // 'PXR_NAMESPACE_OPEN_SCOPE', 'PXR_NAMESPACE_CLOSE_SCOPE'. // ===================================================================== // // --(BEGIN CUSTOM CODE)-- PXR_NAMESPACE_OPEN_SCOPE UsdGeomPrimvar UsdGeomPrimvarsAPI::CreatePrimvar(const TfToken& attrName, const SdfValueTypeName &typeName, const TfToken& interpolation, int elementSize) const { const UsdPrim &prim = GetPrim(); UsdGeomPrimvar primvar(prim, attrName, typeName); if (primvar){ if (!interpolation.IsEmpty()) primvar.SetInterpolation(interpolation); if (elementSize > 0) primvar.SetElementSize(elementSize); } // otherwise, errors have already been issued return primvar; }
TfToken UsdGeomCollectionAPI::_GetCollectionPropertyName( const TfToken &baseName /* =TfToken() */) const { return TfToken(UsdGeomTokens->collection.GetString() + ":" + _name.GetString() + (baseName.IsEmpty() ? "" : (":" + baseName.GetString()))); }
bool UsdGeomPrimvarsAPI::HasPrimvar(const TfToken &name) const { TfToken primvarName = UsdGeomPrimvar::_MakeNamespaced(name, /* quiet */true); const UsdPrim &prim = GetPrim(); if (!prim) { TF_CODING_ERROR("HasPrimvar called on invalid prim: %s", UsdDescribe(prim).c_str()); return false; } return primvarName.IsEmpty() ? false : UsdGeomPrimvar::IsPrimvar(prim.GetAttribute(primvarName)); }
/* static */ UsdSkelInbetweenShape UsdSkelInbetweenShape::_Create(const UsdPrim& prim, const TfToken& name) { if(TF_VERIFY(prim)) { TfToken attrName = _MakeNamespaced(name); if(!attrName.IsEmpty()) { return UsdSkelInbetweenShape( prim.CreateAttribute(attrName, SdfValueTypeNames->Point3fArray, /*custom*/ false, SdfVariabilityUniform)); } } return UsdSkelInbetweenShape(); }
/* static */ TfToken UsdGeomXformOp::GetOpName( const Type opType, const TfToken &opSuffix, bool isInverseOp) { TfToken opName = _MakeNamespaced(GetOpTypeToken(opType)); if (!opSuffix.IsEmpty()) opName = TfToken(opName.GetString() + ":" + opSuffix.GetString()); if (isInverseOp) opName = TfToken(_tokens->invertPrefix.GetString() + opName.GetString()); return opName; }
UsdGeomPrimvar::UsdGeomPrimvar(const UsdPrim& prim, const TfToken& baseName, const SdfValueTypeName &typeName, bool custom) { TF_VERIFY(prim); TfToken attrName = _MakeNamespaced(baseName); if (!attrName.IsEmpty()){ _attr = prim.CreateAttribute(attrName, typeName, custom); } // If a problem occurred, an error should already have been issued, // and _attr will be invalid, which is what we want _SetIdTargetRelName(); }
/* static */ bool PxrUsdKatanaUsdInPluginRegistry::_DoFindKind( const TfToken& kind, std::string* opName, const _KindRegistry& reg) { // can cache this if it becomes an issue. for (TfToken currKind = kind; not currKind.IsEmpty(); currKind = KindRegistry::GetBaseKind(currKind)) { if (TfMapLookup(reg, currKind, opName)) { return true; } } return false; }
/* static */ bool PxrUsdKatanaUsdInPluginRegistry::_DoFindKind( const TfToken& kind, std::string* opName, const _KindRegistry& reg) { // can cache this if it becomes an issue. TfToken currKind = kind; while (!currKind.IsEmpty()) { if (TfMapLookup(reg, currKind, opName)) { return true; } if (KindRegistry::HasKind(currKind)) { currKind = KindRegistry::GetBaseKind(currKind); } else { FnLogWarn(TfStringPrintf("Unknown kind: '%s'", currKind.GetText())); return false; } } return false; }
HdTextureResourceSharedPtr UsdImagingGL_GetTextureResource(UsdPrim const& usdPrim, SdfPath const& usdPath, UsdTimeCode time) { if (!TF_VERIFY(usdPrim)) return HdTextureResourceSharedPtr(); if (!TF_VERIFY(usdPath != SdfPath())) return HdTextureResourceSharedPtr(); UsdAttribute attr = _GetTextureResourceAttr(usdPrim, usdPath); SdfAssetPath asset; if (!TF_VERIFY(attr) || !TF_VERIFY(attr.Get(&asset, time))) { return HdTextureResourceSharedPtr(); } HdTextureType textureType = HdTextureType::Uv; TfToken filePath = TfToken(asset.GetResolvedPath()); // If the path can't be resolved, it's either an UDIM texture // or the texture doesn't exists and we can to exit early. if (filePath.IsEmpty()) { filePath = TfToken(asset.GetAssetPath()); if (GlfIsSupportedUdimTexture(filePath)) { textureType = HdTextureType::Udim; } else { TF_DEBUG(USDIMAGING_TEXTURES).Msg( "File does not exist, returning nullptr"); TF_WARN("Unable to find Texture '%s' with path '%s'.", filePath.GetText(), usdPath.GetText()); return {}; } } else { if (GlfIsSupportedPtexTexture(filePath)) { textureType = HdTextureType::Ptex; } } GlfImage::ImageOriginLocation origin = UsdImagingGL_ComputeTextureOrigin(usdPrim); HdWrap wrapS = _GetWrapS(usdPrim, textureType); HdWrap wrapT = _GetWrapT(usdPrim, textureType); HdMinFilter minFilter = _GetMinFilter(usdPrim); HdMagFilter magFilter = _GetMagFilter(usdPrim); float memoryLimit = _GetMemoryLimit(usdPrim); TF_DEBUG(USDIMAGING_TEXTURES).Msg( "Loading texture: id(%s), type(%s)\n", usdPath.GetText(), textureType == HdTextureType::Uv ? "Uv" : textureType == HdTextureType::Ptex ? "Ptex" : "Udim"); HdTextureResourceSharedPtr texResource; TfStopwatch timer; timer.Start(); // Udim's can't be loaded through like other textures, because // we can't select the right factory based on the file type. // We also need to pass the layer context to the factory, // so each file gets resolved properly. GlfTextureHandleRefPtr texture; if (textureType == HdTextureType::Udim) { UdimTextureFactory factory(_FindLayerHandle(attr, time)); texture = GlfTextureRegistry::GetInstance().GetTextureHandle( filePath, origin, &factory); } else { texture = GlfTextureRegistry::GetInstance().GetTextureHandle( filePath, origin); } texResource = HdTextureResourceSharedPtr( new HdStSimpleTextureResource(texture, textureType, wrapS, wrapT, minFilter, magFilter, memoryLimit)); timer.Stop(); TF_DEBUG(USDIMAGING_TEXTURES).Msg(" Load time: %.3f s\n", timer.GetSeconds()); return texResource; }
void Usd_PrimData::_ComposeAndCacheFlags(Usd_PrimDataConstPtr parent, bool isMasterPrim) { // Special-case the root (the only prim which has no parent) and // instancing masters. if (ARCH_UNLIKELY(not parent or isMasterPrim)) { _flags[Usd_PrimActiveFlag] = true; _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 { // Compose and cache 'active'. UsdPrim self(Usd_PrimDataIPtr(this)); bool active = true; self.GetMetadata(SdfFieldKeys->Active, &active); _flags[Usd_PrimActiveFlag] = active; // 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() ? _stage->_GetPcpCache()->IsPayloadIncluded(_primIndex->GetPath()) : parent->IsLoaded()); // According to Model hierarchy rules, only Model Groups may have Model // 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; 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); } } // Get specifier. SdfSpecifier specifier = GetSpecifier(); // This prim is abstract if its parent is or if it's a class. _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; // The presence of clips that may affect attributes on this prim // is computed and set in UsdStage. Default to false. _flags[Usd_PrimClipsFlag] = false; // These flags indicate whether this prim is an instance or an // instance master. _flags[Usd_PrimInstanceFlag] = active and _primIndex->IsInstanceable(); _flags[Usd_PrimMasterFlag] = parent->IsInMaster(); } }
// Walk the shader graph and emit nodes in topological order // to avoid forward-references. static void _WalkGraph(UsdShadeShader const & shadeNode, HdMaterialNetwork *materialNetwork, const TfTokenVector &shaderSourceTypes) { // Store the path of the node HdMaterialNode node; node.path = shadeNode.GetPath(); if (!TF_VERIFY(node.path != SdfPath::EmptyPath())) { return; } // If this node has already been found via another path, we do // not need to add it again. for (HdMaterialNode const& existingNode: materialNetwork->nodes) { if (existingNode.path == node.path) { return; } } // Visit the inputs of this node to ensure they are emitted first. const std::vector<UsdShadeInput> shadeNodeInputs = shadeNode.GetInputs(); for (UsdShadeInput const& input: shadeNodeInputs) { // Check if this input is a connection and if so follow the path UsdShadeConnectableAPI source; TfToken sourceName; UsdShadeAttributeType sourceType; if (UsdShadeConnectableAPI::GetConnectedSource(input, &source, &sourceName, &sourceType)) { // When we find a connection to a shading node output, // walk the upstream shading node. Do not do this for // other sources (ex: a connection to a material // public interface parameter), since they are not // part of the shading node graph. if (sourceType == UsdShadeAttributeType::Output) { UsdShadeShader connectedNode(source); _WalkGraph(connectedNode, materialNetwork, shaderSourceTypes); } } } // Extract the identifier of the node TfToken id; if (!shadeNode.GetShaderId(&id)) { for (auto &sourceType : shaderSourceTypes) { if (SdrShaderNodeConstPtr n = shadeNode.GetShaderNodeForSourceType(sourceType)) { id = n->GetIdentifier(); break; } } } if (!id.IsEmpty()) { node.identifier = id; // If a node is recognizable, we will try to extract the primvar // names that is using since this can help render delegates // optimize what what is needed from a prim when making data // accessible for renderers. _ExtractPrimvarsFromNode(shadeNode, node, materialNetwork); } else { TF_WARN("UsdShade Shader without an id: %s.", node.path.GetText()); node.identifier = TfToken("PbsNetworkMaterialStandIn_2"); } // Add the parameters and the relationships of this node VtValue value; for (UsdShadeInput const& input: shadeNodeInputs) { // Check if this input is a connection and if so follow the path UsdShadeConnectableAPI source; TfToken sourceName; UsdShadeAttributeType sourceType; if (UsdShadeConnectableAPI::GetConnectedSource(input, &source, &sourceName, &sourceType)) { if (sourceType == UsdShadeAttributeType::Output) { // Store the relationship HdMaterialRelationship relationship; relationship.outputId = shadeNode.GetPath(); relationship.outputName = input.GetBaseName(); relationship.inputId = source.GetPath(); relationship.inputName = sourceName; materialNetwork->relationships.push_back(relationship); } else if (sourceType == UsdShadeAttributeType::Input) { // Connected to an input on the public interface. // The source is not a node in the shader network, so // pull the value and pass it in as a parameter. if (UsdShadeInput connectedInput = source.GetInput(sourceName)) { if (connectedInput.Get(&value)) { node.parameters[input.GetBaseName()] = value; } } } } else { // Parameters detected, let's store it if (input.Get(&value)) { node.parameters[input.GetBaseName()] = value; } } } materialNetwork->nodes.push_back(node); }
HdTextureResource::ID UsdImagingGL_GetTextureResourceID(UsdPrim const& usdPrim, SdfPath const& usdPath, UsdTimeCode time, size_t salt) { if (!TF_VERIFY(usdPrim)) { return HdTextureResource::ID(-1); } if (!TF_VERIFY(usdPath != SdfPath())) { return HdTextureResource::ID(-1); } // If the texture name attribute doesn't exist, it might be badly specified // in scene data. UsdAttribute attr = _GetTextureResourceAttr(usdPrim, usdPath); SdfAssetPath asset; if (!attr || !attr.Get(&asset, time)) { TF_WARN("Unable to find texture attribute <%s> in scene data", usdPath.GetText()); return HdTextureResource::ID(-1); } HdTextureType textureType = HdTextureType::Uv; TfToken filePath = TfToken(asset.GetResolvedPath()); if (!filePath.IsEmpty()) { // If the resolved path contains a correct path, then we are // dealing with a ptex or uv textures. if (GlfIsSupportedPtexTexture(filePath)) { textureType = HdTextureType::Ptex; } else { textureType = HdTextureType::Uv; } } else { // If the path couldn't be resolved, then it might be a Udim as they // contain special characters in the path to identify them <Udim>. // Another option is that the path is just wrong and it can not be // resolved. filePath = TfToken(asset.GetAssetPath()); if (GlfIsSupportedUdimTexture(filePath)) { const GlfContextCaps& caps = GlfContextCaps::GetInstance(); if (!UsdImaging_UdimTilesExist(filePath, caps.maxArrayTextureLayers, _FindLayerHandle(attr, time))) { TF_WARN("Unable to find Texture '%s' with path '%s'. Fallback " "textures are not supported for udim", filePath.GetText(), usdPath.GetText()); return HdTextureResource::ID(-1); } if (!caps.arrayTexturesEnabled) { TF_WARN("OpenGL context does not support array textures, " "skipping UDIM Texture %s with path %s.", filePath.GetText(), usdPath.GetText()); return HdTextureResource::ID(-1); } textureType = HdTextureType::Udim; } else if (GlfIsSupportedPtexTexture(filePath)) { TF_WARN("Unable to find Texture '%s' with path '%s'. Fallback " "textures are not supported for ptex", filePath.GetText(), usdPath.GetText()); return HdTextureResource::ID(-1); } else { TF_WARN("Unable to find Texture '%s' with path '%s'. A black " "texture will be substituted in its place.", filePath.GetText(), usdPath.GetText()); return HdTextureResource::ID(-1); } } GlfImage::ImageOriginLocation origin = UsdImagingGL_ComputeTextureOrigin(usdPrim); // Hash on the texture filename. size_t hash = asset.GetHash(); // Hash in wrapping and filtering metadata. HdWrap wrapS = _GetWrapS(usdPrim, textureType); HdWrap wrapT = _GetWrapT(usdPrim, textureType); HdMinFilter minFilter = _GetMinFilter(usdPrim); HdMagFilter magFilter = _GetMagFilter(usdPrim); float memoryLimit = _GetMemoryLimit(usdPrim); boost::hash_combine(hash, origin); boost::hash_combine(hash, wrapS); boost::hash_combine(hash, wrapT); boost::hash_combine(hash, minFilter); boost::hash_combine(hash, magFilter); boost::hash_combine(hash, memoryLimit); // Salt the result to prevent collisions in non-shared imaging. // Note that the salt is ignored for fallback texture hashes above. boost::hash_combine(hash, salt); return HdTextureResource::ID(hash); }
HdSt_MeshShaderKey::HdSt_MeshShaderKey( Hd_GeometricShader::PrimitiveType primitiveType, TfToken shadingTerminal, bool hasCustomDisplacementTerminal, bool smoothNormals, bool doubleSided, bool faceVarying, bool blendWireframeColor, HdCullStyle cullStyle, HdMeshGeomStyle geomStyle) : primType(primitiveType) , cullStyle(cullStyle) , polygonMode(HdPolygonModeFill) , isFaceVarying(faceVarying) , glslfx(_tokens->baseGLSLFX) { if (geomStyle == HdMeshGeomStyleEdgeOnly || geomStyle == HdMeshGeomStyleHullEdgeOnly) { polygonMode = HdPolygonModeLine; } // vertex shader VS[0] = _tokens->instancing; VS[1] = (smoothNormals ? _tokens->smooth : _tokens->flat); VS[2] = _tokens->mainVS; VS[3] = TfToken(); // tessellation control shader const bool isPrimTypePatches = Hd_GeometricShader::IsPrimTypePatches(primType); TCS[0] = isPrimTypePatches ? _tokens->instancing : TfToken(); TCS[1] = isPrimTypePatches ? _tokens->mainBSplineTCS : TfToken(); TCS[2] = TfToken(); // tessellation evaluation shader TES[0] = isPrimTypePatches ? _tokens->instancing : TfToken(); TES[1] = isPrimTypePatches ? _tokens->mainBezierTES : TfToken(); TES[2] = TfToken(); // geometry shader (note that PRIM_MESH_PATCHES uses triangles) GS[0] = _tokens->instancing; GS[1] = isPrimTypePatches ? _tokens->limit : (smoothNormals ? _tokens->smooth : _tokens->flat); GS[2] = ((geomStyle == HdMeshGeomStyleEdgeOnly || geomStyle == HdMeshGeomStyleHullEdgeOnly) ? _tokens->edgeOnlyGS : (geomStyle == HdMeshGeomStyleEdgeOnSurf || geomStyle == HdMeshGeomStyleHullEdgeOnSurf) ? _tokens->edgeOnSurfGS : _tokens->edgeNoneGS); GS[3] = Hd_GeometricShader::IsPrimTypeQuads(primType)? _tokens->mainQuadGS : _tokens->mainTriangleGS; GS[4] = TfToken(); // Optimization : If the mesh does not provide a custom displacement shader // we have an opportunity to fully disable the geometry // stage. if (!hasCustomDisplacementTerminal) { // Geometry shader (along with the displacement shader) // can be fully disabled in the folowing condition. if (smoothNormals && (geomStyle == HdMeshGeomStyleSurf || geomStyle == HdMeshGeomStyleHull) && Hd_GeometricShader::IsPrimTypeTriangles(primType) && (!isFaceVarying)) { GS[0] = TfToken(); } else { // If we were not able to disable the geometry stage // then we will add a very simple displacement shader. GS[4] = _tokens->displacementGS; GS[5] = TfToken(); } } // Optimization : Points don't need any sort of geometry shader so // we ignore it here. if (Hd_GeometricShader::IsPrimTypePoints(primType)) { GS[0] = TfToken(); } // fragment shader FS[0] = _tokens->instancing; FS[1] = (smoothNormals ? _tokens->smooth : _tokens->flat); FS[2] = (doubleSided ? _tokens->doubleSidedFS : _tokens->singleSidedFS); if (isPrimTypePatches) { FS[3] = ((geomStyle == HdMeshGeomStyleEdgeOnly || geomStyle == HdMeshGeomStyleHullEdgeOnly) ? _tokens->patchEdgeOnlyFS : ((geomStyle == HdMeshGeomStyleEdgeOnSurf || geomStyle == HdMeshGeomStyleHullEdgeOnSurf) ? _tokens->patchEdgeOnSurfFS : _tokens->edgeNoneFS)); } else { if (geomStyle == HdMeshGeomStyleEdgeOnly || geomStyle == HdMeshGeomStyleHullEdgeOnly) { FS[3] = blendWireframeColor ? _tokens->edgeOnlyBlendFS : _tokens->edgeOnlyNoBlendFS; } else if (geomStyle == HdMeshGeomStyleEdgeOnSurf || geomStyle == HdMeshGeomStyleHullEdgeOnSurf) { FS[3] = _tokens->edgeOnSurfFS; } else { FS[3] = _tokens->edgeNoneFS; } } TfToken terminalFS; if (shadingTerminal == HdMeshReprDescTokens->surfaceShader) { terminalFS = _tokens->surfaceFS; } else if (shadingTerminal == HdMeshReprDescTokens->surfaceShaderUnlit) { terminalFS = _tokens->surfaceUnlitFS; } else if (shadingTerminal == HdMeshReprDescTokens->constantColor) { terminalFS = _tokens->constantColorFS; } else if (!shadingTerminal.IsEmpty()) { terminalFS = shadingTerminal; } else { terminalFS = _tokens->surfaceFS; } FS[4] = terminalFS; FS[5] = _tokens->mainFS; FS[6] = TfToken(); }
void Hd_SmoothNormalsComputationGPU::Execute( HdBufferArrayRangeSharedPtr const &range) { HD_TRACE_FUNCTION(); HF_MALLOC_TAG_FUNCTION(); if (!glDispatchCompute) return; TF_VERIFY(_adjacency); HdBufferArrayRangeSharedPtr const &adjacencyRange = _adjacency->GetAdjacencyRange(); TF_VERIFY(adjacencyRange); // select shader by datatype TfToken shaderToken; if (_srcDataType == GL_FLOAT) { if (_dstDataType == GL_FLOAT) { shaderToken = HdGLSLProgramTokens->smoothNormalsFloatToFloat; } else if (_dstDataType == GL_DOUBLE) { shaderToken = HdGLSLProgramTokens->smoothNormalsFloatToDouble; } else if (_dstDataType == GL_INT_2_10_10_10_REV) { shaderToken = HdGLSLProgramTokens->smoothNormalsFloatToPacked; } } else if (_srcDataType == GL_DOUBLE) { if (_dstDataType == GL_FLOAT) { shaderToken = HdGLSLProgramTokens->smoothNormalsDoubleToFloat; } else if (_dstDataType == GL_DOUBLE) { shaderToken = HdGLSLProgramTokens->smoothNormalsDoubleToDouble; } else if (_dstDataType == GL_INT_2_10_10_10_REV) { shaderToken = HdGLSLProgramTokens->smoothNormalsDoubleToPacked; } } if (!TF_VERIFY(!shaderToken.IsEmpty())) return; HdGLSLProgramSharedPtr computeProgram = HdGLSLProgram::GetComputeProgram(shaderToken); if (!computeProgram) return; GLuint program = computeProgram->GetProgram().GetId(); // buffer resources for GPU computation HdBufferResourceSharedPtr points = range->GetResource(_srcName); HdBufferResourceSharedPtr normals = range->GetResource(_dstName); HdBufferResourceSharedPtr adjacency = adjacencyRange->GetResource(); // prepare uniform buffer for GPU computation struct Uniform { int vertexOffset; int adjacencyOffset; int pointsOffset; int pointsStride; int normalsOffset; int normalsStride; } uniform; // coherent vertex offset in aggregated buffer array uniform.vertexOffset = range->GetOffset(); // adjacency offset/stride in aggregated adjacency table uniform.adjacencyOffset = adjacencyRange->GetOffset(); // interleaved offset/stride to points // note: this code (and the glsl smooth normal compute shader) assumes // components in interleaved vertex array are always same data type. // i.e. it can't handle an interleaved array which interleaves // float/double, float/int etc. uniform.pointsOffset = points->GetOffset() / points->GetComponentSize(); uniform.pointsStride = points->GetStride() / points->GetComponentSize(); // interleaved offset/stride to normals uniform.normalsOffset = normals->GetOffset() / normals->GetComponentSize(); uniform.normalsStride = normals->GetStride() / normals->GetComponentSize(); // The number of points is based off the size of the output, // However, the number of points in the adjacency table // is computed based off the largest vertex indexed from // to topology (aka topology->ComputeNumPoints). // // Therefore, we need to clamp the number of points // to the number of entries in the adjancency table. int numDestPoints = range->GetNumElements(); int numSrcPoints = _adjacency->GetNumPoints(); int numPoints = std::min(numSrcPoints, numDestPoints); // transfer uniform buffer GLuint ubo = computeProgram->GetGlobalUniformBuffer().GetId(); HdRenderContextCaps const &caps = HdRenderContextCaps::GetInstance(); // XXX: workaround for 319.xx driver bug of glNamedBufferDataEXT on UBO // XXX: move this workaround to renderContextCaps if (false && caps.directStateAccessEnabled) { glNamedBufferDataEXT(ubo, sizeof(uniform), &uniform, GL_STATIC_DRAW); } else { glBindBuffer(GL_UNIFORM_BUFFER, ubo); glBufferData(GL_UNIFORM_BUFFER, sizeof(uniform), &uniform, GL_STATIC_DRAW); glBindBuffer(GL_UNIFORM_BUFFER, 0); } glBindBufferBase(GL_UNIFORM_BUFFER, 0, ubo); glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, points->GetId()); glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, normals->GetId()); glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, adjacency->GetId()); // dispatch compute kernel glUseProgram(program); glDispatchCompute(numPoints, 1, 1); glUseProgram(0); glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT); glBindBufferBase(GL_UNIFORM_BUFFER, 0, 0); glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, 0); glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, 0); glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, 0); }
void UsdImagingGprimAdapter::TrackVariability(UsdPrim const& prim, SdfPath const& cachePath, int requestedBits, int* dirtyBits, UsdImagingInstancerContext const* instancerContext) { // WARNING: This method is executed from multiple threads, the value cache // has been carefully pre-populated to avoid mutating the underlying // container during update. // Why is this OK? // Either the value is unvarying, in which case the time ordinate doesn't // matter; or the value is varying, in which case we will update it upon // first call to Delegate::SetTime(). UsdTimeCode time(1.0); UsdImagingValueCache* valueCache = _GetValueCache(); if (requestedBits & HdChangeTracker::DirtyPrimVar) { if (not _IsVarying(prim, UsdGeomTokens->primvarsDisplayColor, HdChangeTracker::DirtyPrimVar, UsdImagingTokens->usdVaryingPrimVar, dirtyBits, false)) { // Only do this second check if the displayColor isn't already known // to be varying. _IsVarying(prim, UsdGeomTokens->primvarsDisplayOpacity, HdChangeTracker::DirtyPrimVar, UsdImagingTokens->usdVaryingPrimVar, dirtyBits, false); } } if (requestedBits & HdChangeTracker::DirtyExtent) { // Discover time-varying extent. _IsVarying(prim, UsdGeomTokens->extent, HdChangeTracker::DirtyExtent, UsdImagingTokens->usdVaryingExtent, dirtyBits, false); } if (requestedBits & HdChangeTracker::DirtyTransform) { // Discover time-varying transforms. _IsTransformVarying(prim, HdChangeTracker::DirtyTransform, UsdImagingTokens->usdVaryingXform, dirtyBits); } if (requestedBits & HdChangeTracker::DirtyVisibility) { valueCache->GetVisible(cachePath) = GetVisible(prim, time); // Discover time-varying visibility. _IsVarying(prim, UsdGeomTokens->visibility, HdChangeTracker::DirtyVisibility, UsdImagingTokens->usdVaryingVisibility, dirtyBits, true); TfToken purpose = _GetPurpose(prim, time); // Empty purpose means there is no opinion, fall back to geom. if (purpose.IsEmpty()) purpose = UsdGeomTokens->default_; valueCache->GetPurpose(cachePath) = purpose; } }
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(!parent || isMasterPrim)) { _flags[Usd_PrimActiveFlag] = true; _flags[Usd_PrimLoadedFlag] = true; _flags[Usd_PrimModelFlag] = true; _flags[Usd_PrimGroupFlag] = true; _flags[Usd_PrimDefinedFlag] = true; _flags[Usd_PrimMasterFlag] = isMasterPrim; } else { // Compose and cache 'active'. UsdPrim self(Usd_PrimDataIPtr(this), SdfPath()); bool active = true; 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 && (hasPayload ? _stage->_GetPcpCache()->IsPayloadIncluded(_primIndex->GetPath()) : parent->IsLoaded()); // According to Model hierarchy rules, only Model Groups may have Model // 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. 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 (!kind.IsEmpty()) { isGroup = KindRegistry::IsA(kind, KindTokens->group); isModel = isGroup || KindRegistry::IsA(kind, KindTokens->model); } } _flags[Usd_PrimGroupFlag] = isGroup; _flags[Usd_PrimModelFlag] = isModel; // Get specifier. SdfSpecifier specifier = GetSpecifier(); // This prim is abstract if its parent is or if it's a class. _flags[Usd_PrimAbstractFlag] = parent->IsAbstract() || specifier == SdfSpecifierClass; // 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. _flags[Usd_PrimClipsFlag] = false; // These flags indicate whether this prim is an instance or an // instance master. _flags[Usd_PrimInstanceFlag] = active && _primIndex->IsInstanceable(); _flags[Usd_PrimMasterFlag] = parent->IsInMaster(); } }