diff --git a/NEW_RELEASE_NOTES.md b/NEW_RELEASE_NOTES.md index 4a1a9c7fa7e4..01d998de3c56 100644 --- a/NEW_RELEASE_NOTES.md +++ b/NEW_RELEASE_NOTES.md @@ -7,3 +7,5 @@ for next branch cut* header. appropriate header in [RELEASE_NOTES.md](./RELEASE_NOTES.md). ## Release notes for next branch cut + +- Add a `name` API to Filament objects for debugging handle use-after-free assertions diff --git a/filament/CMakeLists.txt b/filament/CMakeLists.txt index 796acedb7d22..18f402ad9e73 100644 --- a/filament/CMakeLists.txt +++ b/filament/CMakeLists.txt @@ -61,6 +61,7 @@ set(SRCS src/Engine.cpp src/Exposure.cpp src/Fence.cpp + src/FilamentBuilder.cpp src/FrameInfo.cpp src/FrameSkipper.cpp src/Froxelizer.cpp diff --git a/filament/backend/include/private/backend/DriverAPI.inc b/filament/backend/include/private/backend/DriverAPI.inc index d27cea8f4c88..283e3e0e5ca0 100644 --- a/filament/backend/include/private/backend/DriverAPI.inc +++ b/filament/backend/include/private/backend/DriverAPI.inc @@ -162,6 +162,10 @@ DECL_DRIVER_API_0(finish) // reset state tracking, if the driver does any state tracking (e.g. GL) DECL_DRIVER_API_0(resetState) +DECL_DRIVER_API_N(setDebugTag, + backend::HandleBase::HandleId, handleId, + utils::CString, tag) + /* * Creating driver objects * ----------------------- diff --git a/filament/backend/include/private/backend/HandleAllocator.h b/filament/backend/include/private/backend/HandleAllocator.h index 9c31b594875d..b61f8e376f0a 100644 --- a/filament/backend/include/private/backend/HandleAllocator.h +++ b/filament/backend/include/private/backend/HandleAllocator.h @@ -20,11 +20,12 @@ #include #include +#include #include +#include #include #include #include -#include #include @@ -173,8 +174,10 @@ class HandleAllocator { uint8_t const age = (tag & HANDLE_AGE_MASK) >> HANDLE_AGE_SHIFT; auto const pNode = static_cast(p); uint8_t const expectedAge = pNode[-1].age; - FILAMENT_CHECK_POSTCONDITION(expectedAge == age) << - "use-after-free of Handle with id=" << handle.getId(); + // getHandleTag() is only called if the check fails. + FILAMENT_CHECK_POSTCONDITION(expectedAge == age) + << "use-after-free of Handle with id=" << handle.getId() + << ", tag=" << getHandleTag(handle.getId()).c_str_safe(); } } @@ -201,6 +204,34 @@ class HandleAllocator { return handle_cast(const_cast&>(handle)); } + void associateTagToHandle(HandleBase::HandleId id, utils::CString&& tag) noexcept { + // TODO: for now, only pool handles check for use-after-free, so we only keep tags for + // those + if (isPoolHandle(id)) { + // Truncate the tag's age to N bits. + constexpr uint8_t N = 2; // support a history of 4 tags + constexpr uint8_t mask = (1 << N) - 1; + + uint8_t const age = (id & HANDLE_AGE_MASK) >> HANDLE_AGE_SHIFT; + uint8_t const newAge = age & mask; + uint32_t const key = (id & ~HANDLE_AGE_MASK) | (newAge << HANDLE_AGE_SHIFT); + + // This line is the costly part. In the future, we could potentially use a custom + // allocator. + mDebugTags[key] = std::move(tag); + } + } + + utils::CString getHandleTag(HandleBase::HandleId id) const noexcept { + if (!isPoolHandle(id)) { + return "(no tag)"; + } + if (auto pos = mDebugTags.find(id); pos != mDebugTags.end()) { + return pos->second; + } + return "(no tag)"; + } + private: template @@ -363,6 +394,7 @@ class HandleAllocator { // Below is only used when running out of space in the HandleArena mutable utils::Mutex mLock; tsl::robin_map mOverflowMap; + tsl::robin_map mDebugTags; HandleBase::HandleId mId = 0; bool mUseAfterFreeCheckDisabled = false; }; diff --git a/filament/backend/src/HandleAllocator.cpp b/filament/backend/src/HandleAllocator.cpp index 07d028d9d49f..6cdcaa4af4f2 100644 --- a/filament/backend/src/HandleAllocator.cpp +++ b/filament/backend/src/HandleAllocator.cpp @@ -80,6 +80,9 @@ HandleAllocator::HandleAllocator(const char* name, size_t size, bool disableUseAfterFreeCheck) noexcept : mHandleArena(name, size, disableUseAfterFreeCheck), mUseAfterFreeCheckDisabled(disableUseAfterFreeCheck) { + // Reserve initial space for debug tags. This prevents excessive calls to malloc when the first + // few tags are set. + mDebugTags.reserve(512); } template diff --git a/filament/backend/src/metal/MetalDriver.mm b/filament/backend/src/metal/MetalDriver.mm index 397a15993369..3022e7381b37 100644 --- a/filament/backend/src/metal/MetalDriver.mm +++ b/filament/backend/src/metal/MetalDriver.mm @@ -2072,6 +2072,10 @@ void MetalDriver::resetState(int) { } +void MetalDriver::setDebugTag(HandleBase::HandleId handleId, utils::CString tag) { + mHandleAllocator.associateTagToHandle(handleId, std::move(tag)); +} + void MetalDriver::runAtNextTick(const std::function& fn) noexcept { std::lock_guard const lock(mTickOpsLock); mTickOps.push_back(fn); diff --git a/filament/backend/src/noop/NoopDriver.cpp b/filament/backend/src/noop/NoopDriver.cpp index a692cfce8342..096f57c3989a 100644 --- a/filament/backend/src/noop/NoopDriver.cpp +++ b/filament/backend/src/noop/NoopDriver.cpp @@ -392,4 +392,7 @@ void NoopDriver::endTimerQuery(Handle tqh) { void NoopDriver::resetState(int) { } +void NoopDriver::setDebugTag(HandleBase::HandleId handleId, utils::CString tag) { +} + } // namespace filament diff --git a/filament/backend/src/opengl/OpenGLDriver.cpp b/filament/backend/src/opengl/OpenGLDriver.cpp index fdf567849e87..ed23067bb878 100644 --- a/filament/backend/src/opengl/OpenGLDriver.cpp +++ b/filament/backend/src/opengl/OpenGLDriver.cpp @@ -2222,6 +2222,10 @@ void OpenGLDriver::makeCurrent(Handle schDraw, Handle // Updating driver objects // ------------------------------------------------------------------------------------------------ +void OpenGLDriver::setDebugTag(HandleBase::HandleId handleId, utils::CString tag) { + mHandleAllocator.associateTagToHandle(handleId, std::move(tag)); +} + void OpenGLDriver::setVertexBufferObject(Handle vbh, uint32_t index, Handle boh) { DEBUG_MARKER() diff --git a/filament/backend/src/vulkan/VulkanDriver.cpp b/filament/backend/src/vulkan/VulkanDriver.cpp index 46020676630e..0b444c0b75e4 100644 --- a/filament/backend/src/vulkan/VulkanDriver.cpp +++ b/filament/backend/src/vulkan/VulkanDriver.cpp @@ -2038,6 +2038,10 @@ void VulkanDriver::debugCommandBegin(CommandStream* cmds, bool synchronous, cons void VulkanDriver::resetState(int) { } +void VulkanDriver::setDebugTag(HandleBase::HandleId handleId, utils::CString tag) { + mResourceAllocator.associateHandle(handleId, std::move(tag)); +} + // explicit instantiation of the Dispatcher template class ConcreteDispatcher; diff --git a/filament/backend/src/vulkan/VulkanResourceAllocator.h b/filament/backend/src/vulkan/VulkanResourceAllocator.h index 04187658b7de..572aeed4f78a 100644 --- a/filament/backend/src/vulkan/VulkanResourceAllocator.h +++ b/filament/backend/src/vulkan/VulkanResourceAllocator.h @@ -105,6 +105,10 @@ class VulkanResourceAllocator { mHandleAllocatorImpl.deallocate(handle, obj); } + inline void associateHandle(HandleBase::HandleId id, utils::CString&& tag) noexcept { + mHandleAllocatorImpl.associateTagToHandle(id, std::move(tag)); + } + private: AllocatorImpl mHandleAllocatorImpl; diff --git a/filament/include/filament/BufferObject.h b/filament/include/filament/BufferObject.h index 74a4b1ff3906..8c76719c85e5 100644 --- a/filament/include/filament/BufferObject.h +++ b/filament/include/filament/BufferObject.h @@ -54,7 +54,7 @@ class UTILS_PUBLIC BufferObject : public FilamentAPI { using BufferDescriptor = backend::BufferDescriptor; using BindingType = backend::BufferObjectBinding; - class Builder : public BuilderBase { + class Builder : public BuilderBase, public BuilderNameMixin { friend struct BuilderDetails; public: Builder() noexcept; @@ -78,6 +78,21 @@ class UTILS_PUBLIC BufferObject : public FilamentAPI { */ Builder& bindingType(BindingType bindingType) noexcept; + /** + * Associate an optional name with this BufferObject for debugging purposes. + * + * name will show in error messages and should be kept as short as possible. The name is + * truncated to a maximum of 128 characters. + * + * The name string is copied during this method so clients may free its memory after + * the function returns. + * + * @param name A string to identify this BufferObject + * @param len Length of name, should be less than or equal to 128 + * @return This Builder, for chaining calls. + */ + // Builder& name(const char* UTILS_NONNULL name, size_t len) noexcept; // inherited + /** * Creates the BufferObject and returns a pointer to it. After creation, the buffer * object is uninitialized. Use BufferObject::setBuffer() to initialize it. diff --git a/filament/include/filament/FilamentAPI.h b/filament/include/filament/FilamentAPI.h index 19d6ba246a9b..7a6f16d6307d 100644 --- a/filament/include/filament/FilamentAPI.h +++ b/filament/include/filament/FilamentAPI.h @@ -19,6 +19,7 @@ #include #include +#include #include @@ -54,6 +55,22 @@ class UTILS_PUBLIC FilamentAPI { template using BuilderBase = utils::PrivateImplementation; +void builderMakeName(utils::CString& outName, const char* name, size_t len) noexcept; + +template +class UTILS_PUBLIC BuilderNameMixin { +public: + Builder& name(const char* name, size_t len) noexcept { + builderMakeName(mName, name, len); + return static_cast(*this); + } + + utils::CString const& getName() const noexcept { return mName; } + +private: + utils::CString mName; +}; + } // namespace filament #endif // TNT_FILAMENT_FILAMENTAPI_H diff --git a/filament/include/filament/IndexBuffer.h b/filament/include/filament/IndexBuffer.h index 35b8a10ef26a..ff29e1f44d24 100644 --- a/filament/include/filament/IndexBuffer.h +++ b/filament/include/filament/IndexBuffer.h @@ -59,7 +59,7 @@ class UTILS_PUBLIC IndexBuffer : public FilamentAPI { UINT = uint8_t(backend::ElementType::UINT), //!< 32-bit indices }; - class Builder : public BuilderBase { + class Builder : public BuilderBase, public BuilderNameMixin { friend struct BuilderDetails; public: Builder() noexcept; @@ -83,6 +83,21 @@ class UTILS_PUBLIC IndexBuffer : public FilamentAPI { */ Builder& bufferType(IndexType indexType) noexcept; + /** + * Associate an optional name with this IndexBuffer for debugging purposes. + * + * name will show in error messages and should be kept as short as possible. The name is + * truncated to a maximum of 128 characters. + * + * The name string is copied during this method so clients may free its memory after + * the function returns. + * + * @param name A string to identify this IndexBuffer + * @param len Length of name, should be less than or equal to 128 + * @return This Builder, for chaining calls. + */ + // Builder& name(const char* UTILS_NONNULL name, size_t len) noexcept; // inherited + /** * Creates the IndexBuffer object and returns a pointer to it. After creation, the index * buffer is uninitialized. Use IndexBuffer::setBuffer() to initialize the IndexBuffer. diff --git a/filament/include/filament/InstanceBuffer.h b/filament/include/filament/InstanceBuffer.h index 2135152d8836..843c7983bb71 100644 --- a/filament/include/filament/InstanceBuffer.h +++ b/filament/include/filament/InstanceBuffer.h @@ -38,7 +38,7 @@ class UTILS_PUBLIC InstanceBuffer : public FilamentAPI { struct BuilderDetails; public: - class Builder : public BuilderBase { + class Builder : public BuilderBase, public BuilderNameMixin { friend struct BuilderDetails; public: @@ -70,6 +70,21 @@ class UTILS_PUBLIC InstanceBuffer : public FilamentAPI { */ Builder& localTransforms(math::mat4f const* UTILS_NULLABLE localTransforms) noexcept; + /** + * Associate an optional name with this InstanceBuffer for debugging purposes. + * + * name will show in error messages and should be kept as short as possible. The name is + * truncated to a maximum of 128 characters. + * + * The name string is copied during this method so clients may free its memory after + * the function returns. + * + * @param name A string to identify this InstanceBuffer + * @param len Length of name, should be less than or equal to 128 + * @return This Builder, for chaining calls. + */ + // Builder& name(const char* UTILS_NONNULL name, size_t len) noexcept; // inherited + /** * Creates the InstanceBuffer object and returns a pointer to it. */ diff --git a/filament/include/filament/MorphTargetBuffer.h b/filament/include/filament/MorphTargetBuffer.h index 655bb8d848d6..cb77bb79c851 100644 --- a/filament/include/filament/MorphTargetBuffer.h +++ b/filament/include/filament/MorphTargetBuffer.h @@ -39,7 +39,7 @@ class UTILS_PUBLIC MorphTargetBuffer : public FilamentAPI { struct BuilderDetails; public: - class Builder : public BuilderBase { + class Builder : public BuilderBase, public BuilderNameMixin { friend struct BuilderDetails; public: Builder() noexcept; @@ -63,6 +63,21 @@ class UTILS_PUBLIC MorphTargetBuffer : public FilamentAPI { */ Builder& count(size_t count) noexcept; + /** + * Associate an optional name with this MorphTargetBuffer for debugging purposes. + * + * name will show in error messages and should be kept as short as possible. The name is + * truncated to a maximum of 128 characters. + * + * The name string is copied during this method so clients may free its memory after + * the function returns. + * + * @param name A string to identify this MorphTargetBuffer + * @param len Length of name, should be less than or equal to 128 + * @return This Builder, for chaining calls. + */ + // Builder& name(const char* UTILS_NONNULL name, size_t len) noexcept; // inherited + /** * Creates the MorphTargetBuffer object and returns a pointer to it. * diff --git a/filament/include/filament/SkinningBuffer.h b/filament/include/filament/SkinningBuffer.h index 36ae30ed4381..27b13191e545 100644 --- a/filament/include/filament/SkinningBuffer.h +++ b/filament/include/filament/SkinningBuffer.h @@ -39,7 +39,7 @@ class UTILS_PUBLIC SkinningBuffer : public FilamentAPI { struct BuilderDetails; public: - class Builder : public BuilderBase { + class Builder : public BuilderBase, public BuilderNameMixin { friend struct BuilderDetails; public: Builder() noexcept; @@ -69,6 +69,21 @@ class UTILS_PUBLIC SkinningBuffer : public FilamentAPI { */ Builder& initialize(bool initialize = true) noexcept; + /** + * Associate an optional name with this SkinningBuffer for debugging purposes. + * + * name will show in error messages and should be kept as short as possible. The name is + * truncated to a maximum of 128 characters. + * + * The name string is copied during this method so clients may free its memory after + * the function returns. + * + * @param name A string to identify this SkinningBuffer + * @param len Length of name, should be less than or equal to 128 + * @return This Builder, for chaining calls. + */ + // Builder& name(const char* UTILS_NONNULL name, size_t len) noexcept; // inherited + /** * Creates the SkinningBuffer object and returns a pointer to it. * diff --git a/filament/include/filament/Stream.h b/filament/include/filament/Stream.h index 6cafbacc8b30..883a8ccab3c8 100644 --- a/filament/include/filament/Stream.h +++ b/filament/include/filament/Stream.h @@ -94,7 +94,7 @@ class UTILS_PUBLIC Stream : public FilamentAPI { * * To create a NATIVE stream, call the
stream
method on the builder. */ - class Builder : public BuilderBase { + class Builder : public BuilderBase, public BuilderNameMixin { friend struct BuilderDetails; public: Builder() noexcept; @@ -136,6 +136,21 @@ class UTILS_PUBLIC Stream : public FilamentAPI { */ Builder& height(uint32_t height) noexcept; + /** + * Associate an optional name with this Stream for debugging purposes. + * + * name will show in error messages and should be kept as short as possible. The name is + * truncated to a maximum of 128 characters. + * + * The name string is copied during this method so clients may free its memory after + * the function returns. + * + * @param name A string to identify this Stream + * @param len Length of name, should be less than or equal to 128 + * @return This Builder, for chaining calls. + */ + // Builder& name(const char* UTILS_NONNULL name, size_t len) noexcept; // inherited + /** * Creates the Stream object and returns a pointer to it. * diff --git a/filament/include/filament/Texture.h b/filament/include/filament/Texture.h index 8a27f831c2bf..b351c4294351 100644 --- a/filament/include/filament/Texture.h +++ b/filament/include/filament/Texture.h @@ -112,7 +112,7 @@ class UTILS_PUBLIC Texture : public FilamentAPI { //! Use Builder to construct a Texture object instance - class Builder : public BuilderBase { + class Builder : public BuilderBase, public BuilderNameMixin { friend struct BuilderDetails; public: Builder() noexcept; @@ -202,6 +202,21 @@ class UTILS_PUBLIC Texture : public FilamentAPI { */ Builder& swizzle(Swizzle r, Swizzle g, Swizzle b, Swizzle a) noexcept; + /** + * Associate an optional name with this Texture for debugging purposes. + * + * name will show in error messages and should be kept as short as possible. The name is + * truncated to a maximum of 128 characters. + * + * The name string is copied during this method so clients may free its memory after + * the function returns. + * + * @param name A string to identify this Texture + * @param len Length of name, should be less than or equal to 128 + * @return This Builder, for chaining calls. + */ + // Builder& name(const char* UTILS_NONNULL name, size_t len) noexcept; // inherited + /** * Creates the Texture object and returns a pointer to it. * diff --git a/filament/include/filament/VertexBuffer.h b/filament/include/filament/VertexBuffer.h index fccbd0046f80..64106434abc9 100644 --- a/filament/include/filament/VertexBuffer.h +++ b/filament/include/filament/VertexBuffer.h @@ -61,7 +61,7 @@ class UTILS_PUBLIC VertexBuffer : public FilamentAPI { using AttributeType = backend::ElementType; using BufferDescriptor = backend::BufferDescriptor; - class Builder : public BuilderBase { + class Builder : public BuilderBase, public BuilderNameMixin { friend struct BuilderDetails; public: Builder() noexcept; @@ -158,6 +158,21 @@ class UTILS_PUBLIC VertexBuffer : public FilamentAPI { */ Builder& advancedSkinning(bool enabled) noexcept; + /** + * Associate an optional name with this VertexBuffer for debugging purposes. + * + * name will show in error messages and should be kept as short as possible. The name is + * truncated to a maximum of 128 characters. + * + * The name string is copied during this method so clients may free its memory after + * the function returns. + * + * @param name A string to identify this VertexBuffer + * @param len Length of name, should be less than or equal to 128 + * @return This Builder, for chaining calls. + */ + // Builder& name(const char* UTILS_NONNULL name, size_t len) noexcept; // inherited + /** * Creates the VertexBuffer object and returns a pointer to it. * diff --git a/filament/src/FilamentBuilder.cpp b/filament/src/FilamentBuilder.cpp new file mode 100644 index 000000000000..08f1cb323185 --- /dev/null +++ b/filament/src/FilamentBuilder.cpp @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include + +namespace filament { + +void builderMakeName(utils::CString& outName, const char* name, size_t len) noexcept { + if (!name) { + return; + } + size_t const length = std::min(len, size_t { 128u }); + outName = utils::CString(name, length); +} + +} // namespace filament diff --git a/filament/src/components/RenderableManager.cpp b/filament/src/components/RenderableManager.cpp index 6338d53b7259..7b79477bcdc9 100644 --- a/filament/src/components/RenderableManager.cpp +++ b/filament/src/components/RenderableManager.cpp @@ -588,6 +588,9 @@ void FRenderableManager::create( // full size of the UBO. instances.handle = driver.createBufferObject(sizeof(PerRenderableUib), BufferObjectBinding::UNIFORM, backend::BufferUsage::DYNAMIC); + if (auto name = instances.buffer->getName(); !name.empty()) { + driver.setDebugTag(instances.handle.getId(), std::move(name)); + } } const uint32_t boneCount = builder->mSkinningBoneCount; diff --git a/filament/src/details/BufferObject.cpp b/filament/src/details/BufferObject.cpp index 04a68223ba27..a462e42a4237 100644 --- a/filament/src/details/BufferObject.cpp +++ b/filament/src/details/BufferObject.cpp @@ -20,6 +20,8 @@ #include "FilamentAPI-impl.h" +#include + namespace filament { struct BufferObject::BuilderDetails { @@ -56,6 +58,9 @@ FBufferObject::FBufferObject(FEngine& engine, const BufferObject::Builder& build FEngine::DriverApi& driver = engine.getDriverApi(); mHandle = driver.createBufferObject(builder->mByteCount, builder->mBindingType, backend::BufferUsage::STATIC); + if (auto name = builder.getName(); !name.empty()) { + driver.setDebugTag(mHandle.getId(), std::move(name)); + } } void FBufferObject::terminate(FEngine& engine) { diff --git a/filament/src/details/IndexBuffer.cpp b/filament/src/details/IndexBuffer.cpp index 66fc5d2f58c3..ae881de358d2 100644 --- a/filament/src/details/IndexBuffer.cpp +++ b/filament/src/details/IndexBuffer.cpp @@ -20,6 +20,8 @@ #include "FilamentAPI-impl.h" +#include + namespace filament { struct IndexBuffer::BuilderDetails { @@ -58,6 +60,9 @@ FIndexBuffer::FIndexBuffer(FEngine& engine, const IndexBuffer::Builder& builder) (backend::ElementType)builder->mIndexType, uint32_t(builder->mIndexCount), backend::BufferUsage::STATIC); + if (auto name = builder.getName(); !name.empty()) { + driver.setDebugTag(mHandle.getId(), std::move(name)); + } } void FIndexBuffer::terminate(FEngine& engine) { diff --git a/filament/src/details/InstanceBuffer.cpp b/filament/src/details/InstanceBuffer.cpp index af22554d0f2e..89fdd0e5d9a3 100644 --- a/filament/src/details/InstanceBuffer.cpp +++ b/filament/src/details/InstanceBuffer.cpp @@ -61,7 +61,8 @@ InstanceBuffer* InstanceBuffer::Builder::build(Engine& engine) { // ------------------------------------------------------------------------------------------------ -FInstanceBuffer::FInstanceBuffer(FEngine& engine, const Builder& builder) { +FInstanceBuffer::FInstanceBuffer(FEngine& engine, const Builder& builder) + : mName(builder.getName()) { mInstanceCount = builder->mInstanceCount; mLocalTransforms.reserve(mInstanceCount); diff --git a/filament/src/details/InstanceBuffer.h b/filament/src/details/InstanceBuffer.h index 2d25f7833e83..56bac500c2bf 100644 --- a/filament/src/details/InstanceBuffer.h +++ b/filament/src/details/InstanceBuffer.h @@ -25,6 +25,7 @@ #include +#include #include namespace filament { @@ -46,10 +47,13 @@ class FInstanceBuffer : public InstanceBuffer { void prepare(FEngine& engine, math::mat4f rootTransform, const PerRenderableData& ubo, backend::Handle handle); + utils::CString const& getName() const noexcept { return mName; } + private: friend class RenderableManager; utils::FixedCapacityVector mLocalTransforms; + utils::CString mName; size_t mInstanceCount; }; diff --git a/filament/src/details/Material.cpp b/filament/src/details/Material.cpp index 17e5d4633467..b27c6608731f 100644 --- a/filament/src/details/Material.cpp +++ b/filament/src/details/Material.cpp @@ -618,6 +618,7 @@ Program FMaterial::getProgramWithVariants( void FMaterial::createAndCacheProgram(Program&& p, Variant variant) const noexcept { auto program = mEngine.getDriverApi().createProgram(std::move(p)); + mEngine.getDriverApi().setDebugTag(program.getId(), mName); assert_invariant(program); mCachedPrograms[variant.key] = program; } diff --git a/filament/src/details/MaterialInstance.cpp b/filament/src/details/MaterialInstance.cpp index 4595c7e6c3b8..152ecd480a44 100644 --- a/filament/src/details/MaterialInstance.cpp +++ b/filament/src/details/MaterialInstance.cpp @@ -51,6 +51,7 @@ FMaterialInstance::FMaterialInstance(FEngine& engine, FMaterial const* material) mUniforms = UniformBuffer(material->getUniformInterfaceBlock().getSize()); mUbHandle = driver.createBufferObject(mUniforms.getSize(), BufferObjectBinding::UNIFORM, backend::BufferUsage::STATIC); + driver.setDebugTag(mUbHandle.getId(), material->getName()); } if (!material->getSamplerInterfaceBlock().isEmpty()) { @@ -116,6 +117,7 @@ FMaterialInstance::FMaterialInstance(FEngine& engine, mUniforms.setUniforms(other->getUniformBuffer()); mUbHandle = driver.createBufferObject(mUniforms.getSize(), BufferObjectBinding::UNIFORM, backend::BufferUsage::DYNAMIC); + driver.setDebugTag(mUbHandle.getId(), material->getName()); } if (!material->getSamplerInterfaceBlock().isEmpty()) { diff --git a/filament/src/details/MorphTargetBuffer.cpp b/filament/src/details/MorphTargetBuffer.cpp index d4124fb2a6b2..d3323b92c3b8 100644 --- a/filament/src/details/MorphTargetBuffer.cpp +++ b/filament/src/details/MorphTargetBuffer.cpp @@ -25,6 +25,8 @@ #include #include +#include + namespace filament { using namespace backend; @@ -124,6 +126,11 @@ FMorphTargetBuffer::FMorphTargetBuffer(FEngine& engine, const Builder& builder) mCount, TextureUsage::DEFAULT); + if (auto name = builder.getName(); !name.empty()) { + driver.setDebugTag(mPbHandle.getId(), name); + driver.setDebugTag(mTbHandle.getId(), std::move(name)); + } + // create and update sampler group mSbHandle = driver.createSamplerGroup(PerRenderPrimitiveMorphingSib::SAMPLER_COUNT, utils::FixedSizeString<32>("Morph target samplers")); diff --git a/filament/src/details/SkinningBuffer.cpp b/filament/src/details/SkinningBuffer.cpp index b70926386703..c4c79c3a9928 100644 --- a/filament/src/details/SkinningBuffer.cpp +++ b/filament/src/details/SkinningBuffer.cpp @@ -27,6 +27,8 @@ #include #include +#include + #include namespace filament { @@ -80,6 +82,11 @@ FSkinningBuffer::FSkinningBuffer(FEngine& engine, const Builder& builder) BufferObjectBinding::UNIFORM, BufferUsage::DYNAMIC); + if (auto name = builder.getName(); !name.empty()) { + // TODO: We should also tag the texture created inside createIndicesAndWeightsHandle. + driver.setDebugTag(mHandle.getId(), std::move(name)); + } + if (builder->mInitialize) { // initialize the bones to identity (before rounding up) auto* out = driver.allocatePod(mBoneCount); diff --git a/filament/src/details/Stream.cpp b/filament/src/details/Stream.cpp index 317113ace039..c60bcf8bef30 100644 --- a/filament/src/details/Stream.cpp +++ b/filament/src/details/Stream.cpp @@ -23,10 +23,10 @@ #include +#include #include #include - namespace filament { using namespace backend; @@ -80,6 +80,10 @@ FStream::FStream(FEngine& engine, const Builder& builder) noexcept } else { mStreamHandle = engine.getDriverApi().createStreamAcquired(); } + + if (auto name = builder.getName(); !name.empty()) { + engine.getDriverApi().setDebugTag(mStreamHandle.getId(), std::move(name)); + } } void FStream::terminate(FEngine& engine) noexcept { diff --git a/filament/src/details/Texture.cpp b/filament/src/details/Texture.cpp index 3734df4b6d9a..a59a24da97d9 100644 --- a/filament/src/details/Texture.cpp +++ b/filament/src/details/Texture.cpp @@ -243,6 +243,9 @@ FTexture::FTexture(FEngine& engine, const Builder& builder) { mHandle = driver.importTexture(builder->mImportedId, mTarget, mLevelCount, mFormat, mSampleCount, mWidth, mHeight, mDepth, mUsage); } + if (auto name = builder.getName(); !name.empty()) { + driver.setDebugTag(mHandle.getId(), std::move(name)); + } } // frees driver resources, object becomes invalid diff --git a/filament/src/details/VertexBuffer.cpp b/filament/src/details/VertexBuffer.cpp index 6269bc5ed7bf..8aabcf4fc799 100644 --- a/filament/src/details/VertexBuffer.cpp +++ b/filament/src/details/VertexBuffer.cpp @@ -29,6 +29,7 @@ #include #include +#include #include #include #include @@ -259,7 +260,9 @@ FVertexBuffer::FVertexBuffer(FEngine& engine, const VertexBuffer::Builder& build mBufferCount, mDeclaredAttributes.count(), mAttributes); mHandle = driver.createVertexBuffer(mVertexCount, mVertexBufferInfoHandle); - + if (auto name = builder.getName(); !name.empty()) { + driver.setDebugTag(mHandle.getId(), name); + } // calculate buffer sizes size_t bufferSizes[MAX_VERTEX_BUFFER_COUNT] = {}; @@ -287,6 +290,9 @@ FVertexBuffer::FVertexBuffer(FEngine& engine, const VertexBuffer::Builder& build if (!mBufferObjects[i]) { BufferObjectHandle bo = driver.createBufferObject(bufferSizes[i], backend::BufferObjectBinding::VERTEX, backend::BufferUsage::STATIC); + if (auto name = builder.getName(); !name.empty()) { + driver.setDebugTag(bo.getId(), name); + } driver.setVertexBufferObject(mHandle, i, bo); mBufferObjects[i] = bo; } @@ -303,6 +309,9 @@ FVertexBuffer::FVertexBuffer(FEngine& engine, const VertexBuffer::Builder& build if (!mBufferObjects[i]) { BufferObjectHandle const bo = driver.createBufferObject(bufferSizes[i], backend::BufferObjectBinding::VERTEX, backend::BufferUsage::STATIC); + if (auto name = builder.getName(); !name.empty()) { + driver.setDebugTag(bo.getId(), name); + } driver.setVertexBufferObject(mHandle, i, bo); mBufferObjects[i] = bo; }