diff --git a/pxr/imaging/glf/CMakeLists.txt b/pxr/imaging/glf/CMakeLists.txt index c110f3153a..b6c02ff97c 100644 --- a/pxr/imaging/glf/CMakeLists.txt +++ b/pxr/imaging/glf/CMakeLists.txt @@ -89,6 +89,7 @@ pxr_library(glf uvTextureStorage uvTextureStorageData vdbTexture + vdbTextureContainer ${optionalPublicClasses} PRIVATE_CLASSES @@ -97,12 +98,14 @@ pxr_library(glf PUBLIC_HEADERS api.h + textureContainer.h PRIVATE_HEADERS rankedTypeMap.h stb/stb_image.h stb/stb_image_resize.h stb/stb_image_write.h + textureContainerImpl.h CPPFILES ${optionalCppFiles} diff --git a/pxr/imaging/glf/plugInfo.json b/pxr/imaging/glf/plugInfo.json index 2ed6d5e5c5..91a3df717d 100644 --- a/pxr/imaging/glf/plugInfo.json +++ b/pxr/imaging/glf/plugInfo.json @@ -24,8 +24,8 @@ "textureTypes": ["*"], "precedence": 0 }, - "GlfVdbTexture" : { - "bases": ["GlfBaseTexture"], + "GlfVdbTextureContainer" : { + "bases": ["GlfTexture"], "textureTypes": ["vdb"], "precedence": 0 }, diff --git a/pxr/imaging/glf/texture.cpp b/pxr/imaging/glf/texture.cpp index 19aff8e16e..98db8b9ab4 100644 --- a/pxr/imaging/glf/texture.cpp +++ b/pxr/imaging/glf/texture.cpp @@ -145,5 +145,12 @@ GlfTexture::IsOriginLowerLeft() const return _originLocation == GlfImage::OriginLowerLeft; } +void +GlfTexture::GarbageCollect() +{ + // Nothing to do here. + // Only needed for containers of textures. +} + PXR_NAMESPACE_CLOSE_SCOPE diff --git a/pxr/imaging/glf/texture.h b/pxr/imaging/glf/texture.h index ee83960918..3c6b7efc62 100644 --- a/pxr/imaging/glf/texture.h +++ b/pxr/imaging/glf/texture.h @@ -138,6 +138,11 @@ class GlfTexture : public TfRefBase, public TfWeakBase, boost::noncopyable { GLF_API bool IsOriginLowerLeft() const; + /// An opportunity to throw out unused textures if this is + /// a container for textures. + GLF_API + virtual void GarbageCollect(); + protected: GLF_API GlfTexture(); diff --git a/pxr/imaging/glf/textureContainer.h b/pxr/imaging/glf/textureContainer.h new file mode 100644 index 0000000000..9c98ba1cf4 --- /dev/null +++ b/pxr/imaging/glf/textureContainer.h @@ -0,0 +1,86 @@ +// +// Copyright 2020 Pixar +// +// Licensed under the Apache License, Version 2.0 (the "Apache License") +// with the following modification; you may not use this file except in +// compliance with the Apache License and the following modification to it: +// Section 6. Trademarks. is deleted and replaced with: +// +// 6. Trademarks. This License does not grant permission to use the trade +// names, trademarks, service marks, or product names of the Licensor +// and its affiliates, except as required to comply with Section 4(c) of +// the License and to reproduce the content of the NOTICE file. +// +// You may obtain a copy of the Apache License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the Apache License with the above modification is +// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the Apache License for the specific +// language governing permissions and limitations under the Apache License. +// +#ifndef PXR_IMAGING_GLF_TEXTURE_CONTAINER_H +#define PXR_IMAGING_GLF_TEXTURE_CONTAINER_H + +/// \file glf/textureContainer.h + +#include "pxr/pxr.h" +#include "pxr/imaging/glf/api.h" + +#include "pxr/base/tf/declarePtrs.h" + +#include + +PXR_NAMESPACE_OPEN_SCOPE + +TF_DECLARE_WEAK_AND_REF_PTRS(GlfTextureHandle); +TF_DECLARE_REF_PTRS(GlfTexture); + +/// \class GlfTextureContainer +/// +/// A base class for texture containers, e.g., for a movie file where a frame +/// corresponds to a texture, for an exr file where a subimage corresponds +/// to a texture, or for an OpenVDB file where a grid corresponds to a texture. +/// +/// Templated since for, e.g., a movie we would key the container by frame +/// number but for an exr file by subimage name. +/// +/// A note on garbage collection: texture containers are registered with and +/// will be garbage collected by the texture registry. Thus, a texture in a +/// container has to hold on to a ref ptr to the container's handle so that +/// the registry won't delete the container while any of the textures in the +/// container is in use. See GarbageCollect for more details. +/// +template +class GlfTextureContainer : public GlfTexture { +public: + + /// Get texture handle for a particular frame, subimage, grid, ... + GLF_API + GlfTextureHandlePtr GetTextureHandle(Identifier const &identifier); + + /// Implements the garbage collection of textures in this container. + /// + /// When the Glf clients give up all their references to all textures in + /// this container, garbage collection will happen in two steps: + /// the container will note that there are no other references and + /// deletes the textures which references the container. + /// Thus, the texture registry is having the only remaining reference to + /// the container and will delete the container. + GLF_API + void GarbageCollect() override; + +protected: + // Create texture for a particular frame, subimage, grid, ... + virtual GlfTextureRefPtr _CreateTexture(Identifier const &identifier) = 0; + + // Texture handles for frames, subimage, grids, ... + std::map _textureHandles; +}; + +PXR_NAMESPACE_CLOSE_SCOPE + +#endif + diff --git a/pxr/imaging/glf/textureContainerImpl.h b/pxr/imaging/glf/textureContainerImpl.h new file mode 100644 index 0000000000..5100f705d5 --- /dev/null +++ b/pxr/imaging/glf/textureContainerImpl.h @@ -0,0 +1,67 @@ +// +// Copyright 2020 Pixar +// +// Licensed under the Apache License, Version 2.0 (the "Apache License") +// with the following modification; you may not use this file except in +// compliance with the Apache License and the following modification to it: +// Section 6. Trademarks. is deleted and replaced with: +// +// 6. Trademarks. This License does not grant permission to use the trade +// names, trademarks, service marks, or product names of the Licensor +// and its affiliates, except as required to comply with Section 4(c) of +// the License and to reproduce the content of the NOTICE file. +// +// You may obtain a copy of the Apache License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the Apache License with the above modification is +// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the Apache License for the specific +// language governing permissions and limitations under the Apache License. +// +#ifndef PXR_IMAGING_GLF_TEXTURE_CONTAINER_IMPL_H +#define PXR_IMAGING_GLF_TEXTURE_CONTAINER_IMPL_H + +#include "pxr/imaging/glf/textureContainer.h" + +#include "pxr/imaging/glf/textureHandle.h" +#include "pxr/base/trace/trace.h" + +PXR_NAMESPACE_OPEN_SCOPE + +template +GlfTextureHandlePtr +GlfTextureContainer::GetTextureHandle( + Identifier const &identifier) +{ + GlfTextureHandleRefPtr &textureHandle = _textureHandles[identifier]; + if (!textureHandle) { + // Create texture handle if it was not in map + textureHandle = GlfTextureHandle::New(_CreateTexture(identifier)); + } + return textureHandle; +} + +template +void +GlfTextureContainer::GarbageCollect() +{ + TRACE_FUNCTION(); + + // Garbage collection similar to texture registry. + for (auto it = _textureHandles.begin(); it != _textureHandles.end(); ) { + const GlfTextureHandleRefPtr &handle = it->second; + // Delete texture if we hold on to the only reference. + if (TF_VERIFY(handle) && handle->IsUnique()) { + it = _textureHandles.erase(it); + } else { + ++it; + } + } +} + +PXR_NAMESPACE_CLOSE_SCOPE + +#endif diff --git a/pxr/imaging/glf/textureRegistry.cpp b/pxr/imaging/glf/textureRegistry.cpp index 976e24f2ec..a8ffd47f6f 100644 --- a/pxr/imaging/glf/textureRegistry.cpp +++ b/pxr/imaging/glf/textureRegistry.cpp @@ -319,6 +319,14 @@ GlfTextureRegistry::GarbageCollectIfNeeded() while (it != _textureRegistry.end()){ const GlfTextureHandleRefPtr &handle = it->second.GetHandle(); + // Call garbage collection on texture containers first, see + // GlfTextureContainer::GarbageCollect() for reason. + if (TF_VERIFY(handle)) { + if (GlfTexturePtr texture = handle->GetTexture()) { + texture->GarbageCollect(); + } + } + // Null handles should not have been added to the registry if (TF_VERIFY(handle) && handle->IsUnique()) { it = _textureRegistry.erase(it); diff --git a/pxr/imaging/glf/vdbTexture.cpp b/pxr/imaging/glf/vdbTexture.cpp index 3ab7350e08..189f0aa170 100644 --- a/pxr/imaging/glf/vdbTexture.cpp +++ b/pxr/imaging/glf/vdbTexture.cpp @@ -25,6 +25,7 @@ // #include "pxr/imaging/glf/vdbTexture.h" +#include "pxr/imaging/glf/vdbTextureContainer.h" #ifdef PXR_OPENVDB_SUPPORT_ENABLED #include "pxr/imaging/glf/vdbTextureData.h" #else @@ -35,23 +36,12 @@ PXR_NAMESPACE_OPEN_SCOPE -TF_REGISTRY_FUNCTION(TfType) -{ - using Type = GlfVdbTexture; - TfType t = TfType::Define >(); - t.SetFactory< GlfTextureFactory >(); -} - -GlfVdbTextureRefPtr -GlfVdbTexture::New(TfToken const &filePath) -{ - return TfCreateRefPtr(new GlfVdbTexture(filePath)); -} - GlfVdbTextureRefPtr -GlfVdbTexture::New(std::string const &filePath) +GlfVdbTexture::New( + GlfVdbTextureContainerRefPtr const &textureContainer, + TfToken const &gridName) { - return New(TfToken(filePath)); + return TfCreateRefPtr(new GlfVdbTexture(textureContainer, gridName)); } int @@ -60,9 +50,11 @@ GlfVdbTexture::GetNumDimensions() const return 3; } -GlfVdbTexture::GlfVdbTexture(TfToken const &filePath) - : GlfBaseTexture() - , _filePath(filePath) +GlfVdbTexture::GlfVdbTexture( + GlfVdbTextureContainerRefPtr const &textureContainer, + TfToken const &gridName) + : _textureContainer(textureContainer) + , _gridName(gridName) { } @@ -71,7 +63,7 @@ GlfVdbTexture::GetTextureInfo(bool forceLoad) { VtDictionary info = GlfBaseTexture::GetTextureInfo(forceLoad); - info["imageFilePath"] = _filePath; + info["imageFilePath"] = _textureContainer->GetFilePath().GetString(); return info; } @@ -89,7 +81,10 @@ GlfVdbTexture::_ReadTexture() #ifdef PXR_OPENVDB_SUPPORT_ENABLED GlfVdbTextureDataRefPtr const texData = - GlfVdbTextureData::New(_filePath, GetMemoryRequested()); + GlfVdbTextureData::New( + _textureContainer->GetFilePath().GetString(), + _gridName, + GetMemoryRequested()); if (texData) { texData->Read(0, _GenerateMipmap()); diff --git a/pxr/imaging/glf/vdbTexture.h b/pxr/imaging/glf/vdbTexture.h index 7852a7aa0f..10a0125340 100644 --- a/pxr/imaging/glf/vdbTexture.h +++ b/pxr/imaging/glf/vdbTexture.h @@ -35,25 +35,24 @@ PXR_NAMESPACE_OPEN_SCOPE +TF_DECLARE_WEAK_AND_REF_PTRS(GlfVdbTextureContainer); TF_DECLARE_WEAK_AND_REF_PTRS(GlfVdbTexture); /// \class GlfVdbTexture /// -/// Represents a 3-dimensional texture read from an OpenVDB file. +/// Represents a 3-dimensional texture read from grid in an OpenVDB file. /// -/// Current limitations: we always use the first grid in the OpenVDB file. -/// The texture is always loaded at the full resolution of the OpenVDB grid, -/// ignoring the memory request. +/// This texture is supposed to be held by a GlfVdbTextureContainer which +/// tells this texture also what OpenVDB file to read. /// class GlfVdbTexture : public GlfBaseTexture { public: - /// Creates a new texture instance for the OpenVDB file at \p filePath + /// Creates a new texture instance for the grid named \gridName in + /// the OpenVDB file opened by \p textureContainer. GLF_API - static GlfVdbTextureRefPtr New(TfToken const &filePath); - - /// Creates a new texture instance for the OpenVDB file at \p filePath - GLF_API - static GlfVdbTextureRefPtr New(std::string const &filePath); + static GlfVdbTextureRefPtr New( + GlfVdbTextureContainerRefPtr const &textureContainer, + TfToken const &gridName); /// Returns the transform of the grid in the OpenVDB file as well as the /// bounding box of the samples in the corresponding OpenVDB tree. @@ -72,7 +71,9 @@ class GlfVdbTexture : public GlfBaseTexture { protected: GLF_API - GlfVdbTexture(TfToken const &filePath); + GlfVdbTexture( + GlfVdbTextureContainerRefPtr const &textureContainer, + TfToken const &gridName); GLF_API void _ReadTexture() override; @@ -81,7 +82,8 @@ class GlfVdbTexture : public GlfBaseTexture { bool _GenerateMipmap() const; private: - const TfToken _filePath; + GlfVdbTextureContainerRefPtr const _textureContainer; + const TfToken _gridName; GfBBox3d _boundingBox; }; diff --git a/pxr/imaging/glf/vdbTextureContainer.cpp b/pxr/imaging/glf/vdbTextureContainer.cpp new file mode 100644 index 0000000000..94645b0b47 --- /dev/null +++ b/pxr/imaging/glf/vdbTextureContainer.cpp @@ -0,0 +1,89 @@ +// +// Copyright 2020 Pixar +// +// Licensed under the Apache License, Version 2.0 (the "Apache License") +// with the following modification; you may not use this file except in +// compliance with the Apache License and the following modification to it: +// Section 6. Trademarks. is deleted and replaced with: +// +// 6. Trademarks. This License does not grant permission to use the trade +// names, trademarks, service marks, or product names of the Licensor +// and its affiliates, except as required to comply with Section 4(c) of +// the License and to reproduce the content of the NOTICE file. +// +// You may obtain a copy of the Apache License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the Apache License with the above modification is +// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the Apache License for the specific +// language governing permissions and limitations under the Apache License. + +#include "pxr/imaging/glf/vdbTextureContainer.h" + +#include "pxr/imaging/glf/vdbTexture.h" +#include "pxr/imaging/glf/textureContainerImpl.h" + +#include "pxr/base/tf/registryManager.h" +#include "pxr/base/tf/type.h" + +PXR_NAMESPACE_OPEN_SCOPE + +template class GlfTextureContainer; + +TF_REGISTRY_FUNCTION(TfType) +{ + using Type = GlfVdbTextureContainer; + TfType t = TfType::Define >(); + t.SetFactory< GlfTextureFactory >(); +} + +GlfVdbTextureContainerRefPtr +GlfVdbTextureContainer::New(TfToken const &filePath) +{ + return TfCreateRefPtr(new GlfVdbTextureContainer(filePath)); +} + +GlfVdbTextureContainerRefPtr +GlfVdbTextureContainer::New(std::string const &filePath) +{ + return New(TfToken(filePath)); +} + +GlfVdbTextureContainer::GlfVdbTextureContainer(TfToken const &filePath) + : _filePath(filePath) +{ +} + +GlfVdbTextureContainer::~GlfVdbTextureContainer() = default; + +GLuint +GlfVdbTextureContainer::GetGlTextureName() +{ + return 0; +} + +GlfTexture::BindingVector +GlfVdbTextureContainer::GetBindings(TfToken const &identifier, + GLuint samplerName) +{ + return {}; +} + +VtDictionary +GlfVdbTextureContainer::GetTextureInfo(bool forceLoad) +{ + return VtDictionary(); +} + +GlfTextureRefPtr +GlfVdbTextureContainer::_CreateTexture(TfToken const &identifier) +{ + // Creates texture for respective grid. + TfRefPtr const self(this); + return GlfVdbTexture::New(self, identifier); +} + +PXR_NAMESPACE_CLOSE_SCOPE diff --git a/pxr/imaging/glf/vdbTextureContainer.h b/pxr/imaging/glf/vdbTextureContainer.h new file mode 100644 index 0000000000..afd730cae4 --- /dev/null +++ b/pxr/imaging/glf/vdbTextureContainer.h @@ -0,0 +1,98 @@ +// +// Copyright 2020 Pixar +// +// Licensed under the Apache License, Version 2.0 (the "Apache License") +// with the following modification; you may not use this file except in +// compliance with the Apache License and the following modification to it: +// Section 6. Trademarks. is deleted and replaced with: +// +// 6. Trademarks. This License does not grant permission to use the trade +// names, trademarks, service marks, or product names of the Licensor +// and its affiliates, except as required to comply with Section 4(c) of +// the License and to reproduce the content of the NOTICE file. +// +// You may obtain a copy of the Apache License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the Apache License with the above modification is +// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the Apache License for the specific +// language governing permissions and limitations under the Apache License. +// +#ifndef PXR_IMAGING_GLF_VDB_TEXTURE_CONTAINER_H +#define PXR_IMAGING_GLF_VDB_TEXTURE_CONTAINER_H + +/// \file glf/vdbTextureContainer.h + +#include "pxr/pxr.h" +#include "pxr/imaging/glf/api.h" +#include "pxr/imaging/glf/texture.h" +#include "pxr/imaging/glf/textureContainer.h" + +#include "pxr/base/tf/declarePtrs.h" + +PXR_NAMESPACE_OPEN_SCOPE + +TF_DECLARE_WEAK_AND_REF_PTRS(GlfTextureHandle); + +TF_DECLARE_WEAK_AND_REF_PTRS(GlfVdbTextureContainer); + +/// \class GlfVdbTextureContainer +/// +/// A container for 3-dimension textures read from the grids in an OpenVDB file +/// +class GlfVdbTextureContainer : public GlfTextureContainer { +public: + /// Creates a new container for the OpenVDB file \p filePath + GLF_API + static GlfVdbTextureContainerRefPtr New(TfToken const &filePath); + + /// Creates a new container for the OpenVDB file \p filePath + GLF_API + static GlfVdbTextureContainerRefPtr New(std::string const &filePath); + + GLF_API + ~GlfVdbTextureContainer() override; + + /// Returns invalid texture name. + /// + /// Clients are supposed to get texture information from the GlfVdbTexture + /// returned by GlfVdbTextureContainer::GetTextureHandle() + GLF_API + GLuint GetGlTextureName() override; + + + /// Returns empty vector. + /// + /// Clients are supposed to get texture information from the GlfVdbTexture + /// returned by GlfVdbTextureContainer::GetTextureHandle() + GLF_API + BindingVector GetBindings(TfToken const & identifier, + GLuint samplerName) override; + + /// Returns empty dict. + /// + /// Clients are supposed to get texture information from the GlfVdbTexture + /// returned by GlfVdbTextureContainer::GetTextureHandle() + GLF_API + VtDictionary GetTextureInfo(bool forceLoad) override; + + /// The file path of the OpenVDB file + /// + GLF_API + TfToken const &GetFilePath() const { return _filePath; } + +private: + GlfVdbTextureContainer(TfToken const &filePath); + + GlfTextureRefPtr _CreateTexture(TfToken const &identifier) override; + +private: + const TfToken _filePath; +}; + +PXR_NAMESPACE_CLOSE_SCOPE + +#endif diff --git a/pxr/imaging/glf/vdbTextureData.cpp b/pxr/imaging/glf/vdbTextureData.cpp index be5311d6dd..3d3809038c 100644 --- a/pxr/imaging/glf/vdbTextureData.cpp +++ b/pxr/imaging/glf/vdbTextureData.cpp @@ -27,6 +27,7 @@ #include "pxr/imaging/glf/image.h" #include "pxr/imaging/glf/utils.h" #include "pxr/imaging/glf/vdbTextureData.h" +#include "pxr/imaging/glf/vdbTextureContainer.h" #include "pxr/base/tf/fileUtils.h" #include "pxr/base/trace/trace.h" @@ -37,16 +38,20 @@ PXR_NAMESPACE_OPEN_SCOPE GlfVdbTextureDataRefPtr -GlfVdbTextureData::New( - std::string const &filePath, const size_t targetMemory) +GlfVdbTextureData::New(std::string const &filePath, + std::string const &gridName, + const size_t targetMemory) { - return TfCreateRefPtr(new GlfVdbTextureData(filePath, targetMemory)); + return TfCreateRefPtr( + new GlfVdbTextureData(filePath, gridName, targetMemory)); } GlfVdbTextureData::GlfVdbTextureData( - const std::string &filePath, + std::string const &filePath, + std::string const &gridName, const size_t targetMemory) : _filePath(filePath), + _gridName(gridName), _targetMemory(targetMemory), _nativeWidth(0), _nativeHeight(0), _nativeDepth(1), _bytesPerPixel(0), @@ -200,7 +205,7 @@ class _DenseGridHolder : public GlfVdbTextureData_DenseGridHolderBase // Allocate dense grid of given size : _denseGrid(bbox) { - TRACE_SCOPE("GlfVdbTextureData: Copy to dense"); + TRACE_FUNCTION_SCOPE("GlfVdbTextureData: Copy to dense"); openvdb::tools::copyToDense(grid->tree(), _denseGrid); } @@ -249,44 +254,43 @@ _ExtractTransformFromGrid(const openvdb::GridBase::Ptr &grid) return GfMatrix4d(reinterpret_cast(m.asPointer())); } -// Load the first grid from an OpenVDB file +// Load the grid with given name from the OpenVDB file at given path openvdb::GridBase::Ptr -_LoadGridFromFile(openvdb::io::File &f) -{ - TRACE_FUNCTION(); - - if (f.beginName() == f.endName()) { - const std::string &filename = f.filename(); - TF_WARN("OpenVDB file %s has no grid", filename.c_str()); - return nullptr; - } - - const std::string &gridName = f.beginName().gridName(); - TF_DEBUG(GLF_DEBUG_VDB_TEXTURE).Msg( - "[VdbTextureData] Loading first grid (name: '%s')\n", - gridName.c_str()); - - return f.readGrid(gridName); -} - -// Load the first grid from the OpenVDB file at given path -openvdb::GridBase::Ptr -_LoadGrid(const std::string &filePath) +_LoadGrid(const std::string &filePath, std::string const &gridName) { TRACE_FUNCTION(); + openvdb::initialize(); openvdb::io::File f(filePath); - try { - f.open(); - } catch (openvdb::IoError e) { - TF_WARN("Could not open OpenVDB file: %s", e.what()); + { + TRACE_FUNCTION_SCOPE("Opening VDB file"); + try { + f.open(); + } catch (openvdb::IoError e) { + TF_WARN("Could not open OpenVDB file: %s", e.what()); + return nullptr; + } catch (openvdb::LookupError e) { + // Occurs, e.g., when there is an unknown grid type in VDB file + TF_WARN("Could not parse OpenVDB file: %s", e.what()); + return nullptr; + } + } + + if (!f.hasGrid(gridName)) { + TF_WARN("OpenVDB file %s has no grid %s", + filePath.c_str(), gridName.c_str()); return nullptr; } - openvdb::GridBase::Ptr const result = _LoadGridFromFile(f); + openvdb::GridBase::Ptr const result = f.readGrid(gridName); - f.close(); + { + TRACE_FUNCTION_SCOPE("Closing VDB file"); + // openvdb::io::File's d'tor is probably closing the file, but this + // is not explicitly specified in the documentation. + f.close(); + } return result; } @@ -312,11 +316,11 @@ GlfVdbTextureData::Read(int degradeLevel, bool generateMipmap, TRACE_FUNCTION(); TF_DEBUG(GLF_DEBUG_VDB_TEXTURE).Msg( - "[VdbTextureData] Path: %s\n", _filePath.c_str()); + "[VdbTextureData] Path: %s GridName: %s\n", + _filePath.c_str(), + _gridName.c_str()); - openvdb::initialize(); - - openvdb::GridBase::Ptr const grid = _LoadGrid(_filePath); + openvdb::GridBase::Ptr const grid = _LoadGrid(_filePath, _gridName); if (!grid) { return false; } diff --git a/pxr/imaging/glf/vdbTextureData.h b/pxr/imaging/glf/vdbTextureData.h index b667f2b2ac..f2c2d02722 100644 --- a/pxr/imaging/glf/vdbTextureData.h +++ b/pxr/imaging/glf/vdbTextureData.h @@ -45,13 +45,16 @@ class GlfVdbTextureData_DenseGridHolderBase; /// \class GlfVdbTextureData /// -/// Implements GlfBaseTextureData to load an OpenVDB file +/// Implements GlfBaseTextureData to read grid with given name from +/// OpenVDB file at given path. /// class GlfVdbTextureData : public GlfBaseTextureData { public: GLF_API static GlfVdbTextureDataRefPtr - New(std::string const &filePath, size_t targetMemory); + New(std::string const &filePath, + std::string const &gridName, + size_t targetMemory); /// See GlfVdbTexture for details const GfBBox3d &GetBoundingBox() const { return _boundingBox; } @@ -94,10 +97,13 @@ class GlfVdbTextureData : public GlfBaseTextureData { int GetNumMipLevels() const override; private: - GlfVdbTextureData(std::string const &filePath, size_t targetMemory); + GlfVdbTextureData(std::string const &filePath, + std::string const &gridName, + size_t targetMemory); ~GlfVdbTextureData() override; const std::string _filePath; + const std::string _gridName; size_t _targetMemory; diff --git a/pxr/imaging/hdSt/field.cpp b/pxr/imaging/hdSt/field.cpp index 6bc60713d3..e0172712b1 100644 --- a/pxr/imaging/hdSt/field.cpp +++ b/pxr/imaging/hdSt/field.cpp @@ -29,11 +29,17 @@ #include "pxr/imaging/glf/textureRegistry.h" #include "pxr/imaging/glf/textureHandle.h" #include "pxr/imaging/glf/vdbTexture.h" +#include "pxr/imaging/glf/vdbTextureContainer.h" #include "pxr/usd/sdf/types.h" PXR_NAMESPACE_OPEN_SCOPE +TF_DEFINE_PRIVATE_TOKENS( + _tokens, + (fieldName) +); + HdStField::HdStField(SdfPath const& id, TfToken const & fieldType) : HdField(id) , _fieldType(fieldType) @@ -43,6 +49,36 @@ HdStField::HdStField(SdfPath const& id, TfToken const & fieldType) HdStField::~HdStField() = default; +// Obtain texture handle for grid with name fieldName in OpenVDB file at +// given path. +static +GlfTextureHandleRefPtr +_GetVdbTexture(std::string const &path, + TfToken const &fieldName) +{ + // First query the texture registry for the texture container for + // the OpenVDB file. + GlfTextureHandleRefPtr const containerHandle = + GlfTextureRegistry::GetInstance().GetTextureHandle( + TfToken(path)); + if (!containerHandle) { + return TfNullPtr; + } + + GlfVdbTextureContainerPtr const container = + TfDynamic_cast( + containerHandle->GetTexture()); + if (!container) { + TF_CODING_ERROR("When trying to create texture for VDB grid, " + "texture handle does not contain vdb texture " + "container."); + return TfNullPtr; + } + + // Then get the texture handle from the container. + return container->GetTextureHandle(fieldName); +} + void HdStField::Sync(HdSceneDelegate *sceneDelegate, HdRenderParam *renderParam, @@ -53,20 +89,24 @@ HdStField::Sync(HdSceneDelegate *sceneDelegate, // Get asset path from scene delegate. // - // TODO: also read field name. const VtValue filePath = sceneDelegate->Get(GetId(), HdFieldTokens->filePath); const SdfAssetPath fileAssetPath = filePath.Get(); + const VtValue fieldNameValue = sceneDelegate->Get(GetId(), + _tokens->fieldName); + const TfToken fieldName = fieldNameValue.Get(); + // Resolve asset path // // Assuming that correct resolve context is set when HdStField::Sync is // called. const std::string &resolvedPath = fileAssetPath.GetResolvedPath(); - // Using resolved path for key + // Using resolved path and field name for key size_t hash = 0; boost::hash_combine(hash, resolvedPath); + boost::hash_combine(hash, fieldName); HdResourceRegistry::TextureKey texID = hash; // Note that unlike HdTexture::Sync, we do not use @@ -92,7 +132,8 @@ HdStField::Sync(HdSceneDelegate *sceneDelegate, bool isNewTexture = true; if (texInstance.IsFirstInstance()) { - // Get texture from registry to create field resource. + // Get texture for respective grid in VDB file to create field + // resource. // // Note that creating the field resource also does the necessary // OpenGL calls to create the sampler and (if bindless) the OpenGL @@ -106,8 +147,7 @@ HdStField::Sync(HdSceneDelegate *sceneDelegate, // sprim and is not run multi-threadedly. // _fieldResource = boost::make_shared( - GlfTextureRegistry::GetInstance().GetTextureHandle( - TfToken(resolvedPath))); + _GetVdbTexture(resolvedPath, fieldName)); texInstance.SetValue(_fieldResource); } else { HdStFieldResourceSharedPtr const fieldResource =