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); }
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(); } }
void HdSurfaceShader::Sync() { HD_TRACE_FUNCTION(); HD_MALLOC_TAG_FUNCTION(); // _delegate might be null in certain conditions including when // Hydra is using a fallback surface shader if (not _delegate) { return; } SdfPath const& id = GetID(); HdSceneDelegate* delegate = GetDelegate(); HdResourceRegistry *resourceRegistry = &HdResourceRegistry::GetInstance(); HdChangeTracker& changeTracker = delegate->GetRenderIndex().GetChangeTracker(); HdChangeTracker::DirtyBits bits = changeTracker.GetShaderDirtyBits(id); if(bits & HdChangeTracker::DirtySurfaceShader) { _fragmentSource = delegate->GetSurfaceShaderSource(id); _geometrySource = delegate->GetDisplacementShaderSource(id); // XXX Forcing collections to be dirty to reload everything // Something more efficient can be done here changeTracker.MarkAllCollectionsDirty(); } if(bits & HdChangeTracker::DirtyParams) { HdBufferSourceVector sources; TextureDescriptorVector textures; _params = delegate->GetSurfaceShaderParams(id); TF_FOR_ALL(paramIt, _params) { if (paramIt->IsPrimvar()) { // skip -- maybe not necessary, but more memory efficient continue; } else if (paramIt->IsFallback()) { HdBufferSourceSharedPtr source(new HdVtBufferSource( paramIt->GetName(), delegate->GetSurfaceShaderParamValue(id, paramIt->GetName()))); sources.push_back(source); } else if (paramIt->IsTexture()) { bool bindless = HdRenderContextCaps::GetInstance() .bindlessTextureEnabled; // register bindless handle HdTextureResource::ID texID = delegate->GetTextureResourceID(paramIt->GetConnection()); HdTextureResourceSharedPtr texResource; { HdInstance<HdTextureResource::ID, HdTextureResourceSharedPtr> texInstance; std::unique_lock<std::mutex> regLock = resourceRegistry->RegisterTextureResource(texID, &texInstance); if (not TF_VERIFY(not texInstance.IsFirstInstance(), "%s", paramIt->GetConnection().GetText())) { continue; } texResource = texInstance.GetValue(); if (not TF_VERIFY(texResource)) { continue; } } TextureDescriptor tex; tex.name = paramIt->GetName(); if (texResource->IsPtex()) { tex.type = TextureDescriptor::TEXTURE_PTEX_TEXEL; tex.handle = bindless ? texResource->GetTexelsTextureHandle() : texResource->GetTexelsTextureId(); textures.push_back(tex); if (bindless) { HdBufferSourceSharedPtr source(new Hd_BindlessSamplerBufferSource( tex.name, GL_SAMPLER_2D_ARRAY, tex.handle)); sources.push_back(source); } // layout tex.name = TfToken(std::string(paramIt->GetName().GetText()) + "_layout"); tex.type = TextureDescriptor::TEXTURE_PTEX_LAYOUT; tex.handle = bindless ? texResource->GetLayoutTextureHandle() : texResource->GetLayoutTextureId(); textures.push_back(tex); if (bindless) { HdBufferSourceSharedPtr source(new Hd_BindlessSamplerBufferSource( tex.name, GL_INT_SAMPLER_BUFFER, tex.handle)); sources.push_back(source); } } else { tex.type = TextureDescriptor::TEXTURE_2D; tex.handle = bindless ? texResource->GetTexelsTextureHandle() : texResource->GetTexelsTextureId(); tex.sampler = texResource->GetTexelsSamplerId(); textures.push_back(tex); if (bindless) { HdBufferSourceSharedPtr source(new Hd_BindlessSamplerBufferSource( tex.name, GL_SAMPLER_2D, tex.handle)); sources.push_back(source); } } } } _textureDescriptors = textures; // return before allocation if it's empty. if (sources.empty()) return; // Allocate a new uniform buffer if not exists. if (not _paramArray) { // establish a buffer range HdBufferSpecVector bufferSpecs; TF_FOR_ALL(srcIt, sources) { (*srcIt)->AddBufferSpecs(&bufferSpecs); }