diff --git a/src/renderer/wg_engine/tvgWgRenderData.cpp b/src/renderer/wg_engine/tvgWgRenderData.cpp index 9fbddd68..ed91a27a 100755 --- a/src/renderer/wg_engine/tvgWgRenderData.cpp +++ b/src/renderer/wg_engine/tvgWgRenderData.cpp @@ -207,20 +207,15 @@ void WgMeshDataGroup::release(WgContext& context) // WgImageData //*********************************************************************** -void WgImageData::update(WgContext& context, RenderSurface* surface) +void WgImageData::update(WgContext& context, const RenderSurface* surface) { - release(context); - assert(surface); - texture = context.createTexture(surface->w, surface->h, WGPUTextureFormat_RGBA8Unorm); - assert(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); + // allocate new texture handle + bool texHandleChanged = context.allocateTexture(texture, surface->w, surface->h, WGPUTextureFormat_RGBA8Unorm, surface->data); + // update texture view of texture handle was changed + if (texHandleChanged) { + context.releaseTextureView(textureView); + textureView = context.createTextureView(texture); + } }; @@ -506,26 +501,26 @@ void WgRenderDataShape::release(WgContext& context) WgRenderDataShape* WgRenderDataShapePool::allocate(WgContext& context) { - WgRenderDataShape* dataShape{}; + WgRenderDataShape* renderData{}; if (mPool.count > 0) { - dataShape = mPool.last(); + renderData = mPool.last(); mPool.pop(); } else { - dataShape = new WgRenderDataShape(); - mList.push(dataShape); + renderData = new WgRenderDataShape(); + 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); - dataShape->meshGroupShapesBBox.release(context); - dataShape->meshGroupStrokes.release(context); - dataShape->meshGroupStrokesBBox.release(context); - dataShape->clips.clear(); - mPool.push(dataShape); + renderData->meshGroupShapes.release(context); + renderData->meshGroupShapesBBox.release(context); + renderData->meshGroupStrokes.release(context); + renderData->meshGroupStrokesBBox.release(context); + renderData->clips.clear(); + mPool.push(renderData); } @@ -543,10 +538,59 @@ void WgRenderDataShapePool::release(WgContext& context) // 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) { - meshData.release(context); - imageData.release(context); context.pipelines->layouts.releaseBindGroup(bindGroupPicture); + imageData.release(context); + meshData.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(); +} diff --git a/src/renderer/wg_engine/tvgWgRenderData.h b/src/renderer/wg_engine/tvgWgRenderData.h index 1b091688..29d28945 100755 --- a/src/renderer/wg_engine/tvgWgRenderData.h +++ b/src/renderer/wg_engine/tvgWgRenderData.h @@ -69,7 +69,7 @@ struct WgImageData { WGPUTexture texture{}; WGPUTextureView textureView{}; - void update(WgContext& context, RenderSurface* surface); + void update(WgContext& context, const RenderSurface* surface); void release(WgContext& context); }; @@ -142,7 +142,7 @@ private: Array mList; public: WgRenderDataShape* allocate(WgContext& context); - void free(WgContext& context, WgRenderDataShape* dataShape); + void free(WgContext& context, WgRenderDataShape* renderData); void release(WgContext& context); }; @@ -152,8 +152,19 @@ struct WgRenderDataPicture: public WgRenderDataPaint WgImageData imageData{}; WgMeshData meshData{}; + void updateSurface(WgContext& context, const RenderSurface* surface); void release(WgContext& context) override; Type type() override { return Type::Picture; }; }; +class WgRenderDataPicturePool { +private: + Array mPool; + Array mList; +public: + WgRenderDataPicture* allocate(WgContext& context); + void free(WgContext& context, WgRenderDataPicture* dataPicture); + void release(WgContext& context); +}; + #endif // _TVG_WG_RENDER_DATA_H_ diff --git a/src/renderer/wg_engine/tvgWgRenderer.cpp b/src/renderer/wg_engine/tvgWgRenderer.cpp index 070904e3..35f18982 100755 --- a/src/renderer/wg_engine/tvgWgRenderer.cpp +++ b/src/renderer/wg_engine/tvgWgRenderer.cpp @@ -46,13 +46,18 @@ void WgRenderer::release() // dispose stored objects 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 mCompositorStack.clear(); mRenderStorageStack.clear(); - mRenderStoragePool.release(mContext); - mRenderDataShapePool.release(mContext); - WgMeshDataPool::gMeshDataPool->release(mContext); - mStorageRoot.release(mContext); + mRenderStorageRoot.release(mContext); // release context handles mCompositor.release(mContext); @@ -72,8 +77,7 @@ void WgRenderer::disposeObjects() if (renderData->type() == Type::Shape) { mRenderDataShapePool.free(mContext, (WgRenderDataShape*)renderData); } else { - renderData->release(mContext); - delete renderData; + mRenderDataPicturePool.free(mContext, (WgRenderDataPicture*)renderData); } } mDisposeRenderDatas.clear(); @@ -117,7 +121,7 @@ RenderData WgRenderer::prepare(RenderSurface* surface, RenderData data, const Ma // get or create render data shape auto renderDataPicture = (WgRenderDataPicture*)data; if (!renderDataPicture) - renderDataPicture = new WgRenderDataPicture(); + renderDataPicture = mRenderDataPicturePool.allocate(mContext); // update paint settings renderDataPicture->viewport = mViewport; @@ -128,13 +132,7 @@ RenderData WgRenderer::prepare(RenderSurface* surface, RenderData data, const Ma // update image data if (flags & (RenderUpdateFlag::Path | RenderUpdateFlag::Image)) { - mContext.pipelines->layouts.releaseBindGroup(renderDataPicture->bindGroupPicture); - 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 - ); + renderDataPicture->updateSurface(mContext, surface); } // store clips data @@ -147,7 +145,7 @@ bool WgRenderer::preRender() { // push rot render storage to the render tree stack assert(mRenderStorageStack.count == 0); - mRenderStorageStack.push(&mStorageRoot); + mRenderStorageStack.push(&mRenderStorageRoot); // create command encoder for drawing WGPUCommandEncoderDescriptor commandEncoderDesc{}; mCommandEncoder = wgpuDeviceCreateCommandEncoder(mContext.device, &commandEncoderDesc); @@ -191,6 +189,7 @@ bool WgRenderer::postRender() void WgRenderer::dispose(RenderData data) { + if (!mContext.queue) return; auto renderData = (WgRenderDataPaint*)data; if (renderData) { ScopedLock lock(mDisposeKey); @@ -277,7 +276,7 @@ bool WgRenderer::sync() WGPUCommandEncoder commandEncoder = wgpuDeviceCreateCommandEncoder(mContext.device, &commandEncoderDesc); // show root offscreen buffer - mCompositor.blit(mContext, commandEncoder, &mStorageRoot, dstTextureView); + mCompositor.blit(mContext, commandEncoder, &mRenderStorageRoot, dstTextureView); // release command encoder const WGPUCommandBufferDescriptor commandBufferDesc{}; @@ -317,7 +316,7 @@ bool WgRenderer::target(WGPUDevice device, WGPUInstance instance, void* target, // initialize render tree instances mRenderStoragePool.initialize(mContext, width, height); - mStorageRoot.initialize(mContext, width, height); + mRenderStorageRoot.initialize(mContext, width, height); mCompositor.initialize(mContext, width, height); // configure surface (must be called after context creation) diff --git a/src/renderer/wg_engine/tvgWgRenderer.h b/src/renderer/wg_engine/tvgWgRenderer.h index 56e25457..8c8717cb 100755 --- a/src/renderer/wg_engine/tvgWgRenderer.h +++ b/src/renderer/wg_engine/tvgWgRenderer.h @@ -71,12 +71,17 @@ private: void clearTargets(); bool surfaceConfigure(WGPUSurface surface, WgContext& context, uint32_t width, uint32_t height); - // render tree stacks and pools - WgRenderStorage mStorageRoot; + // render tree stacks + WgRenderStorage mRenderStorageRoot; Array mCompositorStack; Array mRenderStorageStack; + + // render storage pool WgRenderStoragePool mRenderStoragePool; + + // render data paint pools WgRenderDataShapePool mRenderDataShapePool; + WgRenderDataPicturePool mRenderDataPicturePool; // rendering context WgContext mContext;