static bool _GetMayaDictValue(const UsdAttribute& attr, const TfToken& key, T* outVal) { VtValue data = attr.GetCustomDataByKey(_tokens->Maya); if (!data.IsEmpty()) { if (data.IsHolding<VtDictionary>()) { VtValue val; if (TfMapLookup(data.UncheckedGet<VtDictionary>(), key, &val)) { if (val.IsHolding<T>()) { *outVal = val.UncheckedGet<T>(); return true; } else { TF_WARN("Unexpected type for %s[%s] on <%s>.", _tokens->Maya.GetText(), key.GetText(), attr.GetPath().GetText()); } } } else { TF_WARN("Expected to get %s on <%s> to be a dictionary.", _tokens->Maya.GetText(), attr.GetPath().GetText()); } } return false; }
static bool _GetMetadataUnchecked( const MFnDependencyNode& node, const TfToken& key, VtValue* value) { VtValue fallback = SdfSchema::GetInstance().GetFallback(key); if (fallback.IsEmpty()) { return false; } std::string mayaAttrName = _GetMayaAttrNameForMetadataKey(key); MPlug plug = node.findPlug(mayaAttrName.c_str()); if (plug.isNull()) { return false; } TfType ty = fallback.GetType(); VtValue result = UsdMayaWriteUtil::GetVtValue(plug, ty, TfToken()); if (result.IsEmpty()) { TF_RUNTIME_ERROR( "Cannot convert plug '%s' into metadata '%s' (%s)", plug.name().asChar(), key.GetText(), ty.GetTypeName().c_str()); return false; } *value = result; return true; }
UsdAttribute UsdSchemaBase::_CreateAttr(TfToken const &attrName, SdfValueTypeName const & typeName, bool custom, SdfVariability variability, VtValue const &defaultValue, bool writeSparsely) const { UsdPrim prim(GetPrim()); if (writeSparsely && !custom){ // We are a builtin, and we're trying to be parsimonious. // We only need to even CREATE a propertySpec if we are // authoring a non-fallback default value UsdAttribute attr = prim.GetAttribute(attrName); VtValue fallback; if (defaultValue.IsEmpty() || (!attr.HasAuthoredValueOpinion() && attr.Get(&fallback) && fallback == defaultValue)){ return attr; } } UsdAttribute attr(prim.CreateAttribute(attrName, typeName, custom, variability)); if (attr && !defaultValue.IsEmpty()) { attr.Set(defaultValue); } return attr; }
static void _ProcessChildren( const TfToken& childrenField, const VtValue& srcChildrenValue, const VtValue& dstChildrenValue, const SdfLayerHandle& srcLayer, const SdfPath& srcPath, bool childrenInSrc, const SdfLayerHandle& dstLayer, const SdfPath& dstPath, bool childrenInDst, _CopyStack* copyStack) { typedef typename ChildPolicy::FieldType FieldType; typedef std::vector<FieldType> ChildrenVector; if (!TF_VERIFY(srcChildrenValue.IsHolding<ChildrenVector>() || srcChildrenValue.IsEmpty()) || !TF_VERIFY(dstChildrenValue.IsHolding<ChildrenVector>() || dstChildrenValue.IsEmpty())) { return; } const ChildrenVector emptyChildren; const ChildrenVector& srcChildren = srcChildrenValue.IsEmpty() ? emptyChildren : srcChildrenValue.UncheckedGet<ChildrenVector>(); const ChildrenVector& dstChildren = dstChildrenValue.IsEmpty() ? emptyChildren : dstChildrenValue.UncheckedGet<ChildrenVector>(); for (size_t i = 0; i < srcChildren.size(); ++i) { if (srcChildren[i].IsEmpty() || dstChildren[i].IsEmpty()) { continue; } const SdfPath srcChildPath = ChildPolicy::GetChildPath(srcPath, srcChildren[i]); const SdfPath dstChildPath = ChildPolicy::GetChildPath(dstPath, dstChildren[i]); copyStack->emplace_back(srcChildPath, dstChildPath); } // Add entries to the copy stack to mark the removal of child specs // in the destination layer that aren't included in the list of children // to copy. if (childrenInDst) { const VtValue oldDstChildrenValue = dstLayer->GetField(dstPath, childrenField); if (!TF_VERIFY(oldDstChildrenValue.IsHolding<ChildrenVector>())) { return; } for (const auto& oldDstChild : oldDstChildrenValue.UncheckedGet<ChildrenVector>()) { if (std::find(dstChildren.begin(), dstChildren.end(), oldDstChild) == dstChildren.end()) { const SdfPath oldDstChildPath = ChildPolicy::GetChildPath(dstPath, oldDstChild); copyStack->emplace_back(SdfPath(), oldDstChildPath); } } } }
void HdPoints::_PopulateVertexPrimVars(HdDrawItem *drawItem, HdChangeTracker::DirtyBits *dirtyBits) { HD_TRACE_FUNCTION(); HD_MALLOC_TAG_FUNCTION(); SdfPath const& id = GetId(); HdSceneDelegate* delegate = GetDelegate(); HdResourceRegistry *resourceRegistry = &HdResourceRegistry::GetInstance(); // The "points" attribute is expected to be in this list. TfTokenVector primVarNames = delegate->GetPrimVarVertexNames(id); TfTokenVector const& vars = delegate->GetPrimVarVaryingNames(id); primVarNames.insert(primVarNames.end(), vars.begin(), vars.end()); HdBufferSourceVector sources; sources.reserve(primVarNames.size()); int pointsIndexInSourceArray = -1; TF_FOR_ALL(nameIt, primVarNames) { if (not HdChangeTracker::IsPrimVarDirty(*dirtyBits, id, *nameIt)) continue; // TODO: We don't need to pull primvar metadata every time a value // changes, but we need support from the delegate. //assert name not in range.bufferArray.GetResources() VtValue value = delegate->Get(id, *nameIt); if (!value.IsEmpty()) { // Store where the points will be stored in the source array // we need this later to figure out if the number of points is changing // and we need to force a garbage collection to resize the buffer if (*nameIt == HdTokens->points) { pointsIndexInSourceArray = sources.size(); } // XXX: do we need special treatment for width as basicCurves? HdBufferSourceSharedPtr source(new HdVtBufferSource(*nameIt, value)); sources.push_back(source); } } // return before allocation if it's empty. if (sources.empty()) return; if (not drawItem->GetVertexPrimVarRange() or not drawItem->GetVertexPrimVarRange()->IsValid()) { // initialize buffer array HdBufferSpecVector bufferSpecs; TF_FOR_ALL(it, sources) { (*it)->AddBufferSpecs(&bufferSpecs); }
bool UsdGeomPrimvar::ComputeFlattened(VtValue *value, UsdTimeCode time) const { VtValue attrVal; if (!Get(&attrVal, time)) { return false; } // If the primvar attr value is not an array or if the primvar isn't // indexed, simply return the attribute value. if (!attrVal.IsArrayValued() || !IsIndexed()) { *value = VtValue::Take(attrVal); return true; } VtIntArray indices; if (!GetIndices(&indices, time)) { TF_CODING_ERROR("No indices authored for indexed primvar <%s>.", _attr.GetPath().GetText()); return false; } // Handle all known supported array value types. bool foundSupportedType = _ComputeFlattenedArray<VtVec2fArray>(attrVal, indices, value) || _ComputeFlattenedArray<VtVec2dArray>(attrVal, indices, value) || _ComputeFlattenedArray<VtVec2iArray>(attrVal, indices, value) || _ComputeFlattenedArray<VtVec2hArray>(attrVal, indices, value) || _ComputeFlattenedArray<VtVec3fArray>(attrVal, indices, value) || _ComputeFlattenedArray<VtVec3dArray>(attrVal, indices, value) || _ComputeFlattenedArray<VtVec3iArray>(attrVal, indices, value) || _ComputeFlattenedArray<VtVec3hArray>(attrVal, indices, value) || _ComputeFlattenedArray<VtVec4fArray>(attrVal, indices, value) || _ComputeFlattenedArray<VtVec4dArray>(attrVal, indices, value) || _ComputeFlattenedArray<VtVec4iArray>(attrVal, indices, value) || _ComputeFlattenedArray<VtVec4hArray>(attrVal, indices, value) || _ComputeFlattenedArray<VtMatrix3dArray>(attrVal, indices, value) || _ComputeFlattenedArray<VtMatrix4dArray>(attrVal, indices, value) || _ComputeFlattenedArray<VtStringArray>(attrVal, indices, value) || _ComputeFlattenedArray<VtDoubleArray>(attrVal, indices, value) || _ComputeFlattenedArray<VtIntArray>(attrVal, indices, value) || _ComputeFlattenedArray<VtFloatArray>(attrVal, indices, value) || _ComputeFlattenedArray<VtHalfArray>(attrVal, indices, value); if (!foundSupportedType) { TF_WARN("Unsupported indexed primvar value type %s.", attrVal.GetTypeName().c_str()); } return !value->IsEmpty(); }
bool UsdMayaAdaptor::AttributeAdaptor::Get(VtValue* value) const { if (!*this) { return false; } VtValue result = UsdMayaWriteUtil::GetVtValue(_plug, _attrDef->GetTypeName()); if (result.IsEmpty()) { return false; } *value = result; return true; }
void Hd_VtExtractor::Extract(const VtValue &value) { // Type dispatch to _Extractor. // // Iterate over each acceptable type T, calling typeChecker<T>(), which // internally calls value.IsHolding<T>(); if the VtValue IS holding a T, // then pass the held value to _Extractor::Extract<T>(value). _Extractor e; boost::mpl::for_each<_AcceptedTypes>(_TypeChecker<_Extractor>(value, e)); // Guarantee that the _Extractor::Extract method was called exactly once // and issue a runtime error otherwise. (The only case where Extract wont // be called is when the VtValue is holding an unacceptable type). if (e.GetNumComponents() == 0) { TF_RUNTIME_ERROR("Trying to extract a VtValue holding " "unacceptable type: %s", value.GetType().GetTypeName().c_str()); return; } const _GLDataType &glDataType = e.GetGLDataType(); _glComponentType = glDataType.componentType; _glElementType = glDataType.elementType; _size = e.GetSize(); _numComponents = e.GetNumComponents(); _data = e.GetData(); }
PXR_NAMESPACE_OPEN_SCOPE static void _ClearBuffer(GLenum buffer, GLint drawBuffer, const VtValue &value) { // XXX: There has to be a better way to handle the different formats. if (value.IsHolding<int>()) { glClearBufferiv(buffer, drawBuffer, &value.UncheckedGet<int>()); } else if (value.IsHolding<GfVec2i>()) { glClearBufferiv(buffer, drawBuffer, value.UncheckedGet<GfVec2i>().GetArray()); } else if (value.IsHolding<GfVec3i>()) { glClearBufferiv(buffer, drawBuffer, value.UncheckedGet<GfVec3i>().GetArray()); } else if (value.IsHolding<GfVec4i>()) { glClearBufferiv(buffer, drawBuffer, value.UncheckedGet<GfVec4i>().GetArray()); } else if (value.IsHolding<float>()) { glClearBufferfv(buffer, drawBuffer, &value.UncheckedGet<float>()); } else if (value.IsHolding<GfVec2f>()) { glClearBufferfv(buffer, drawBuffer, value.UncheckedGet<GfVec2f>().GetArray()); } else if (value.IsHolding<GfVec3f>()) { glClearBufferfv(buffer, drawBuffer, value.UncheckedGet<GfVec3f>().GetArray()); } else if (value.IsHolding<GfVec4f>()) { glClearBufferfv(buffer, drawBuffer, value.UncheckedGet<GfVec4f>().GetArray()); } else { TF_CODING_ERROR("Unsupported clear value type: %s", value.GetTypeName().c_str()); } }
bool SdfPropertySpec::SetDefaultValue(const VtValue &defaultValue) { if (defaultValue.IsEmpty()) { ClearDefaultValue(); return true; } if (defaultValue.IsHolding<SdfValueBlock>()) { return SetField(SdfFieldKeys->Default, defaultValue); } TfType valueType = GetValueType(); if (valueType.IsUnknown()) { TF_CODING_ERROR("Can't set value on attribute <%s> with " "unknown type \"%s\"", GetPath().GetText(), GetTypeName().GetAsToken().GetText()); return false; } if (ARCH_UNLIKELY(valueType.GetTypeid() == typeid(void))) { // valueType may be provided by a plugin that has not been loaded. // In that case, we cannot get the type info, which is required to cast. // So we load the plugin in that case. if (PlugPluginPtr p = PlugRegistry::GetInstance().GetPluginForType(valueType)) { p->Load(); } } VtValue value = VtValue::CastToTypeid(defaultValue, valueType.GetTypeid()); if (value.IsEmpty()) { TF_CODING_ERROR("Can't set value on <%s> to %s: " "expected a value of type \"%s\"", GetPath().GetText(), TfStringify(defaultValue).c_str(), valueType.GetTypeName().c_str()); return false; } return SetField(SdfFieldKeys->Default, value); }
static void _SetMayaDictValue(const UsdAttribute& attr, const TfToken& flagName, const T& val) { VtValue data = attr.GetCustomDataByKey(_tokens->Maya); VtDictionary newDict; if (!data.IsEmpty()) { if (data.IsHolding<VtDictionary>()) { newDict = data.UncheckedGet<VtDictionary>(); } else { TF_WARN("Expected to get %s on <%s> to be a dictionary.", _tokens->Maya.GetText(), attr.GetPath().GetText()); return; } } newDict[flagName] = VtValue(val); attr.SetCustomDataByKey(_tokens->Maya, VtValue(newDict)); }
bool UsdMayaAdaptor::SetMetadata( const TfToken& key, const VtValue& value, MDGModifier& modifier) { if (!*this) { TF_CODING_ERROR("Adaptor is not valid"); return false; } VtValue fallback; if (!SdfSchema::GetInstance().IsRegistered(key, &fallback)) { TF_CODING_ERROR("Metadata key '%s' is not registered", key.GetText()); return false; } if (fallback.IsEmpty()) { return false; } VtValue castValue = VtValue::CastToTypeOf(value, fallback); if (castValue.IsEmpty()) { TF_CODING_ERROR("Can't cast value to type '%s'", fallback.GetTypeName().c_str()); return false; } std::string mayaAttrName = _GetMayaAttrNameForMetadataKey(key); std::string mayaNiceAttrName = key.GetText(); MFnDependencyNode node(_handle.object()); TfType ty = fallback.GetType(); MObject attrObj = UsdMayaReadUtil::FindOrCreateMayaAttr( ty, TfToken(), SdfVariabilityUniform, node, mayaAttrName, mayaNiceAttrName, modifier); if (attrObj.isNull()) { return false; } MPlug plug = node.findPlug(attrObj); if (!UsdMayaReadUtil::SetMayaAttr(plug, castValue, modifier)) { return false; } return true; }
GlfGLSLFXConfig::Parameters GlfGLSLFXConfig::_GetParameters(VtDictionary const & dict, string *errorStr) const { Parameters ret; VtValue params; // look for the params section if (!TfMapLookup(dict, _tokens->parameters, ¶ms)) { return ret; } // verify that it holds a VtDictionary if (!params.IsHolding<VtDictionary>()) { *errorStr = TfStringPrintf("%s declaration expects a dictionary value", _tokens->parameters.GetText()); return ret; } // look for the parameterOrder section: vector<string> paramOrder; VtValue paramOrderAny; TfMapLookup(dict, _tokens->parameterOrder, ¶mOrderAny); if (!paramOrderAny.IsEmpty()) { // verify the type if (!paramOrderAny.IsHolding<vector<VtValue> >()) { *errorStr = TfStringPrintf("%s declaration expects a list of strings", _tokens->parameterOrder.GetText()); return ret; } const vector<VtValue>& paramOrderList = paramOrderAny.UncheckedGet<vector<VtValue> >(); TF_FOR_ALL(paramIt, paramOrderList) { const VtValue& val = *paramIt; // verify that this value is a string if (!val.IsHolding<string>()) { *errorStr = TfStringPrintf("%s declaration expects a list of " "strings", _tokens->parameterOrder.GetText()); return ret; } const string& paramName = val.UncheckedGet<string>(); if (std::find(paramOrder.begin(), paramOrder.end(), paramName) == paramOrder.end()) { paramOrder.push_back(paramName); } } } const VtDictionary& paramsDict = params.UncheckedGet<VtDictionary>(); // pre-process the paramsDict in order to get the merged ordering TF_FOR_ALL(it, paramsDict) { string paramName = it->first; if (std::find(paramOrder.begin(), paramOrder.end(), paramName) == paramOrder.end()) { paramOrder.push_back(paramName); } }
void HdRprim::_PopulateConstantPrimVars(HdSceneDelegate* delegate, HdDrawItem *drawItem, HdDirtyBits *dirtyBits) { HD_TRACE_FUNCTION(); HF_MALLOC_TAG_FUNCTION(); SdfPath const& id = GetId(); HdRenderIndex &renderIndex = delegate->GetRenderIndex(); HdResourceRegistry *resourceRegistry = &HdResourceRegistry::GetInstance(); // XXX: this should be in a different method // XXX: This should be in HdSt getting the HdSt Shader const HdShader *shader = static_cast<const HdShader *>( renderIndex.GetSprim(HdPrimTypeTokens->shader, _surfaceShaderID)); if (shader == nullptr) { shader = static_cast<const HdShader *>( renderIndex.GetFallbackSprim(HdPrimTypeTokens->shader)); } _sharedData.surfaceShader = shader->GetShaderCode(); // update uniforms HdBufferSourceVector sources; if (HdChangeTracker::IsTransformDirty(*dirtyBits, id)) { GfMatrix4d transform = delegate->GetTransform(id); _sharedData.bounds.SetMatrix(transform); // for CPU frustum culling HdBufferSourceSharedPtr source(new HdVtBufferSource( HdTokens->transform, transform)); sources.push_back(source); source.reset(new HdVtBufferSource(HdTokens->transformInverse, transform.GetInverse())); sources.push_back(source); // if this is a prototype (has instancer), // also push the instancer transform separately. if (!_instancerID.IsEmpty()) { // gather all instancer transforms in the instancing hierarchy VtMatrix4dArray rootTransforms = _GetInstancerTransforms(delegate); VtMatrix4dArray rootInverseTransforms(rootTransforms.size()); bool leftHanded = transform.IsLeftHanded(); for (size_t i = 0; i < rootTransforms.size(); ++i) { rootInverseTransforms[i] = rootTransforms[i].GetInverse(); // flip the handedness if necessary leftHanded ^= rootTransforms[i].IsLeftHanded(); } source.reset(new HdVtBufferSource( HdTokens->instancerTransform, rootTransforms, /*staticArray=*/true)); sources.push_back(source); source.reset(new HdVtBufferSource( HdTokens->instancerTransformInverse, rootInverseTransforms, /*staticArray=*/true)); sources.push_back(source); // XXX: It might be worth to consider to have isFlipped // for non-instanced prims as well. It can improve // the drawing performance on older-GPUs by reducing // fragment shader cost, although it needs more GPU memory. // set as int (GLSL needs 32-bit align for bool) source.reset(new HdVtBufferSource( HdTokens->isFlipped, VtValue(int(leftHanded)))); sources.push_back(source); } } if (HdChangeTracker::IsExtentDirty(*dirtyBits, id)) { _sharedData.bounds.SetRange(GetExtent(delegate)); GfVec3d const & localMin = drawItem->GetBounds().GetBox().GetMin(); HdBufferSourceSharedPtr sourceMin(new HdVtBufferSource( HdTokens->bboxLocalMin, VtValue(GfVec4f( localMin[0], localMin[1], localMin[2], 0)))); sources.push_back(sourceMin); GfVec3d const & localMax = drawItem->GetBounds().GetBox().GetMax(); HdBufferSourceSharedPtr sourceMax(new HdVtBufferSource( HdTokens->bboxLocalMax, VtValue(GfVec4f( localMax[0], localMax[1], localMax[2], 0)))); sources.push_back(sourceMax); } if (HdChangeTracker::IsPrimIdDirty(*dirtyBits, id)) { GfVec4f primIdColor; int32_t primId = GetPrimId(); HdBufferSourceSharedPtr source(new HdVtBufferSource( HdTokens->primID, VtValue(primId))); sources.push_back(source); } if (HdChangeTracker::IsAnyPrimVarDirty(*dirtyBits, id)) { TfTokenVector primVarNames = delegate->GetPrimVarConstantNames(id); sources.reserve(sources.size()+primVarNames.size()); TF_FOR_ALL(nameIt, primVarNames) { if (HdChangeTracker::IsPrimVarDirty(*dirtyBits, id, *nameIt)) { VtValue value = delegate->Get(id, *nameIt); // XXX Hydra doesn't support string primvar yet if (value.IsHolding<std::string>()) continue; if (!value.IsEmpty()) { HdBufferSourceSharedPtr source( new HdVtBufferSource(*nameIt, value)); // if it's an unacceptable type, skip it (e.g. std::string) if (source->GetNumComponents() > 0) { sources.push_back(source); } } } } }
void HdStExtComputation::Sync(HdSceneDelegate *sceneDelegate, HdRenderParam *renderParam, HdDirtyBits *dirtyBits) { HD_TRACE_FUNCTION(); HF_MALLOC_TAG_FUNCTION(); TF_DEBUG(HD_EXT_COMPUTATION_UPDATED).Msg( "HdStExtComputation::Sync %s\n", GetId().GetText()); HdExtComputation::_Sync(sceneDelegate, renderParam, dirtyBits); // We only commit GPU resources when directly executing a GPU computation // or when aggregating inputs for a downstream computation. if (GetGpuKernelSource().empty() && !IsInputAggregation()) { return; } HdRenderIndex &renderIndex = sceneDelegate->GetRenderIndex(); HdStResourceRegistrySharedPtr const & resourceRegistry = boost::dynamic_pointer_cast<HdStResourceRegistry>( renderIndex.GetResourceRegistry()); HdBufferSourceVector inputs; for (TfToken const & inputName: GetSceneInputNames()) { VtValue inputValue = sceneDelegate->GetExtComputationInput( GetId(), inputName); size_t arraySize = inputValue.IsArrayValued() ? inputValue.GetArraySize() : 1; HdBufferSourceSharedPtr inputSource = HdBufferSourceSharedPtr( new HdVtBufferSource(inputName, inputValue, arraySize)); if (inputSource->IsValid()) { inputs.push_back(inputSource); } else { TF_WARN("Unsupported type %s for source %s in extComputation %s.", inputValue.GetType().GetTypeName().c_str(), inputName.GetText(), GetId().GetText()); } } _inputRange.reset(); if (!inputs.empty()) { if (_IsEnabledSharedExtComputationData() && IsInputAggregation()) { uint64_t inputId = _ComputeSharedComputationInputId(0, inputs); HdInstance<uint64_t, HdBufferArrayRangeSharedPtr> barInstance; std::unique_lock<std::mutex> regLog = resourceRegistry->RegisterExtComputationDataRange(inputId, &barInstance); if (barInstance.IsFirstInstance()) { // Allocate the first buffer range for this input key _inputRange = _AllocateComputationDataRange(inputs, resourceRegistry); barInstance.SetValue(_inputRange); TF_DEBUG(HD_SHARED_EXT_COMPUTATION_DATA).Msg( "Allocated shared ExtComputation buffer range: %s: %p\n", GetId().GetText(), (void *)_inputRange.get()); } else { // Share the existing buffer range for this input key _inputRange = barInstance.GetValue(); TF_DEBUG(HD_SHARED_EXT_COMPUTATION_DATA).Msg( "Reused shared ExtComputation buffer range: %s: %p\n", GetId().GetText(), (void *)_inputRange.get()); } } else { // We're not sharing, so go ahead and allocate new buffer range. _inputRange = _AllocateComputationDataRange(inputs, resourceRegistry); } // Make sure that we also release any stale input range data renderIndex.GetChangeTracker().SetGarbageCollectionNeeded(); } }
static void testValue() { { // Test that we can create values holding non-streamable types. _NotStreamable n; VtValue v(n); VtValue copy = v; copy = n; } { // Test that we can store non-default-constructible objects in VtValue. _NotDefaultConstructible n(123); VtValue v(n); VtValue copy = v; copy = n; } { VtValue v(Vt_TestEnumVal1); TF_AXIOM(TfStringify(v) == "Vt_TestEnumVal1"); v = Vt_TestEnumVal2; TF_AXIOM(TfStringify(v) == "Vt_TestEnumVal2"); } { // Test that floating-point values stream as expected. TF_AXIOM(TfStringify(VtValue(0.0)) == "0"); TF_AXIOM(TfStringify(VtValue(3.14159)) == "3.14159"); TF_AXIOM(TfStringify(VtValue(0.1)) == "0.1"); TF_AXIOM(TfStringify(VtValue(-0.000001)) == "-0.000001"); TF_AXIOM(TfStringify( VtValue(std::numeric_limits<double>::infinity())) == "inf"); TF_AXIOM(TfStringify( VtValue(-std::numeric_limits<double>::infinity())) == "-inf"); TF_AXIOM(TfStringify(VtValue(0.0f)) == "0"); TF_AXIOM(TfStringify(VtValue(3.14159f)) == "3.14159"); TF_AXIOM(TfStringify(VtValue(0.1f)) == "0.1"); TF_AXIOM(TfStringify(VtValue(-0.000001f)) == "-0.000001"); TF_AXIOM(TfStringify( VtValue(std::numeric_limits<float>::infinity())) == "inf"); TF_AXIOM(TfStringify( VtValue(-std::numeric_limits<float>::infinity())) == "-inf"); } VtValue v(1.234); if (!v.IsHolding<double>()) die("IsHolding"); if (v.Get<double>() != 1.234) die("Get"); if (v.GetTypeid() != typeid(double)) die("GetTypeid"); if (v.GetType() != TfType::Find<double>()) die("GetType for unregistered type"); if (v.GetElementTypeid() != typeid(void)) die("GetElementTypeid for non-shaped type"); v = VtValue("hello world"); if (v.GetElementTypeid() != typeid(void)) die("GetElementTypeid for non-shaped, non-stack-held type"); if (v.IsArrayValued()) die("IsArrayValued for non-array type"); // Now test with shaped case. v = VtValue(VtDoubleArray(9)); if (v.GetElementTypeid() != typeid(double)) die("GetElementTypeid"); // Test casts... v = VtValue(2.345); if (!v.CanCast<double>()) die("CanCast to same type"); if (v != VtValue::Cast<double>(v)) die("Cast to same type"); v = VtValue(2.345); if (!v.CanCast<int>()) die("CanCast double to int"); if (v.Cast<int>() != 2) die("Cast double to int"); v = VtValue(2.345); if (!v.CanCast<short>()) die("CanCast double to short"); if (v.Cast<short>() != short(2)) die("Cast double to short"); v = VtValue(1.25); if (!v.CanCast<float>()) die("CanCast double to float"); if (v.Cast<float>() != 1.25f) die("Cast double to float"); v = VtValue(1.25); if (v.CanCast<GfVec3d>()) die("CanCast double to Vec3d"); if (!v.Cast<GfVec3d>().IsEmpty()) die("Cast to Vec3d type is not empty"); v = VtValue(1.25); if (!v.CanCastToTypeOf(v)) die("CanCast to same type"); if (v.CastToTypeOf(v).Get<double>() != 1.25) die("Casting to same type got wrong value"); v = VtValue(1.25); VtValue v2 = VtValue(3); if (!v.CanCastToTypeOf(v2)) die("CanCast to type of another value"); if (v2.CastToTypeOf(v).Get<double>() != 3.0) die("Could not cast to type of another value"); v = VtValue(1.25); v2 = VtValue(3); if (!v.CanCastToTypeOf(v2)) die("CanCast to type of another value"); if (VtValue::CastToTypeOf(v2, v).Get<double>() != 3.0) die("Could not cast to type of another value"); v = VtValue(1.25); if (!v.CanCastToTypeid(typeid(double))) die("CanCast to typeid of same type"); if (!v.CanCastToTypeid(typeid(int))) die("CanCast double to typeid of int"); if (v.CanCastToTypeid(typeid(GfVec3d))) die("CanCast double to typeid of GfVec3d"); // Check that too large doubles cast to float infinities v = VtValue(1e50); if (!v.CanCast<float>()) die("CanCast of too large double to float"); if (v.Cast<float>() != std::numeric_limits<float>::infinity()) die("Cast of too large double to float is not +inf"); v = VtValue(-1e50); if (!v.CanCast<float>()) die("CanCast of too small double to float"); if (v.Cast<float>() != -std::numeric_limits<float>::infinity()) die("Cast of too small double to float is not -inf"); // Check that double infinities cast to float infinities v = VtValue(std::numeric_limits<double>::infinity()); if (!v.CanCast<float>()) die("CanCast of double +inf to float"); if (v.Cast<float>() != std::numeric_limits<float>::infinity()) die("Cast of double +inf to float is not +inf"); v = VtValue(-std::numeric_limits<double>::infinity()); if (!v.CanCast<float>()) die("CanCast of double -inf to float"); if (v.Cast<float>() != -std::numeric_limits<float>::infinity()) die("Cast of double -inf to float is not -inf"); // Check that float infinities cast to double infinities v = VtValue(std::numeric_limits<float>::infinity()); if (!v.CanCast<double>()) die("CanCast of float +inf to double"); if (v.Cast<double>() != std::numeric_limits<double>::infinity()) die("Cast of float +inf to double is not +inf"); v = VtValue(-std::numeric_limits<float>::infinity()); if (!v.CanCast<double>()) die("CanCast of float -inf to double"); if (v.Cast<double>() != -std::numeric_limits<double>::infinity()) die("Cast of float -inf to double is not -inf"); // Check that really large long long casts to double v = VtValue(1000000000000000000ll); if (!v.CanCast<double>()) die("CanCast of really large long long to double"); if (v.Cast<double>() != 1e+18) die("Cast of really large long long to double"); // Check that really large long long casts to float v = VtValue(1000000000000000000ll); if (!v.CanCast<float>()) die("CanCast of really large long long to float"); if (v.Cast<float>() != 1e+18f) die("Cast of really large long long to float"); // Check that really large long long casts to GfHalf infinity v = VtValue(1000000000000000000ll); if (!v.CanCast<GfHalf>()) die("CanCast of really large long long to GfHalf"); if (v.Cast<GfHalf>() != std::numeric_limits<GfHalf>::infinity()) die("Cast of really large long long to GfHalf is not +inf"); // Check that really small long long casts to minus GfHalf infinity v = VtValue(-1000000000000000000ll); if (!v.CanCast<GfHalf>()) die("CanCast of really small long long to GfHalf"); if (v.Cast<GfHalf>() != -std::numeric_limits<GfHalf>::infinity()) die("Cast of really small long long to GfHalf is not -inf"); // Check that too large unsigned short casts to GfHalf infinity v = VtValue((unsigned short)65535); if (!v.CanCast<GfHalf>()) die("CanCast of too large unsigned short to GfHalf"); if (v.Cast<GfHalf>() != std::numeric_limits<GfHalf>::infinity()) die("Cast of too large unsigned short to GfHalf is not +inf"); // Some sanity checks v = VtValue((int)0); if (!v.CanCast<double>()) die("CanCast of integer zero to double"); if (v.Cast<double>() != 0.0) die("Cast of integer zero to double not zero"); v = VtValue((int)-1); if (!v.CanCast<double>()) die("CanCast of integer -1 to double"); if (v.Cast<double>() != -1.0) die("Cast of integer -1 to double not -1"); v = VtValue((int)+1); if (!v.CanCast<double>()) die("CanCast of integer one to double"); if (v.Cast<double>() != +1.0) die("Cast of integer one to double not one"); // Range-checked casts. v = VtValue(std::numeric_limits<short>::max()); v.Cast<short>(); TF_AXIOM(v.IsHolding<short>() && v.UncheckedGet<short>() == std::numeric_limits<short>::max()); // Out-of-range should fail. v = VtValue(std::numeric_limits<int>::max()); v.Cast<short>(); TF_AXIOM(v.IsEmpty()); v = VtValue(std::numeric_limits<unsigned int>::max()); v.Cast<int>(); TF_AXIOM(v.IsEmpty()); // expected to succeed _TestVecCast<GfVec2h>(GfVec2i(1, 2)); _TestVecCast<GfVec2f>(GfVec2i(1, 2)); _TestVecCast<GfVec2d>(GfVec2i(1, 2)); _TestVecCast<GfVec2f>(GfVec2h(1, 2)); _TestVecCast<GfVec2d>(GfVec2h(1, 2)); _TestVecCast<GfVec2d>(GfVec2f(1, 2)); _TestVecCast<GfVec2h>(GfVec2f(1, 2)); _TestVecCast<GfVec2h>(GfVec2d(1, 2)); _TestVecCast<GfVec2f>(GfVec2d(1, 2)); _TestVecCast<GfVec3h>(GfVec3i(1, 2, 3)); _TestVecCast<GfVec3f>(GfVec3i(1, 2, 3)); _TestVecCast<GfVec3d>(GfVec3i(1, 2, 3)); _TestVecCast<GfVec3f>(GfVec3h(1, 2, 3)); _TestVecCast<GfVec3d>(GfVec3h(1, 2, 3)); _TestVecCast<GfVec3d>(GfVec3f(1, 2, 3)); _TestVecCast<GfVec3h>(GfVec3f(1, 2, 3)); _TestVecCast<GfVec3h>(GfVec3d(1, 2, 3)); _TestVecCast<GfVec3f>(GfVec3d(1, 2, 3)); _TestVecCast<GfVec4h>(GfVec4i(1, 2, 3, 4)); _TestVecCast<GfVec4f>(GfVec4i(1, 2, 3, 4)); _TestVecCast<GfVec4d>(GfVec4i(1, 2, 3, 4)); _TestVecCast<GfVec4f>(GfVec4h(1, 2, 3, 4)); _TestVecCast<GfVec4d>(GfVec4h(1, 2, 3, 4)); _TestVecCast<GfVec4d>(GfVec4f(1, 2, 3, 4)); _TestVecCast<GfVec4h>(GfVec4f(1, 2, 3, 4)); _TestVecCast<GfVec4h>(GfVec4d(1, 2, 3, 4)); _TestVecCast<GfVec4f>(GfVec4d(1, 2, 3, 4)); _FailVecCast<GfVec4i>(GfVec4h(1, 2, 3, 4)); _FailVecCast<GfVec4i>(GfVec4f(1, 2, 3, 4)); _FailVecCast<GfVec4i>(GfVec4d(1, 2, 3, 4)); _FailVecCast<GfVec3i>(GfVec3h(1, 2, 3)); _FailVecCast<GfVec3i>(GfVec3f(1, 2, 3)); _FailVecCast<GfVec3i>(GfVec3d(1, 2, 3)); _FailVecCast<GfVec2i>(GfVec2h(1, 2)); _FailVecCast<GfVec2i>(GfVec2f(1, 2)); _FailVecCast<GfVec2i>(GfVec2d(1, 2)); // Equality special cases. v = VtValue(); v2 = VtValue(); if (!(v == v2)) die("comparison with empty"); v = VtValue(1.234); if (v == v2) die("comparison with empty"); v2 = VtValue("hello"); if (v == v2) die("comparison of mismatched types"); v = VtValue(1234.0); v2 = VtValue(1234); if (v == v2) die("comparison of mismatched stack-held types"); // Coverage v = VtValue(); if (v.IsArrayValued()) die("IsArrayValued for empty value"); v = VtValue(1.234); if (v.IsArrayValued()) die("scalar value reports it is shaped"); v = VtValue(VtDoubleArray()); if (!v.IsArrayValued()) die("array value reports it is not an array"); // Streaming... VtDictionary d; d["foo"] = 1.234; d["bar"] = "baz"; vector<VtValue> vals; vals.push_back(VtValue(1.234)); vals.push_back(VtValue("hello world")); std::ostringstream stream; stream << VtValue(d); if (stream.str().empty()) die("couldn't stream value holding dictionary."); std::ostringstream stream2; stream2 << VtValue(vals); if (stream2.str().empty()) die("couldn't stream value holding vector of values."); // Default stuff... TF_AXIOM(VtDictionaryGet<double>(d, "foo", VtDefault = 0) == 1.234); TF_AXIOM(VtDictionaryGet<double>(d, "noKey", VtDefault = 3.14) == 3.14); TF_AXIOM(VtDictionaryGet<string>(d, "bar", VtDefault = "hello") == "baz"); TF_AXIOM(VtDictionaryGet<string>(d, "noKey", VtDefault = "bye") == "bye"); // Casting a VtValue holding a TfToken to a string. { TfToken token("token"); VtValue val(token); TF_AXIOM(val.IsHolding<TfToken>()); val.Cast<string>(); TF_AXIOM(val.IsHolding<string>()); TF_AXIOM(val.Get<string>() == "token"); } // Assignment and equality with string literals. { VtValue val; val = "hello"; TF_AXIOM(val.IsHolding<string>()); TF_AXIOM(val.Get<string>() == "hello"); TF_AXIOM(val == "hello"); TF_AXIOM("hello" == val); } // Equality { double d = 1.234, e = 2.71828; VtValue v(d); TF_AXIOM(v == d); TF_AXIOM(d == v); TF_AXIOM(v != e); TF_AXIOM(e != v); } // IsHolding<VtValue> { VtValue v(1.234); TF_AXIOM(v.IsHolding<double>()); TF_AXIOM(v.IsHolding<VtValue>()); } // Shapeliness and other stuff with non-stack-held arrays. { VtVec2iArray a(2), b(3); VtValue v(a); VtValue vclone(v); TF_AXIOM(v.Get<VtVec2iArray>().size() == 2); v = b; TF_AXIOM(v.Get<VtVec2iArray>().size() == 3); TF_AXIOM(v.IsArrayValued()); TF_AXIOM(v.GetElementTypeid() == typeid(GfVec2i)); TF_AXIOM(vclone.Get<VtVec2iArray>().size() == 2); } // Precision-casting of VtArrays { // only testing float <-> double... compound Vec types should // be the same VtFloatArray fa(3), fRoundTripped; VtDoubleArray da; fa[0] = 1.23456567; fa[1] = 4.63256635; fa[2] = 123443634.432; VtValue v(fa); v.Cast<VtDoubleArray>(); TF_AXIOM(v.IsHolding<VtDoubleArray>()); da = v.UncheckedGet<VtDoubleArray>(); VtValue vv(da); vv.Cast<VtFloatArray>(); TF_AXIOM(vv.IsHolding<VtFloatArray>()); fRoundTripped = vv.UncheckedGet<VtFloatArray>(); // verify they compare euqal, but are physically two different arrays TF_AXIOM(fRoundTripped == fa); TF_AXIOM(!fRoundTripped.IsIdentical(fa)); } // Test swapping VtValues holding dictionaries. { VtValue a, b; VtDictionary d1, d2; d1["foo"] = "bar"; d2["bar"] = "foo"; a = d1; b = d2; a.Swap(b); TF_AXIOM(a.Get<VtDictionary>().count("bar")); TF_AXIOM(b.Get<VtDictionary>().count("foo")); } // Test creating VtValues by taking contents of objects, and destructively // removing contents from objects. { string s("hello world!"); VtValue v = VtValue::Take(s); TF_AXIOM(s.empty()); TF_AXIOM(v.IsHolding<string>()); TF_AXIOM(v.UncheckedGet<string>() == "hello world!"); v.Swap(s); TF_AXIOM(v.IsHolding<string>()); TF_AXIOM(v.UncheckedGet<string>().empty()); TF_AXIOM(s == "hello world!"); v.Swap(s); TF_AXIOM(v.IsHolding<string>() && v.UncheckedGet<string>() == "hello world!"); string t = v.Remove<string>(); TF_AXIOM(t == "hello world!"); TF_AXIOM(v.IsEmpty()); v.Swap(t); TF_AXIOM(t.empty()); TF_AXIOM(v.IsHolding<string>() && v.UncheckedGet<string>() == "hello world!"); t = v.UncheckedRemove<string>(); TF_AXIOM(t == "hello world!"); TF_AXIOM(v.IsEmpty()); } // Test calling Get with incorrect type. Should issue an error and produce // some "default" value. { VtValue empty; TfErrorMark m; TF_AXIOM(empty.Get<bool>() == false); TF_AXIOM(!m.IsClean()); } { VtValue d(1.234); TfErrorMark m; TF_AXIOM(d.Get<double>() == 1.234); TF_AXIOM(m.IsClean()); m.SetMark(); TF_AXIOM(d.Get<int>() == 0); TF_AXIOM(!m.IsClean()); m.SetMark(); TF_AXIOM(d.Get<string>() == string()); TF_AXIOM(!m.IsClean()); } }
void HdxRenderTask::_Execute(HdTaskContext* ctx) { HD_TRACE_FUNCTION(); HD_MALLOC_TAG_FUNCTION(); HdRenderPassStateSharedPtr renderPassState; if (_setupTask) { // if _setupTask exists (for backward compatibility), use it renderPassState = _setupTask->GetRenderPassState(); } else { // otherwise, extract from TaskContext _GetTaskContextData(ctx, HdxTokens->renderPassState, &renderPassState); } if (not TF_VERIFY(renderPassState)) return; // Can't use GetTaskContextData because the lightingShader // is optional. VtValue lightingShader = (*ctx)[HdTokens->lightingShader]; // it's possible to not set lighting shader to HdRenderPassState. // Hd_DefaultLightingShader will be used in that case. if (lightingShader.IsHolding<HdLightingShaderSharedPtr>()) { renderPassState->SetLightingShader( lightingShader.Get<HdLightingShaderSharedPtr>()); } // Selection Setup // Note that selectionTask comes after renderTask, so that // it can access rprimIDs populated in RenderTask::_Sync. VtValue vo = (*ctx)[HdxTokens->selectionOffsets]; VtValue vu = (*ctx)[HdxTokens->selectionUniforms]; HdRenderPassShaderSharedPtr renderPassShader = renderPassState->GetRenderPassShader(); if (not vo.IsEmpty() and not vu.IsEmpty()) { HdBufferArrayRangeSharedPtr obar = vo.Get<HdBufferArrayRangeSharedPtr>(); HdBufferArrayRangeSharedPtr ubar = vu.Get<HdBufferArrayRangeSharedPtr>(); renderPassShader->AddBufferBinding( HdBindingRequest(HdBinding::SSBO, HdxTokens->selectionOffsets, obar, /*interleave*/false)); renderPassShader->AddBufferBinding( HdBindingRequest(HdBinding::UBO, HdxTokens->selectionUniforms, ubar, /*interleave*/true)); } else { renderPassShader->RemoveBufferBinding(HdxTokens->selectionOffsets); renderPassShader->RemoveBufferBinding(HdxTokens->selectionUniforms); } renderPassState->Bind(); // execute all render passes. TF_FOR_ALL(it, _passes) { (*it)->Execute(renderPassState); }