Skip to content

Commit 15054d7

Browse files
committed
RHI: Fix RenderTarget sub-class resources not cleanup
1 parent f06ffb1 commit 15054d7

File tree

6 files changed

+38
-9
lines changed

6 files changed

+38
-9
lines changed

axmol/base/Object.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,8 @@ Object::~Object()
7878
#endif
7979
}
8080

81+
void Object::dispose() {}
82+
8183
void Object::retain()
8284
{
8385
AXASSERT(_referenceCount > 0, "reference count should be greater than 0");
@@ -91,6 +93,7 @@ void Object::release()
9193

9294
if (_referenceCount == 0)
9395
{
96+
dispose();
9497
#if defined(_AX_DEBUG) && (_AX_DEBUG > 0)
9598
auto poolManager = PoolManager::getInstance();
9699
if (!poolManager->getCurrentPool()->isClearing() && poolManager->isObjectInPools(this))

axmol/base/Object.h

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,30 @@ class AX_DLL Object
134134
*/
135135
Object();
136136

137+
/**
138+
* @brief Virtual cleanup hook function called before object destruction (prior to ~Object()).
139+
*
140+
* This protected virtual method serves as a dedicated resource cleanup interface, designed to
141+
* solve the C++ pitfall where calling virtual functions within a destructor fails to invoke
142+
* subclass-specific implementations (polymorphism is disabled during destructor execution).
143+
*
144+
* Unlike destructors, this method is invoked while the object (including all subclass components)
145+
* is still fully intact and its polymorphic behavior is fully functional. Subclasses can override
146+
* this method to implement custom resource release logic (e.g., deallocating dynamic memory,
147+
* closing file handles, releasing engine resources) that would otherwise be unsafe or ineffective
148+
* if placed in a subclass destructor's virtual function call chain.
149+
*
150+
* @note This method is automatically invoked by Object::release() when the reference count
151+
* (_referenceCount) reaches 0, immediately before the object is deleted via `delete this`.
152+
* It is not intended to be called directly from external code (protected access control)
153+
* to avoid invalid resource cleanup or double-free issues.
154+
* @note Subclasses overriding this method should ensure to call the base class implementation
155+
* (Object::dispose()) at the appropriate time to guarantee complete cleanup of the
156+
* inheritance hierarchy.
157+
* @see Object::release() The method that triggers this cleanup hook when reference count is zero.
158+
*/
159+
virtual void dispose();
160+
137161
public:
138162
/**
139163
* Destructor

axmol/rhi/RenderTarget.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,9 @@ THE SOFTWARE.
2727
namespace ax::rhi
2828
{
2929

30-
RenderTarget::~RenderTarget()
30+
RenderTarget::~RenderTarget() {}
31+
32+
void RenderTarget::dispose()
3133
{
3234
cleanupResources();
3335
}

axmol/rhi/RenderTarget.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,9 @@ static constexpr uint32_t INITIAL_COLOR_CAPACITY = 4;
4545
*/
4646
class RenderTarget : public ax::Object
4747
{
48+
protected:
49+
void dispose() override;
50+
4851
public:
4952
struct RenderBuffer
5053
{

axmol/rhi/d3d12/RenderTarget12.cpp

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -35,13 +35,11 @@ RenderTargetImpl::RenderTargetImpl(DriverImpl* driver, bool defaultRenderTarget)
3535
_dirtyFlags = TargetBufferFlags::ALL;
3636
}
3737

38-
RenderTargetImpl::~RenderTargetImpl()
39-
{
40-
_driver->waitForGPU();
41-
}
38+
RenderTargetImpl::~RenderTargetImpl() {}
4239

4340
void RenderTargetImpl::cleanupResources()
4441
{
42+
_driver->waitForGPU();
4543
// RTVs
4644
for (auto i = 0; i < _rtvsDescriptors.size(); ++i)
4745
{

axmol/rhi/vulkan/RenderTargetVK.cpp

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -39,13 +39,12 @@ RenderTargetImpl::RenderTargetImpl(DriverImpl* driver, bool defaultRenderTarget)
3939
_clearValues.reserve(_color.size() + 1);
4040
}
4141

42-
RenderTargetImpl::~RenderTargetImpl()
43-
{
44-
_driver->waitForGPU();
45-
}
42+
RenderTargetImpl::~RenderTargetImpl() {}
4643

4744
void RenderTargetImpl::cleanupResources()
4845
{
46+
_driver->waitForGPU();
47+
4948
// Conservative: wait idle before destroying caches to avoid "in use" errors.
5049
for (auto& [_, pass] : _renderPassCache)
5150
_driver->destroyRenderPass(pass);

0 commit comments

Comments
 (0)