Skip to content

Commit 8e57166

Browse files
authored
Fix cyclic reference in ExtendedTypeLayout. (shader-slang#1868)
1 parent 7e93e81 commit 8e57166

File tree

4 files changed

+68
-3
lines changed

4 files changed

+68
-3
lines changed

source/core/slang-smart-pointer.h

+65-1
Original file line numberDiff line numberDiff line change
@@ -272,6 +272,70 @@ namespace Slang
272272
private:
273273
T* m_ptr;
274274
};
275-
}
276275

276+
// A pointer that can be transformed to hold either a weak reference or a strong reference.
277+
template<typename T>
278+
class TransformablePtr
279+
{
280+
private:
281+
T* m_weakPtr = nullptr;
282+
RefPtr<T> m_strongPtr;
283+
284+
public:
285+
TransformablePtr() = default;
286+
TransformablePtr(T* ptr) { *this = ptr; }
287+
TransformablePtr(RefPtr<T> ptr) { *this = ptr; }
288+
TransformablePtr(const TransformablePtr<T>& ptr) = default;
289+
290+
void promoteToStrongReference() { m_strongPtr = m_weakPtr; }
291+
void demoteToWeakReference() { m_strongPtr = nullptr; }
292+
bool isStrongReference() const { return m_strongPtr != nullptr; }
293+
294+
T& operator*() const { return *m_weakPtr; }
295+
296+
T* operator->() const { return m_weakPtr; }
297+
298+
T* Ptr() const { return m_weakPtr; }
299+
T* get() const { return m_weakPtr; }
300+
301+
operator T*() const { return m_weakPtr; }
302+
operator RefPtr<T>() const { return m_weakPtr; }
303+
304+
305+
TransformablePtr<T>& operator=(T* ptr)
306+
{
307+
m_weakPtr = ptr;
308+
m_strongPtr = ptr;
309+
return *this;
310+
}
311+
template<typename U>
312+
TransformablePtr<T>& operator=(const RefPtr<U>& ptr)
313+
{
314+
m_weakPtr = ptr.Ptr();
315+
m_strongPtr = ptr;
316+
return *this;
317+
}
318+
319+
HashCode getHashCode() const
320+
{
321+
// Note: We need a `RefPtr<T>` to hash the same as a `T*`,
322+
// so that a `T*` can be used as a key in a dictionary with
323+
// `RefPtr<T>` keys, and vice versa.
324+
//
325+
return Slang::getHashCode(m_weakPtr);
326+
}
327+
328+
bool operator==(const T* ptr) const { return m_weakPtr == ptr; }
329+
330+
bool operator!=(const T* ptr) const { return m_weakPtr != ptr; }
331+
332+
bool operator==(RefPtr<T> const& ptr) const { return m_weakPtr == ptr.Ptr(); }
333+
334+
bool operator!=(RefPtr<T> const& ptr) const { return m_weakPtr != ptr.Ptr(); }
335+
336+
bool operator==(TransformablePtr<T> const& ptr) const { return m_weakPtr == ptr.m_weakPtr; }
337+
338+
bool operator!=(TransformablePtr<T> const& ptr) const { return m_weakPtr != ptr.m_weakPtr; }
339+
};
340+
}
277341
#endif

source/slang/slang-reflection-api.cpp

+1
Original file line numberDiff line numberDiff line change
@@ -1405,6 +1405,7 @@ namespace Slang
14051405

14061406
RefPtr<VarLayout> varLayout = new VarLayout();
14071407
varLayout->typeLayout = typeLayout;
1408+
varLayout->typeLayout.demoteToWeakReference();
14081409

14091410
for(auto typeResInfo : typeLayout->resourceInfos)
14101411
{

source/slang/slang-type-layout.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -2819,7 +2819,7 @@ static RefPtr<TypeLayout> maybeAdjustLayoutForArrayElementType(
28192819

28202820
// If nothing needed to be changed on the inner element type,
28212821
// then we are done.
2822-
if(adjustedInnerElementTypeLayout == originalInnerElementTypeLayout)
2822+
if (originalInnerElementTypeLayout == adjustedInnerElementTypeLayout)
28232823
return originalTypeLayout;
28242824

28252825
// TODO: actually adjust the element type, and create all the required bits and

source/slang/slang-type-layout.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -467,7 +467,7 @@ class VarLayout : public Layout
467467
Name* getName() { return getVariable()->getName(); }
468468

469469
// The result of laying out the variable's type
470-
RefPtr<TypeLayout> typeLayout;
470+
TransformablePtr<TypeLayout> typeLayout;
471471
TypeLayout* getTypeLayout() { return typeLayout.Ptr(); }
472472

473473
// Additional flags

0 commit comments

Comments
 (0)