Skip to content

Commit bce91c5

Browse files
committed
Merge branch 'rc/1.54.1' into release
2 parents c1a3450 + eb12e06 commit bce91c5

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

54 files changed

+654
-253
lines changed

NEW_RELEASE_NOTES.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,5 @@ for next branch cut* header.
77
appropriate header in [RELEASE_NOTES.md](./RELEASE_NOTES.md).
88

99
## Release notes for next branch cut
10+
11+
- Add a `name` API to Filament objects for debugging handle use-after-free assertions

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ repositories {
3131
}
3232
3333
dependencies {
34-
implementation 'com.google.android.filament:filament-android:1.54.0'
34+
implementation 'com.google.android.filament:filament-android:1.54.1'
3535
}
3636
```
3737

@@ -51,7 +51,7 @@ Here are all the libraries available in the group `com.google.android.filament`:
5151
iOS projects can use CocoaPods to install the latest release:
5252

5353
```shell
54-
pod 'Filament', '~> 1.54.0'
54+
pod 'Filament', '~> 1.54.1'
5555
```
5656

5757
### Snapshots

RELEASE_NOTES.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@ A new header is inserted each time a *tag* is created.
77
Instead, if you are authoring a PR for the main branch, add your release note to
88
[NEW_RELEASE_NOTES.md](./NEW_RELEASE_NOTES.md).
99

10+
## v1.54.1
11+
12+
1013
## v1.54.0
1114

1215
- materials: add a new `stereoscopicType` material parameter. [⚠️ **New Material Version**]

android/gradle.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
GROUP=com.google.android.filament
2-
VERSION_NAME=1.54.0
2+
VERSION_NAME=1.54.1
33

44
POM_DESCRIPTION=Real-time physically based rendering engine for Android.
55

filament/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ set(SRCS
6161
src/Engine.cpp
6262
src/Exposure.cpp
6363
src/Fence.cpp
64+
src/FilamentBuilder.cpp
6465
src/FrameInfo.cpp
6566
src/FrameSkipper.cpp
6667
src/Froxelizer.cpp

filament/backend/include/private/backend/DriverAPI.inc

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,10 @@ DECL_DRIVER_API_0(finish)
162162
// reset state tracking, if the driver does any state tracking (e.g. GL)
163163
DECL_DRIVER_API_0(resetState)
164164

165+
DECL_DRIVER_API_N(setDebugTag,
166+
backend::HandleBase::HandleId, handleId,
167+
utils::CString, tag)
168+
165169
/*
166170
* Creating driver objects
167171
* -----------------------

filament/backend/include/private/backend/HandleAllocator.h

Lines changed: 35 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,12 @@
2020
#include <backend/Handle.h>
2121

2222
#include <utils/Allocator.h>
23+
#include <utils/CString.h>
2324
#include <utils/Log.h>
25+
#include <utils/Panic.h>
2426
#include <utils/compiler.h>
2527
#include <utils/debug.h>
2628
#include <utils/ostream.h>
27-
#include <utils/Panic.h>
2829

2930
#include <tsl/robin_map.h>
3031

@@ -173,8 +174,10 @@ class HandleAllocator {
173174
uint8_t const age = (tag & HANDLE_AGE_MASK) >> HANDLE_AGE_SHIFT;
174175
auto const pNode = static_cast<typename Allocator::Node*>(p);
175176
uint8_t const expectedAge = pNode[-1].age;
176-
FILAMENT_CHECK_POSTCONDITION(expectedAge == age) <<
177-
"use-after-free of Handle with id=" << handle.getId();
177+
// getHandleTag() is only called if the check fails.
178+
FILAMENT_CHECK_POSTCONDITION(expectedAge == age)
179+
<< "use-after-free of Handle with id=" << handle.getId()
180+
<< ", tag=" << getHandleTag(handle.getId()).c_str_safe();
178181
}
179182
}
180183

@@ -201,6 +204,34 @@ class HandleAllocator {
201204
return handle_cast<Dp>(const_cast<Handle<B>&>(handle));
202205
}
203206

207+
void associateTagToHandle(HandleBase::HandleId id, utils::CString&& tag) noexcept {
208+
// TODO: for now, only pool handles check for use-after-free, so we only keep tags for
209+
// those
210+
if (isPoolHandle(id)) {
211+
// Truncate the tag's age to N bits.
212+
constexpr uint8_t N = 2; // support a history of 4 tags
213+
constexpr uint8_t mask = (1 << N) - 1;
214+
215+
uint8_t const age = (id & HANDLE_AGE_MASK) >> HANDLE_AGE_SHIFT;
216+
uint8_t const newAge = age & mask;
217+
uint32_t const key = (id & ~HANDLE_AGE_MASK) | (newAge << HANDLE_AGE_SHIFT);
218+
219+
// This line is the costly part. In the future, we could potentially use a custom
220+
// allocator.
221+
mDebugTags[key] = std::move(tag);
222+
}
223+
}
224+
225+
utils::CString getHandleTag(HandleBase::HandleId id) const noexcept {
226+
if (!isPoolHandle(id)) {
227+
return "(no tag)";
228+
}
229+
if (auto pos = mDebugTags.find(id); pos != mDebugTags.end()) {
230+
return pos->second;
231+
}
232+
return "(no tag)";
233+
}
234+
204235
private:
205236

206237
template<typename D>
@@ -363,6 +394,7 @@ class HandleAllocator {
363394
// Below is only used when running out of space in the HandleArena
364395
mutable utils::Mutex mLock;
365396
tsl::robin_map<HandleBase::HandleId, void*> mOverflowMap;
397+
tsl::robin_map<HandleBase::HandleId, utils::CString> mDebugTags;
366398
HandleBase::HandleId mId = 0;
367399
bool mUseAfterFreeCheckDisabled = false;
368400
};

filament/backend/src/HandleAllocator.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,9 @@ HandleAllocator<P0, P1, P2>::HandleAllocator(const char* name, size_t size,
8080
bool disableUseAfterFreeCheck) noexcept
8181
: mHandleArena(name, size, disableUseAfterFreeCheck),
8282
mUseAfterFreeCheckDisabled(disableUseAfterFreeCheck) {
83+
// Reserve initial space for debug tags. This prevents excessive calls to malloc when the first
84+
// few tags are set.
85+
mDebugTags.reserve(512);
8386
}
8487

8588
template <size_t P0, size_t P1, size_t P2>

filament/backend/src/metal/MetalDriver.mm

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2061,6 +2061,10 @@
20612061
void MetalDriver::resetState(int) {
20622062
}
20632063

2064+
void MetalDriver::setDebugTag(HandleBase::HandleId handleId, utils::CString tag) {
2065+
mHandleAllocator.associateTagToHandle(handleId, std::move(tag));
2066+
}
2067+
20642068
void MetalDriver::runAtNextTick(const std::function<void()>& fn) noexcept {
20652069
std::lock_guard<std::mutex> const lock(mTickOpsLock);
20662070
mTickOps.push_back(fn);

filament/backend/src/noop/NoopDriver.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -388,4 +388,7 @@ void NoopDriver::endTimerQuery(Handle<HwTimerQuery> tqh) {
388388
void NoopDriver::resetState(int) {
389389
}
390390

391+
void NoopDriver::setDebugTag(HandleBase::HandleId handleId, utils::CString tag) {
392+
}
393+
391394
} // namespace filament

filament/backend/src/opengl/OpenGLDriver.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2210,6 +2210,10 @@ void OpenGLDriver::makeCurrent(Handle<HwSwapChain> schDraw, Handle<HwSwapChain>
22102210
// Updating driver objects
22112211
// ------------------------------------------------------------------------------------------------
22122212

2213+
void OpenGLDriver::setDebugTag(HandleBase::HandleId handleId, utils::CString tag) {
2214+
mHandleAllocator.associateTagToHandle(handleId, std::move(tag));
2215+
}
2216+
22132217
void OpenGLDriver::setVertexBufferObject(Handle<HwVertexBuffer> vbh,
22142218
uint32_t index, Handle<HwBufferObject> boh) {
22152219
DEBUG_MARKER()

filament/backend/src/vulkan/VulkanDriver.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2032,6 +2032,10 @@ void VulkanDriver::debugCommandBegin(CommandStream* cmds, bool synchronous, cons
20322032
void VulkanDriver::resetState(int) {
20332033
}
20342034

2035+
void VulkanDriver::setDebugTag(HandleBase::HandleId handleId, utils::CString tag) {
2036+
mResourceAllocator.associateHandle(handleId, std::move(tag));
2037+
}
2038+
20352039
// explicit instantiation of the Dispatcher
20362040
template class ConcreteDispatcher<VulkanDriver>;
20372041

filament/backend/src/vulkan/VulkanResourceAllocator.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,10 @@ class VulkanResourceAllocator {
105105
mHandleAllocatorImpl.deallocate(handle, obj);
106106
}
107107

108+
inline void associateHandle(HandleBase::HandleId id, utils::CString&& tag) noexcept {
109+
mHandleAllocatorImpl.associateTagToHandle(id, std::move(tag));
110+
}
111+
108112
private:
109113
AllocatorImpl mHandleAllocatorImpl;
110114

filament/include/filament/BufferObject.h

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ class UTILS_PUBLIC BufferObject : public FilamentAPI {
5454
using BufferDescriptor = backend::BufferDescriptor;
5555
using BindingType = backend::BufferObjectBinding;
5656

57-
class Builder : public BuilderBase<BuilderDetails> {
57+
class Builder : public BuilderBase<BuilderDetails>, public BuilderNameMixin<Builder> {
5858
friend struct BuilderDetails;
5959
public:
6060
Builder() noexcept;
@@ -78,6 +78,21 @@ class UTILS_PUBLIC BufferObject : public FilamentAPI {
7878
*/
7979
Builder& bindingType(BindingType bindingType) noexcept;
8080

81+
/**
82+
* Associate an optional name with this BufferObject for debugging purposes.
83+
*
84+
* name will show in error messages and should be kept as short as possible. The name is
85+
* truncated to a maximum of 128 characters.
86+
*
87+
* The name string is copied during this method so clients may free its memory after
88+
* the function returns.
89+
*
90+
* @param name A string to identify this BufferObject
91+
* @param len Length of name, should be less than or equal to 128
92+
* @return This Builder, for chaining calls.
93+
*/
94+
// Builder& name(const char* UTILS_NONNULL name, size_t len) noexcept; // inherited
95+
8196
/**
8297
* Creates the BufferObject and returns a pointer to it. After creation, the buffer
8398
* object is uninitialized. Use BufferObject::setBuffer() to initialize it.

filament/include/filament/FilamentAPI.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919

2020
#include <utils/compiler.h>
2121
#include <utils/PrivateImplementation.h>
22+
#include <utils/CString.h>
2223

2324
#include <stddef.h>
2425

@@ -54,6 +55,22 @@ class UTILS_PUBLIC FilamentAPI {
5455
template<typename T>
5556
using BuilderBase = utils::PrivateImplementation<T>;
5657

58+
void builderMakeName(utils::CString& outName, const char* name, size_t len) noexcept;
59+
60+
template <typename Builder>
61+
class UTILS_PUBLIC BuilderNameMixin {
62+
public:
63+
Builder& name(const char* name, size_t len) noexcept {
64+
builderMakeName(mName, name, len);
65+
return static_cast<Builder&>(*this);
66+
}
67+
68+
utils::CString const& getName() const noexcept { return mName; }
69+
70+
private:
71+
utils::CString mName;
72+
};
73+
5774
} // namespace filament
5875

5976
#endif // TNT_FILAMENT_FILAMENTAPI_H

filament/include/filament/IndexBuffer.h

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ class UTILS_PUBLIC IndexBuffer : public FilamentAPI {
5959
UINT = uint8_t(backend::ElementType::UINT), //!< 32-bit indices
6060
};
6161

62-
class Builder : public BuilderBase<BuilderDetails> {
62+
class Builder : public BuilderBase<BuilderDetails>, public BuilderNameMixin<Builder> {
6363
friend struct BuilderDetails;
6464
public:
6565
Builder() noexcept;
@@ -83,6 +83,21 @@ class UTILS_PUBLIC IndexBuffer : public FilamentAPI {
8383
*/
8484
Builder& bufferType(IndexType indexType) noexcept;
8585

86+
/**
87+
* Associate an optional name with this IndexBuffer for debugging purposes.
88+
*
89+
* name will show in error messages and should be kept as short as possible. The name is
90+
* truncated to a maximum of 128 characters.
91+
*
92+
* The name string is copied during this method so clients may free its memory after
93+
* the function returns.
94+
*
95+
* @param name A string to identify this IndexBuffer
96+
* @param len Length of name, should be less than or equal to 128
97+
* @return This Builder, for chaining calls.
98+
*/
99+
// Builder& name(const char* UTILS_NONNULL name, size_t len) noexcept; // inherited
100+
86101
/**
87102
* Creates the IndexBuffer object and returns a pointer to it. After creation, the index
88103
* buffer is uninitialized. Use IndexBuffer::setBuffer() to initialize the IndexBuffer.

filament/include/filament/InstanceBuffer.h

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ class UTILS_PUBLIC InstanceBuffer : public FilamentAPI {
3838
struct BuilderDetails;
3939

4040
public:
41-
class Builder : public BuilderBase<BuilderDetails> {
41+
class Builder : public BuilderBase<BuilderDetails>, public BuilderNameMixin<Builder> {
4242
friend struct BuilderDetails;
4343

4444
public:
@@ -70,6 +70,21 @@ class UTILS_PUBLIC InstanceBuffer : public FilamentAPI {
7070
*/
7171
Builder& localTransforms(math::mat4f const* UTILS_NULLABLE localTransforms) noexcept;
7272

73+
/**
74+
* Associate an optional name with this InstanceBuffer for debugging purposes.
75+
*
76+
* name will show in error messages and should be kept as short as possible. The name is
77+
* truncated to a maximum of 128 characters.
78+
*
79+
* The name string is copied during this method so clients may free its memory after
80+
* the function returns.
81+
*
82+
* @param name A string to identify this InstanceBuffer
83+
* @param len Length of name, should be less than or equal to 128
84+
* @return This Builder, for chaining calls.
85+
*/
86+
// Builder& name(const char* UTILS_NONNULL name, size_t len) noexcept; // inherited
87+
7388
/**
7489
* Creates the InstanceBuffer object and returns a pointer to it.
7590
*/

filament/include/filament/MorphTargetBuffer.h

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ class UTILS_PUBLIC MorphTargetBuffer : public FilamentAPI {
3939
struct BuilderDetails;
4040

4141
public:
42-
class Builder : public BuilderBase<BuilderDetails> {
42+
class Builder : public BuilderBase<BuilderDetails>, public BuilderNameMixin<Builder> {
4343
friend struct BuilderDetails;
4444
public:
4545
Builder() noexcept;
@@ -63,6 +63,21 @@ class UTILS_PUBLIC MorphTargetBuffer : public FilamentAPI {
6363
*/
6464
Builder& count(size_t count) noexcept;
6565

66+
/**
67+
* Associate an optional name with this MorphTargetBuffer for debugging purposes.
68+
*
69+
* name will show in error messages and should be kept as short as possible. The name is
70+
* truncated to a maximum of 128 characters.
71+
*
72+
* The name string is copied during this method so clients may free its memory after
73+
* the function returns.
74+
*
75+
* @param name A string to identify this MorphTargetBuffer
76+
* @param len Length of name, should be less than or equal to 128
77+
* @return This Builder, for chaining calls.
78+
*/
79+
// Builder& name(const char* UTILS_NONNULL name, size_t len) noexcept; // inherited
80+
6681
/**
6782
* Creates the MorphTargetBuffer object and returns a pointer to it.
6883
*

filament/include/filament/SkinningBuffer.h

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ class UTILS_PUBLIC SkinningBuffer : public FilamentAPI {
3939
struct BuilderDetails;
4040

4141
public:
42-
class Builder : public BuilderBase<BuilderDetails> {
42+
class Builder : public BuilderBase<BuilderDetails>, public BuilderNameMixin<Builder> {
4343
friend struct BuilderDetails;
4444
public:
4545
Builder() noexcept;
@@ -69,6 +69,21 @@ class UTILS_PUBLIC SkinningBuffer : public FilamentAPI {
6969
*/
7070
Builder& initialize(bool initialize = true) noexcept;
7171

72+
/**
73+
* Associate an optional name with this SkinningBuffer for debugging purposes.
74+
*
75+
* name will show in error messages and should be kept as short as possible. The name is
76+
* truncated to a maximum of 128 characters.
77+
*
78+
* The name string is copied during this method so clients may free its memory after
79+
* the function returns.
80+
*
81+
* @param name A string to identify this SkinningBuffer
82+
* @param len Length of name, should be less than or equal to 128
83+
* @return This Builder, for chaining calls.
84+
*/
85+
// Builder& name(const char* UTILS_NONNULL name, size_t len) noexcept; // inherited
86+
7287
/**
7388
* Creates the SkinningBuffer object and returns a pointer to it.
7489
*

0 commit comments

Comments
 (0)