mirror of
https://github.com/thorvg/thorvg.git
synced 2025-06-16 04:54:39 +00:00
wg_engine: fix resources disposing on context destroy
We must to dispose all paints render handles before the context will be destroyed to prevent handles leak
This commit is contained in:
parent
951ea77f5d
commit
6c452c1fd3
4 changed files with 107 additions and 48 deletions
|
@ -207,20 +207,15 @@ void WgMeshDataGroup::release(WgContext& context)
|
||||||
// WgImageData
|
// WgImageData
|
||||||
//***********************************************************************
|
//***********************************************************************
|
||||||
|
|
||||||
void WgImageData::update(WgContext& context, RenderSurface* surface)
|
void WgImageData::update(WgContext& context, const RenderSurface* surface)
|
||||||
{
|
{
|
||||||
release(context);
|
// allocate new texture handle
|
||||||
assert(surface);
|
bool texHandleChanged = context.allocateTexture(texture, surface->w, surface->h, WGPUTextureFormat_RGBA8Unorm, surface->data);
|
||||||
texture = context.createTexture(surface->w, surface->h, WGPUTextureFormat_RGBA8Unorm);
|
// update texture view of texture handle was changed
|
||||||
assert(texture);
|
if (texHandleChanged) {
|
||||||
|
context.releaseTextureView(textureView);
|
||||||
textureView = context.createTextureView(texture);
|
textureView = context.createTextureView(texture);
|
||||||
assert(textureView);
|
}
|
||||||
// update texture data
|
|
||||||
WGPUImageCopyTexture imageCopyTexture{ .texture = texture };
|
|
||||||
WGPUTextureDataLayout textureDataLayout{ .bytesPerRow = 4 * surface->w, .rowsPerImage = surface->h };
|
|
||||||
WGPUExtent3D writeSize{ .width = surface->w, .height = surface->h, .depthOrArrayLayers = 1 };
|
|
||||||
wgpuQueueWriteTexture(context.queue, &imageCopyTexture, surface->data, 4 * surface->w * surface->h, &textureDataLayout, &writeSize);
|
|
||||||
wgpuQueueSubmit(context.queue, 0, nullptr);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -506,26 +501,26 @@ void WgRenderDataShape::release(WgContext& context)
|
||||||
|
|
||||||
WgRenderDataShape* WgRenderDataShapePool::allocate(WgContext& context)
|
WgRenderDataShape* WgRenderDataShapePool::allocate(WgContext& context)
|
||||||
{
|
{
|
||||||
WgRenderDataShape* dataShape{};
|
WgRenderDataShape* renderData{};
|
||||||
if (mPool.count > 0) {
|
if (mPool.count > 0) {
|
||||||
dataShape = mPool.last();
|
renderData = mPool.last();
|
||||||
mPool.pop();
|
mPool.pop();
|
||||||
} else {
|
} else {
|
||||||
dataShape = new WgRenderDataShape();
|
renderData = new WgRenderDataShape();
|
||||||
mList.push(dataShape);
|
mList.push(renderData);
|
||||||
}
|
}
|
||||||
return dataShape;
|
return renderData;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void WgRenderDataShapePool::free(WgContext& context, WgRenderDataShape* dataShape)
|
void WgRenderDataShapePool::free(WgContext& context, WgRenderDataShape* renderData)
|
||||||
{
|
{
|
||||||
dataShape->meshGroupShapes.release(context);
|
renderData->meshGroupShapes.release(context);
|
||||||
dataShape->meshGroupShapesBBox.release(context);
|
renderData->meshGroupShapesBBox.release(context);
|
||||||
dataShape->meshGroupStrokes.release(context);
|
renderData->meshGroupStrokes.release(context);
|
||||||
dataShape->meshGroupStrokesBBox.release(context);
|
renderData->meshGroupStrokesBBox.release(context);
|
||||||
dataShape->clips.clear();
|
renderData->clips.clear();
|
||||||
mPool.push(dataShape);
|
mPool.push(renderData);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -543,10 +538,59 @@ void WgRenderDataShapePool::release(WgContext& context)
|
||||||
// WgRenderDataPicture
|
// WgRenderDataPicture
|
||||||
//***********************************************************************
|
//***********************************************************************
|
||||||
|
|
||||||
|
void WgRenderDataPicture::updateSurface(WgContext& context, const RenderSurface* surface)
|
||||||
|
{
|
||||||
|
// upoate mesh data
|
||||||
|
meshData.imageBox(context, surface->w, surface->h);
|
||||||
|
// update texture data
|
||||||
|
imageData.update(context, surface);
|
||||||
|
// update texture bind group
|
||||||
|
context.pipelines->layouts.releaseBindGroup(bindGroupPicture);
|
||||||
|
bindGroupPicture = context.pipelines->layouts.createBindGroupTexSampled(
|
||||||
|
context.samplerLinearRepeat, imageData.textureView
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void WgRenderDataPicture::release(WgContext& context)
|
void WgRenderDataPicture::release(WgContext& context)
|
||||||
{
|
{
|
||||||
meshData.release(context);
|
|
||||||
imageData.release(context);
|
|
||||||
context.pipelines->layouts.releaseBindGroup(bindGroupPicture);
|
context.pipelines->layouts.releaseBindGroup(bindGroupPicture);
|
||||||
|
imageData.release(context);
|
||||||
|
meshData.release(context);
|
||||||
WgRenderDataPaint::release(context);
|
WgRenderDataPaint::release(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//***********************************************************************
|
||||||
|
// WgRenderDataPicturePool
|
||||||
|
//***********************************************************************
|
||||||
|
|
||||||
|
WgRenderDataPicture* WgRenderDataPicturePool::allocate(WgContext& context)
|
||||||
|
{
|
||||||
|
WgRenderDataPicture* renderData{};
|
||||||
|
if (mPool.count > 0) {
|
||||||
|
renderData = mPool.last();
|
||||||
|
mPool.pop();
|
||||||
|
} else {
|
||||||
|
renderData = new WgRenderDataPicture();
|
||||||
|
mList.push(renderData);
|
||||||
|
}
|
||||||
|
return renderData;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void WgRenderDataPicturePool::free(WgContext& context, WgRenderDataPicture* renderData)
|
||||||
|
{
|
||||||
|
renderData->clips.clear();
|
||||||
|
mPool.push(renderData);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void WgRenderDataPicturePool::release(WgContext& context)
|
||||||
|
{
|
||||||
|
for (uint32_t i = 0; i < mList.count; i++) {
|
||||||
|
mList[i]->release(context);
|
||||||
|
delete mList[i];
|
||||||
|
}
|
||||||
|
mPool.clear();
|
||||||
|
mList.clear();
|
||||||
|
}
|
||||||
|
|
|
@ -69,7 +69,7 @@ struct WgImageData {
|
||||||
WGPUTexture texture{};
|
WGPUTexture texture{};
|
||||||
WGPUTextureView textureView{};
|
WGPUTextureView textureView{};
|
||||||
|
|
||||||
void update(WgContext& context, RenderSurface* surface);
|
void update(WgContext& context, const RenderSurface* surface);
|
||||||
void release(WgContext& context);
|
void release(WgContext& context);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -142,7 +142,7 @@ private:
|
||||||
Array<WgRenderDataShape*> mList;
|
Array<WgRenderDataShape*> mList;
|
||||||
public:
|
public:
|
||||||
WgRenderDataShape* allocate(WgContext& context);
|
WgRenderDataShape* allocate(WgContext& context);
|
||||||
void free(WgContext& context, WgRenderDataShape* dataShape);
|
void free(WgContext& context, WgRenderDataShape* renderData);
|
||||||
void release(WgContext& context);
|
void release(WgContext& context);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -152,8 +152,19 @@ struct WgRenderDataPicture: public WgRenderDataPaint
|
||||||
WgImageData imageData{};
|
WgImageData imageData{};
|
||||||
WgMeshData meshData{};
|
WgMeshData meshData{};
|
||||||
|
|
||||||
|
void updateSurface(WgContext& context, const RenderSurface* surface);
|
||||||
void release(WgContext& context) override;
|
void release(WgContext& context) override;
|
||||||
Type type() override { return Type::Picture; };
|
Type type() override { return Type::Picture; };
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class WgRenderDataPicturePool {
|
||||||
|
private:
|
||||||
|
Array<WgRenderDataPicture*> mPool;
|
||||||
|
Array<WgRenderDataPicture*> mList;
|
||||||
|
public:
|
||||||
|
WgRenderDataPicture* allocate(WgContext& context);
|
||||||
|
void free(WgContext& context, WgRenderDataPicture* dataPicture);
|
||||||
|
void release(WgContext& context);
|
||||||
|
};
|
||||||
|
|
||||||
#endif // _TVG_WG_RENDER_DATA_H_
|
#endif // _TVG_WG_RENDER_DATA_H_
|
||||||
|
|
|
@ -46,13 +46,18 @@ void WgRenderer::release()
|
||||||
// dispose stored objects
|
// dispose stored objects
|
||||||
disposeObjects();
|
disposeObjects();
|
||||||
|
|
||||||
|
// clear render data paint pools
|
||||||
|
mRenderDataShapePool.release(mContext);
|
||||||
|
mRenderDataPicturePool.release(mContext);
|
||||||
|
WgMeshDataPool::gMeshDataPool->release(mContext);
|
||||||
|
|
||||||
|
// clear render storage pool
|
||||||
|
mRenderStoragePool.release(mContext);
|
||||||
|
|
||||||
// clear rendering tree stacks
|
// clear rendering tree stacks
|
||||||
mCompositorStack.clear();
|
mCompositorStack.clear();
|
||||||
mRenderStorageStack.clear();
|
mRenderStorageStack.clear();
|
||||||
mRenderStoragePool.release(mContext);
|
mRenderStorageRoot.release(mContext);
|
||||||
mRenderDataShapePool.release(mContext);
|
|
||||||
WgMeshDataPool::gMeshDataPool->release(mContext);
|
|
||||||
mStorageRoot.release(mContext);
|
|
||||||
|
|
||||||
// release context handles
|
// release context handles
|
||||||
mCompositor.release(mContext);
|
mCompositor.release(mContext);
|
||||||
|
@ -72,8 +77,7 @@ void WgRenderer::disposeObjects()
|
||||||
if (renderData->type() == Type::Shape) {
|
if (renderData->type() == Type::Shape) {
|
||||||
mRenderDataShapePool.free(mContext, (WgRenderDataShape*)renderData);
|
mRenderDataShapePool.free(mContext, (WgRenderDataShape*)renderData);
|
||||||
} else {
|
} else {
|
||||||
renderData->release(mContext);
|
mRenderDataPicturePool.free(mContext, (WgRenderDataPicture*)renderData);
|
||||||
delete renderData;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mDisposeRenderDatas.clear();
|
mDisposeRenderDatas.clear();
|
||||||
|
@ -117,7 +121,7 @@ RenderData WgRenderer::prepare(RenderSurface* surface, RenderData data, const Ma
|
||||||
// get or create render data shape
|
// get or create render data shape
|
||||||
auto renderDataPicture = (WgRenderDataPicture*)data;
|
auto renderDataPicture = (WgRenderDataPicture*)data;
|
||||||
if (!renderDataPicture)
|
if (!renderDataPicture)
|
||||||
renderDataPicture = new WgRenderDataPicture();
|
renderDataPicture = mRenderDataPicturePool.allocate(mContext);
|
||||||
|
|
||||||
// update paint settings
|
// update paint settings
|
||||||
renderDataPicture->viewport = mViewport;
|
renderDataPicture->viewport = mViewport;
|
||||||
|
@ -128,13 +132,7 @@ RenderData WgRenderer::prepare(RenderSurface* surface, RenderData data, const Ma
|
||||||
|
|
||||||
// update image data
|
// update image data
|
||||||
if (flags & (RenderUpdateFlag::Path | RenderUpdateFlag::Image)) {
|
if (flags & (RenderUpdateFlag::Path | RenderUpdateFlag::Image)) {
|
||||||
mContext.pipelines->layouts.releaseBindGroup(renderDataPicture->bindGroupPicture);
|
renderDataPicture->updateSurface(mContext, surface);
|
||||||
renderDataPicture->meshData.release(mContext);
|
|
||||||
renderDataPicture->meshData.imageBox(mContext, surface->w, surface->h);
|
|
||||||
renderDataPicture->imageData.update(mContext, surface);
|
|
||||||
renderDataPicture->bindGroupPicture = mContext.pipelines->layouts.createBindGroupTexSampled(
|
|
||||||
mContext.samplerLinearRepeat, renderDataPicture->imageData.textureView
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// store clips data
|
// store clips data
|
||||||
|
@ -147,7 +145,7 @@ bool WgRenderer::preRender()
|
||||||
{
|
{
|
||||||
// push rot render storage to the render tree stack
|
// push rot render storage to the render tree stack
|
||||||
assert(mRenderStorageStack.count == 0);
|
assert(mRenderStorageStack.count == 0);
|
||||||
mRenderStorageStack.push(&mStorageRoot);
|
mRenderStorageStack.push(&mRenderStorageRoot);
|
||||||
// create command encoder for drawing
|
// create command encoder for drawing
|
||||||
WGPUCommandEncoderDescriptor commandEncoderDesc{};
|
WGPUCommandEncoderDescriptor commandEncoderDesc{};
|
||||||
mCommandEncoder = wgpuDeviceCreateCommandEncoder(mContext.device, &commandEncoderDesc);
|
mCommandEncoder = wgpuDeviceCreateCommandEncoder(mContext.device, &commandEncoderDesc);
|
||||||
|
@ -191,6 +189,7 @@ bool WgRenderer::postRender()
|
||||||
|
|
||||||
|
|
||||||
void WgRenderer::dispose(RenderData data) {
|
void WgRenderer::dispose(RenderData data) {
|
||||||
|
if (!mContext.queue) return;
|
||||||
auto renderData = (WgRenderDataPaint*)data;
|
auto renderData = (WgRenderDataPaint*)data;
|
||||||
if (renderData) {
|
if (renderData) {
|
||||||
ScopedLock lock(mDisposeKey);
|
ScopedLock lock(mDisposeKey);
|
||||||
|
@ -277,7 +276,7 @@ bool WgRenderer::sync()
|
||||||
WGPUCommandEncoder commandEncoder = wgpuDeviceCreateCommandEncoder(mContext.device, &commandEncoderDesc);
|
WGPUCommandEncoder commandEncoder = wgpuDeviceCreateCommandEncoder(mContext.device, &commandEncoderDesc);
|
||||||
|
|
||||||
// show root offscreen buffer
|
// show root offscreen buffer
|
||||||
mCompositor.blit(mContext, commandEncoder, &mStorageRoot, dstTextureView);
|
mCompositor.blit(mContext, commandEncoder, &mRenderStorageRoot, dstTextureView);
|
||||||
|
|
||||||
// release command encoder
|
// release command encoder
|
||||||
const WGPUCommandBufferDescriptor commandBufferDesc{};
|
const WGPUCommandBufferDescriptor commandBufferDesc{};
|
||||||
|
@ -317,7 +316,7 @@ bool WgRenderer::target(WGPUDevice device, WGPUInstance instance, void* target,
|
||||||
|
|
||||||
// initialize render tree instances
|
// initialize render tree instances
|
||||||
mRenderStoragePool.initialize(mContext, width, height);
|
mRenderStoragePool.initialize(mContext, width, height);
|
||||||
mStorageRoot.initialize(mContext, width, height);
|
mRenderStorageRoot.initialize(mContext, width, height);
|
||||||
mCompositor.initialize(mContext, width, height);
|
mCompositor.initialize(mContext, width, height);
|
||||||
|
|
||||||
// configure surface (must be called after context creation)
|
// configure surface (must be called after context creation)
|
||||||
|
|
|
@ -71,12 +71,17 @@ private:
|
||||||
void clearTargets();
|
void clearTargets();
|
||||||
bool surfaceConfigure(WGPUSurface surface, WgContext& context, uint32_t width, uint32_t height);
|
bool surfaceConfigure(WGPUSurface surface, WgContext& context, uint32_t width, uint32_t height);
|
||||||
|
|
||||||
// render tree stacks and pools
|
// render tree stacks
|
||||||
WgRenderStorage mStorageRoot;
|
WgRenderStorage mRenderStorageRoot;
|
||||||
Array<WgCompose*> mCompositorStack;
|
Array<WgCompose*> mCompositorStack;
|
||||||
Array<WgRenderStorage*> mRenderStorageStack;
|
Array<WgRenderStorage*> mRenderStorageStack;
|
||||||
|
|
||||||
|
// render storage pool
|
||||||
WgRenderStoragePool mRenderStoragePool;
|
WgRenderStoragePool mRenderStoragePool;
|
||||||
|
|
||||||
|
// render data paint pools
|
||||||
WgRenderDataShapePool mRenderDataShapePool;
|
WgRenderDataShapePool mRenderDataShapePool;
|
||||||
|
WgRenderDataPicturePool mRenderDataPicturePool;
|
||||||
|
|
||||||
// rendering context
|
// rendering context
|
||||||
WgContext mContext;
|
WgContext mContext;
|
||||||
|
|
Loading…
Add table
Reference in a new issue