bool Hd_SmoothNormalsComputation::Resolve() { // dependency check first if (_adjacencyBuilder) { if (not _adjacencyBuilder->IsResolved()) return false; } if (_points) { if (not _points->IsResolved()) return false; } if (not _TryLock()) return false; HD_TRACE_FUNCTION(); HD_MALLOC_TAG_FUNCTION(); if (not TF_VERIFY(_adjacency)) return true; int numPoints = _points->GetNumElements(); HdBufferSourceSharedPtr normals; switch (_points->GetGLElementDataType()) { case GL_FLOAT_VEC3: normals = HdBufferSourceSharedPtr( new HdVtBufferSource( _dstName, VtValue( _adjacency->ComputeSmoothNormals( numPoints, static_cast<const GfVec3f*>(_points->GetData()))))); break; case GL_DOUBLE_VEC3: normals = HdBufferSourceSharedPtr( new HdVtBufferSource( _dstName, VtValue( _adjacency->ComputeSmoothNormals( numPoints, static_cast<const GfVec3d*>(_points->GetData()))))); break; default: TF_CODING_ERROR("Unsupported points type for computing smooth normals"); break; } _SetResult(normals); // call base class to mark as resolved. _SetResolved(); return true; }
bool HdSt_TriangleIndexBuilderComputation::Resolve() { if (!_TryLock()) return false; HD_TRACE_FUNCTION(); VtVec3iArray trianglesFaceVertexIndices; VtIntArray primitiveParam; HdMeshUtil meshUtil(_topology, _id); meshUtil.ComputeTriangleIndices( &trianglesFaceVertexIndices, &primitiveParam); _SetResult(HdBufferSourceSharedPtr( new HdVtBufferSource( HdTokens->indices, VtValue(trianglesFaceVertexIndices)))); _primitiveParam.reset(new HdVtBufferSource( HdTokens->primitiveParam, VtValue(primitiveParam))); _SetResolved(); return true; }
bool HdSt_TriangulateFaceVaryingComputation::Resolve() { if (!TF_VERIFY(_source)) return false; if (!_source->IsResolved()) return false; if (!_TryLock()) return false; HD_TRACE_FUNCTION(); HD_PERF_COUNTER_INCR(HdPerfTokens->triangulateFaceVarying); VtValue result; HdMeshUtil meshUtil(_topology, _id); if(meshUtil.ComputeTriangulatedFaceVaryingPrimvar( _source->GetData(), _source->GetNumElements(), _source->GetGLElementDataType(), &result)) { _SetResult(HdBufferSourceSharedPtr( new HdVtBufferSource( _source->GetName(), result))); } else { _SetResult(_source); } _SetResolved(); return true; }
HdBufferSourceSharedPtr HdSt_MeshTopology::GetTriangulateFaceVaryingComputation( HdBufferSourceSharedPtr const &source, SdfPath const &id) { return HdBufferSourceSharedPtr( new HdSt_TriangulateFaceVaryingComputation(this, source, id)); }
HdBufferSourceSharedPtr Hd_VertexAdjacency::GetAdjacencyBuilderForGPUComputation() { // If the cpu adjacency table has requested to be computed (and not yet // solved), make a dependency to its builder. HdBufferSourceSharedPtr gpuAdjacecnyBuilder = HdBufferSourceSharedPtr(new Hd_AdjacencyBuilderForGPUComputation( this, _adjacencyBuilder.lock())); return gpuAdjacecnyBuilder; }
HdBufferSourceSharedPtr Hd_VertexAdjacency::GetSmoothNormalsComputation( HdBufferSourceSharedPtr const &points, 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(), packed)); }
HdBufferSourceSharedPtr HdSt_MeshTopology::GetPointsIndexBuilderComputation() { // this is simple enough to return the result right away. int numPoints = GetNumPoints(); VtIntArray indices(numPoints); for (int i = 0; i < numPoints; ++i) indices[i] = i; return HdBufferSourceSharedPtr( new HdVtBufferSource(HdTokens->indices, VtValue(indices))); }
HdBufferSourceSharedPtr HdSt_MeshTopology::GetQuadrangulateComputation( HdBufferSourceSharedPtr const &source, SdfPath const &id) { // check if the quad table is already computed as all-quads. if (_quadInfo && _quadInfo->IsAllQuads()) { // no need of quadrangulation. return HdBufferSourceSharedPtr(); } // Make a dependency to quad info, in case if the topology // is chaging and the quad info hasn't been populated. // // It can be null for the second or later primvar animation. // Don't call GetQuadInfoBuilderComputation instead. It may result // unregisterd computation. HdBufferSourceSharedPtr quadInfo = _quadInfoBuilder.lock(); return HdBufferSourceSharedPtr( new HdSt_QuadrangulateComputation(this, source, quadInfo, id)); }
HdBufferSourceSharedPtr HdSt_MeshTopology::GetOsdTopologyComputation(SdfPath const &id) { if (HdBufferSourceSharedPtr builder = _osdTopologyBuilder.lock()) { return builder; } // this has to be the first instance. if (!TF_VERIFY(!_subdivision)) return HdBufferSourceSharedPtr(); // create HdSt_Subdivision _subdivision = HdSt_Osd3Factory::CreateSubdivision(); if (!TF_VERIFY(_subdivision)) return HdBufferSourceSharedPtr(); bool adaptive = RefinesToBSplinePatches(); // create a topology computation for HdSt_Subdivision HdBufferSourceSharedPtr builder = _subdivision->CreateTopologyComputation(this, adaptive, _refineLevel, id); _osdTopologyBuilder = builder; // retain weak ptr return builder; }
bool Hd_AdjacencyBuilderForGPUComputation::Resolve() { if (!_adjacencyBuilder->IsResolved()) return false; if (!_TryLock()) return false; HD_TRACE_FUNCTION(); HF_MALLOC_TAG_FUNCTION(); // prepare buffer source to be transferred. std::vector<int> const &adjacency = _adjacency->GetAdjacencyTable(); // create buffer source VtIntArray array(adjacency.size()); for (size_t i = 0; i < adjacency.size(); ++i) { array[i] = adjacency[i]; } _SetResult(HdBufferSourceSharedPtr(new HdVtBufferSource(HdTokens->adjacency, VtValue(array)))); _SetResolved(); return true; }
bool Hd_SmoothNormalsComputation::Resolve() { // dependency check first if (_adjacencyBuilder) { if (!_adjacencyBuilder->IsResolved()) return false; } if (!_points->IsResolved()) return false; if (!_TryLock()) return false; HD_TRACE_FUNCTION(); HF_MALLOC_TAG_FUNCTION(); if (!TF_VERIFY(_adjacency)) return true; size_t numPoints = _points->GetNumElements(); HdBufferSourceSharedPtr normals; switch (_points->GetTupleType().type) { case HdTypeFloatVec3: if (_packed) { normals = HdBufferSourceSharedPtr( new HdVtBufferSource( _dstName, VtValue( Hd_SmoothNormals::ComputeSmoothNormalsPacked( _adjacency, numPoints, static_cast<const GfVec3f*>(_points->GetData()))))); } else { normals = HdBufferSourceSharedPtr( new HdVtBufferSource( _dstName, VtValue( Hd_SmoothNormals::ComputeSmoothNormals( _adjacency, numPoints, static_cast<const GfVec3f*>(_points->GetData()))))); } break; case HdTypeDoubleVec3: if (_packed) { normals = HdBufferSourceSharedPtr( new HdVtBufferSource( _dstName, VtValue( Hd_SmoothNormals::ComputeSmoothNormalsPacked( _adjacency, numPoints, static_cast<const GfVec3d*>(_points->GetData()))))); } else { normals = HdBufferSourceSharedPtr( new HdVtBufferSource( _dstName, VtValue( Hd_SmoothNormals::ComputeSmoothNormals( _adjacency, numPoints, static_cast<const GfVec3d*>(_points->GetData()))))); } break; default: TF_CODING_ERROR("Unsupported points type for computing smooth normals"); break; } _SetResult(normals); // call base class to mark as resolved. _SetResolved(); return true; }
HdBufferSourceSharedPtr HdSt_MeshTopology::GetTriangleIndexBuilderComputation(SdfPath const &id) { return HdBufferSourceSharedPtr( new HdSt_TriangleIndexBuilderComputation(this, id)); }
void HdxSelectionTask::_Sync(HdTaskContext* ctx) { HD_TRACE_FUNCTION(); SdfPath const& id = GetId(); HdSceneDelegate* delegate = GetDelegate(); HdRenderIndex& index = delegate->GetRenderIndex(); HdChangeTracker& changeTracker = index.GetChangeTracker(); HdDirtyBits bits = changeTracker.GetTaskDirtyBits(id); HdResourceRegistrySharedPtr const& resourceRegistry = index.GetResourceRegistry(); bool paramsChanged = bits & HdChangeTracker::DirtyParams; if (paramsChanged) { _GetSceneDelegateValue(HdTokens->params, &_params); } HdxSelectionTrackerSharedPtr sel; if (_GetTaskContextData(ctx, HdxTokens->selectionState, &sel)) { sel->Sync(&index); } if (sel && (paramsChanged || sel->GetVersion() != _lastVersion)) { _lastVersion = sel->GetVersion(); VtIntArray offsets; VtIntArray values; _hasSelection = sel->GetSelectionOffsetBuffer(&index, &offsets); if (!_selOffsetBar) { HdBufferSpecVector offsetSpecs; offsetSpecs.emplace_back(HdxTokens->hdxSelectionBuffer, HdTupleType { HdTypeInt32, 1 }); _selOffsetBar = resourceRegistry->AllocateSingleBufferArrayRange( /*role*/HdxTokens->selection, offsetSpecs); } if (!_selUniformBar) { HdBufferSpecVector uniformSpecs; uniformSpecs.emplace_back(HdxTokens->selColor, HdTupleType { HdTypeFloatVec4, 1 }); uniformSpecs.emplace_back(HdxTokens->selLocateColor, HdTupleType { HdTypeFloatVec4, 1 }); uniformSpecs.emplace_back(HdxTokens->selMaskColor, HdTupleType { HdTypeFloatVec4, 1 }); _selUniformBar = resourceRegistry->AllocateUniformBufferArrayRange( /*role*/HdxTokens->selection, uniformSpecs); } // // Uniforms // HdBufferSourceSharedPtrVector uniformSources; uniformSources.push_back(HdBufferSourceSharedPtr( new HdVtBufferSource(HdxTokens->selColor, VtValue(_params.selectionColor)))); uniformSources.push_back(HdBufferSourceSharedPtr( new HdVtBufferSource(HdxTokens->selLocateColor, VtValue(_params.locateColor)))); uniformSources.push_back(HdBufferSourceSharedPtr( new HdVtBufferSource(HdxTokens->selMaskColor, VtValue(_params.maskColor)))); resourceRegistry->AddSources(_selUniformBar, uniformSources); // // Offsets // HdBufferSourceSharedPtr offsetSource( new HdVtBufferSource(HdxTokens->hdxSelectionBuffer, VtValue(offsets))); resourceRegistry->AddSource(_selOffsetBar, offsetSource); } if (_params.enableSelection && _hasSelection) { (*ctx)[HdxTokens->selectionOffsets] = _selOffsetBar; (*ctx)[HdxTokens->selectionUniforms] = _selUniformBar; } else { (*ctx)[HdxTokens->selectionOffsets] = VtValue(); (*ctx)[HdxTokens->selectionUniforms] = VtValue(); } }
HdBufferSourceSharedPtr HdSt_MeshTopology::GetQuadIndexBuilderComputation(SdfPath const &id) { return HdBufferSourceSharedPtr( new HdSt_QuadIndexBuilderComputation(this, _quadInfoBuilder.lock(), id)); }
HdBufferSourceSharedPtr _TriangulateFaceVarying(HdBufferSourceSharedPtr const &source, VtIntArray const &faceVertexCounts, VtIntArray const &holeFaces, bool flip, SdfPath const &id) { T const *srcPtr = reinterpret_cast<T const *>(source->GetData()); int numElements = source->GetNumElements(); // CPU face-varying triangulation bool invalidTopology = false; int numFVarValues = 0; int holeIndex = 0; int numHoleFaces = holeFaces.size(); for (int i = 0; i < faceVertexCounts.size(); ++i) { int nv = faceVertexCounts[i] - 2; if (nv < 1) { // skip degenerated face invalidTopology = true; } else if (holeIndex < numHoleFaces and holeFaces[holeIndex] == i) { // skip hole face ++holeIndex; } else { numFVarValues += 3 * nv; } } if (invalidTopology) { TF_WARN("degenerated face found [%s]", id.GetText()); invalidTopology = false; } VtArray<T> results(numFVarValues); // reset holeIndex holeIndex = 0; int dstIndex = 0; for (int i = 0, v = 0; i < faceVertexCounts.size(); ++i) { int nVerts = faceVertexCounts[i]; if (nVerts < 3) { // Skip degenerate faces. } else if (holeIndex < numHoleFaces and holeFaces[holeIndex] == i) { // Skip hole faces. ++holeIndex; } else { // triangulate. // apply same triangulation as index does for (int j=0; j < nVerts-2; ++j) { if (not _FanTriangulate(&results[dstIndex], srcPtr, v, j, numElements, flip)) { invalidTopology = true; } dstIndex += 3; } } v += nVerts; } if (invalidTopology) { TF_WARN("numVerts and verts are incosistent [%s]", id.GetText()); } return HdBufferSourceSharedPtr(new HdVtBufferSource( source->GetName(), VtValue(results))); }
bool Hd_TriangleIndexBuilderComputation::Resolve() { if (not _TryLock()) return false; HD_TRACE_FUNCTION(); // generate triangle index buffer int const * numVertsPtr = _topology->GetFaceVertexCounts().cdata(); int const * vertsPtr = _topology->GetFaceVertexIndices().cdata(); int const * holeFacesPtr = _topology->GetHoleIndices().cdata(); int numFaces = _topology->GetFaceVertexCounts().size(); int numVertIndices = _topology->GetFaceVertexIndices().size(); int numTris = 0; int numHoleFaces = _topology->GetHoleIndices().size(); bool invalidTopology = false; int holeIndex = 0; for (int i=0; i<numFaces; ++i) { int nv = numVertsPtr[i]-2; if (nv < 1) { // skip degenerated face invalidTopology = true; } else if (holeIndex < numHoleFaces and holeFacesPtr[holeIndex] == i) { // skip hole face ++holeIndex; } else { numTris += nv; } } if (invalidTopology) { TF_WARN("degenerated face found [%s]", _id.GetText()); invalidTopology = false; } VtVec3iArray trianglesFaceVertexIndices(numTris); VtIntArray primitiveParam(numTris); bool flip = (_topology->GetOrientation() != HdTokens->rightHanded); // reset holeIndex holeIndex = 0; for (int i=0,tv=0,v=0; i<numFaces; ++i) { int nv = numVertsPtr[i]; if (nv < 3) { // Skip degenerate faces. } else if (holeIndex < numHoleFaces and holeFacesPtr[holeIndex] == i) { // Skip hole faces. ++holeIndex; } else { // edgeFlag is used for inner-line removal of non-triangle // faces on wireframe shading. // // 0__ 0 0 0__ // _/|\ \_ _/. .. . \_ // _/ | \ \_ -> _/ . . . . \_ // / A |C \ B \_ / A . .C . . B \_ // 1-----2---3----4 1-----2 1---2 1----2 // // Type EdgeFlag Draw // - 0 show all edges // A 1 hide [2-0] // B 2 hide [0-1] // C 3 hide [0-1] and [2-0] // int edgeFlag = 0; for (int j=0; j < nv-2; ++j) { if (nv > 3) { if (j == 0) edgeFlag = flip ? 2 : 1; else if (j == nv-3) edgeFlag = flip ? 1 : 2; else edgeFlag = 3; } if (not _FanTriangulate( trianglesFaceVertexIndices[tv], vertsPtr, v, j, numVertIndices, flip)) { invalidTopology = true; } // note that ptex indexing isn't available along with // triangulation. int coarseFaceParam = HdMeshTopology::EncodeCoarseFaceParam(i, edgeFlag); primitiveParam[tv] = coarseFaceParam; ++tv; } } // When the face is degenerate and nv > 0, we need to increment the v // pointer to walk past the degenerate verts. v += nv; } if (invalidTopology) { TF_WARN("numVerts and verts are incosistent [%s]", _id.GetText()); } _SetResult(HdBufferSourceSharedPtr( new HdVtBufferSource( HdTokens->indices, VtValue(trianglesFaceVertexIndices)))); _primitiveParam.reset(new HdVtBufferSource( HdTokens->primitiveParam, VtValue(primitiveParam))); _SetResolved(); return true; }
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(); } }