HdStGLSLProgramSharedPtr HdStGLSLProgram::GetComputeProgram( TfToken const &shaderToken, HdStResourceRegistry *resourceRegistry) { // Find the program from registry HdInstance<HdStGLSLProgram::ID, HdStGLSLProgramSharedPtr> programInstance; std::unique_lock<std::mutex> regLock = resourceRegistry->RegisterGLSLProgram( HdStGLSLProgram::ComputeHash(shaderToken), &programInstance); if (programInstance.IsFirstInstance()) { // if not exists, create new one HdStGLSLProgramSharedPtr newProgram( new HdStGLSLProgram(HdTokens->computeShader)); GlfGLSLFX glslfx(HdStPackageComputeShader()); std::string version = "#version 430\n"; if (!newProgram->CompileShader( GL_COMPUTE_SHADER, version + glslfx.GetSource(shaderToken))) { TF_CODING_ERROR("Fail to compile " + shaderToken.GetString()); return HdStGLSLProgramSharedPtr(); } if (!newProgram->Link()) { TF_CODING_ERROR("Fail to link " + shaderToken.GetString()); return HdStGLSLProgramSharedPtr(); } programInstance.SetValue(newProgram); } return programInstance.GetValue(); }
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); }