diff --git a/examples/Example.h b/examples/Example.h index 02f22075..bad0177f 100644 --- a/examples/Example.h +++ b/examples/Example.h @@ -425,14 +425,14 @@ struct WgWindow : Window virtual ~WgWindow() { - wgpuSurfaceRelease(surface); + //wgpuSurfaceRelease(surface); wgpuInstanceRelease(instance); } void resize() override { //Set the canvas target and draw on it. - verify(static_cast(canvas)->target(instance, surface, width, height)); + verify(static_cast(canvas)->target(nullptr, instance, surface, width, height)); } void refresh() override diff --git a/inc/thorvg.h b/inc/thorvg.h index 1a12b4c5..da455613 100644 --- a/inc/thorvg.h +++ b/inc/thorvg.h @@ -1774,11 +1774,12 @@ public: /** * @brief Sets the drawing target for the rasterization. * - * @param[in] instance WGPUInstance, context for all other wgpu objects. - * @param[in] surface WGPUSurface, handle to a presentable surface. - * @param[in] w The width of the surface. - * @param[in] h The height of the surface. * @param[in] device WGPUDevice, a desired handle for the wgpu device. If it is @c nullptr, ThorVG will assign an appropriate device internally. + * @param[in] instance WGPUInstance, context for all other wgpu objects. + * @param[in] target Either WGPUSurface or WGPUTexture, serving as handles to a presentable surface or texture + * @param[in] w The width of the target. + * @param[in] h The height of the target. + * @param[in] type 0: surface, 1: texture are used as pesentable target * * @retval Result::InsufficientCondition if the canvas is performing rendering. Please ensure the canvas is synced. * @retval Result::NonSupport In case the wg engine is not supported. @@ -1788,7 +1789,7 @@ public: * @see Canvas::viewport() * @see Canvas::sync() */ - Result target(void* instance, void* surface, uint32_t w, uint32_t h, void* device = nullptr) noexcept; + Result target(void* device, void* instance, void* target, uint32_t w, uint32_t h, int type = 0) noexcept; /** * @brief Creates a new WgCanvas object. @@ -2148,4 +2149,4 @@ public: } //namespace -#endif //_THORVG_H_ +#endif //_THORVG_H_ \ No newline at end of file diff --git a/src/bindings/capi/thorvg_capi.h b/src/bindings/capi/thorvg_capi.h index 0d3b31a0..ce291511 100644 --- a/src/bindings/capi/thorvg_capi.h +++ b/src/bindings/capi/thorvg_capi.h @@ -560,11 +560,12 @@ TVG_API Tvg_Canvas* tvg_wgcanvas_create(void); /*! * \brief Sets the drawing target for the rasterization. * -* \param[in] instance WGPUInstance, context for all other wgpu objects. -* \param[in] surface WGPUSurface, handle to a presentable surface. -* \param[in] w The width of the surface. -* \param[in] h The height of the surface. -* \param[in] device WGPUDevice, a desired handle for the wgpu device. If it is @c nullptr, ThorVG will assign an appropriate device internally. +* @param[in] device WGPUDevice, a desired handle for the wgpu device. If it is @c nullptr, ThorVG will assign an appropriate device internally. +* @param[in] instance WGPUInstance, context for all other wgpu objects. +* @param[in] target Either WGPUSurface or WGPUTexture, serving as handles to a presentable surface or texture +* @param[in] w The width of the target. +* @param[in] h The height of the target. +* @param[in] type 0: surface, 1: texture are used as pesentable target * * \return Tvg_Result enumeration. * \retval TVG_RESULT_INSUFFICIENT_CONDITION if the canvas is performing rendering. Please ensure the canvas is synced. @@ -572,7 +573,7 @@ TVG_API Tvg_Canvas* tvg_wgcanvas_create(void); * * \note Experimental API */ -TVG_API Tvg_Result tvg_wgcanvas_set_target(Tvg_Canvas* canvas, void* instance, void* surface, uint32_t w, uint32_t h, void* device); +TVG_API Tvg_Result tvg_wgcanvas_set_target(Tvg_Canvas* canvas, void* device, void* instance, void* target, uint32_t w, uint32_t h, int type = 0); /** \} */ // end defgroup ThorVGCapi_WgCanvas diff --git a/src/bindings/capi/tvgCapi.cpp b/src/bindings/capi/tvgCapi.cpp index c9457114..3ec7b601 100644 --- a/src/bindings/capi/tvgCapi.cpp +++ b/src/bindings/capi/tvgCapi.cpp @@ -109,10 +109,10 @@ TVG_API Tvg_Result tvg_glcanvas_set_target(Tvg_Canvas* canvas, int32_t id, uint3 } -TVG_API Tvg_Result tvg_wgcanvas_set_target(Tvg_Canvas* canvas, void* instance, void* surface, uint32_t w, uint32_t h, void* device) +TVG_API Tvg_Result tvg_wgcanvas_set_target(Tvg_Canvas* canvas, void* device, void* instance, void* target, uint32_t w, uint32_t h, int type) { if (!canvas) return TVG_RESULT_INVALID_ARGUMENT; - return (Tvg_Result) reinterpret_cast(canvas)->target(instance, surface, w, h, device); + return (Tvg_Result) reinterpret_cast(canvas)->target(device, instance, target, w, h, type); } diff --git a/src/bindings/wasm/tvgWasmLottieAnimation.cpp b/src/bindings/wasm/tvgWasmLottieAnimation.cpp index e0447ed6..867aa01d 100644 --- a/src/bindings/wasm/tvgWasmLottieAnimation.cpp +++ b/src/bindings/wasm/tvgWasmLottieAnimation.cpp @@ -150,7 +150,7 @@ struct TvgWgEngine : TvgEngineMethod void resize(Canvas* canvas, int w, int h) override { #ifdef THORVG_WG_RASTER_SUPPORT - static_cast(canvas)->target(instance, surface, w, h, device); + static_cast(canvas)->target(device, instance, surface, w, h); #endif } }; diff --git a/src/renderer/tvgWgCanvas.cpp b/src/renderer/tvgWgCanvas.cpp index d6dafbe6..a95a7bf2 100644 --- a/src/renderer/tvgWgCanvas.cpp +++ b/src/renderer/tvgWgCanvas.cpp @@ -52,25 +52,23 @@ WgCanvas::~WgCanvas() { #ifdef THORVG_WG_RASTER_SUPPORT auto renderer = static_cast(Canvas::pImpl->renderer); - renderer->target(nullptr, 0, 0); + renderer->target(nullptr, nullptr, nullptr, 0, 0); #endif } -Result WgCanvas::target(void* instance, void* surface, uint32_t w, uint32_t h, void* device) noexcept +Result WgCanvas::target(void* device, void* instance, void* target, uint32_t w, uint32_t h, int type) noexcept { #ifdef THORVG_WG_RASTER_SUPPORT if (Canvas::pImpl->status != Status::Damaged && Canvas::pImpl->status != Status::Synced) { return Result::InsufficientCondition; } - if (!instance || !surface || (w == 0) || (h == 0)) return Result::InvalidArguments; - //We know renderer type, avoid dynamic_cast for performance. auto renderer = static_cast(Canvas::pImpl->renderer); if (!renderer) return Result::MemoryCorruption; - if (!renderer->target((WGPUInstance)instance, (WGPUSurface)surface, w, h, (WGPUDevice)device)) return Result::Unknown; + if (!renderer->target((WGPUDevice)device, (WGPUInstance)instance, target, w, h, type)) return Result::Unknown; Canvas::pImpl->vport = {0, 0, (int32_t)w, (int32_t)h}; renderer->viewport(Canvas::pImpl->vport); diff --git a/src/renderer/wg_engine/tvgWgBindGroups.cpp b/src/renderer/wg_engine/tvgWgBindGroups.cpp index f3373fdb..cf8037a1 100755 --- a/src/renderer/wg_engine/tvgWgBindGroups.cpp +++ b/src/renderer/wg_engine/tvgWgBindGroups.cpp @@ -140,6 +140,12 @@ void WgBindGroupLayouts::releaseBindGroup(WGPUBindGroup& bindGroup) bindGroup = nullptr; } +void WgBindGroupLayouts::releaseBindGroupLayout(WGPUBindGroupLayout& bindGroupLayout) +{ + if (bindGroupLayout) wgpuBindGroupLayoutRelease(bindGroupLayout); + bindGroupLayout = nullptr; +} + void WgBindGroupLayouts::initialize(WgContext& context) { @@ -262,14 +268,15 @@ void WgBindGroupLayouts::initialize(WgContext& context) void WgBindGroupLayouts::release(WgContext& context) { - wgpuBindGroupLayoutRelease(layoutBuffer3Un); - wgpuBindGroupLayoutRelease(layoutBuffer2Un); - wgpuBindGroupLayoutRelease(layoutBuffer1Un); - wgpuBindGroupLayoutRelease(layoutTexStrorage3RO); - wgpuBindGroupLayoutRelease(layoutTexStrorage2RO); - wgpuBindGroupLayoutRelease(layoutTexStrorage1RO); - wgpuBindGroupLayoutRelease(layoutTexStrorage1WO); - wgpuBindGroupLayoutRelease(layoutTexSampledBuff1Un); - wgpuBindGroupLayoutRelease(layoutTexSampled); + releaseBindGroupLayout(layoutBuffer3Un); + releaseBindGroupLayout(layoutBuffer2Un); + releaseBindGroupLayout(layoutBuffer1Un); + releaseBindGroupLayout(layoutTexStrorage3RO); + releaseBindGroupLayout(layoutTexStrorage2RO); + releaseBindGroupLayout(layoutTexStrorage1RO); + releaseBindGroupLayout(layoutTexStrorage1WO); + releaseBindGroupLayout(layoutTexSampledBuff1Un); + releaseBindGroupLayout(layoutTexSampledBuff2Un); + releaseBindGroupLayout(layoutTexSampled); device = nullptr; } diff --git a/src/renderer/wg_engine/tvgWgBindGroups.h b/src/renderer/wg_engine/tvgWgBindGroups.h index ee587b60..b41bb9eb 100755 --- a/src/renderer/wg_engine/tvgWgBindGroups.h +++ b/src/renderer/wg_engine/tvgWgBindGroups.h @@ -51,6 +51,7 @@ public: WGPUBindGroup createBindGroupBuffer2Un(WGPUBuffer buff0, WGPUBuffer buff1); WGPUBindGroup createBindGroupBuffer3Un(WGPUBuffer buff0, WGPUBuffer buff1, WGPUBuffer buff2); void releaseBindGroup(WGPUBindGroup& bindGroup); + void releaseBindGroupLayout(WGPUBindGroupLayout& bindGroupLayout); public: void initialize(WgContext& context); void release(WgContext& context); diff --git a/src/renderer/wg_engine/tvgWgCommon.cpp b/src/renderer/wg_engine/tvgWgCommon.cpp index 5077611b..1bd6f1a6 100755 --- a/src/renderer/wg_engine/tvgWgCommon.cpp +++ b/src/renderer/wg_engine/tvgWgCommon.cpp @@ -260,7 +260,7 @@ void WgContext::releaseBuffer(WGPUBuffer& buffer) } } -void WgContext::releaseQueue(WGPUQueue queue) +void WgContext::releaseQueue(WGPUQueue& queue) { if (queue) { wgpuQueueRelease(queue); diff --git a/src/renderer/wg_engine/tvgWgCommon.h b/src/renderer/wg_engine/tvgWgCommon.h index a6c6cd19..ace62e94 100755 --- a/src/renderer/wg_engine/tvgWgCommon.h +++ b/src/renderer/wg_engine/tvgWgCommon.h @@ -63,7 +63,7 @@ struct WgContext { void releaseTextureView(WGPUTextureView& textureView); void releaseTexture(WGPUTexture& texture); void releaseSampler(WGPUSampler& sampler); - void releaseQueue(WGPUQueue queue); + void releaseQueue(WGPUQueue& queue); // create buffer objects (return true, if buffer handle was changed) bool allocateBufferUniform(WGPUBuffer& buffer, const void* data, uint64_t size); diff --git a/src/renderer/wg_engine/tvgWgRenderData.cpp b/src/renderer/wg_engine/tvgWgRenderData.cpp index 8f96494b..9fbddd68 100755 --- a/src/renderer/wg_engine/tvgWgRenderData.cpp +++ b/src/renderer/wg_engine/tvgWgRenderData.cpp @@ -165,7 +165,8 @@ void WgMeshDataPool::release(WgContext& context) mList.clear(); } -WgMeshDataPool* WgMeshDataGroup::gMeshDataPool = nullptr; +WgMeshDataPool gMeshDataPoolInstance; +WgMeshDataPool* WgMeshDataPool::gMeshDataPool = &gMeshDataPoolInstance; //*********************************************************************** // WgMeshDataGroup @@ -174,7 +175,7 @@ WgMeshDataPool* WgMeshDataGroup::gMeshDataPool = nullptr; void WgMeshDataGroup::append(WgContext& context, const WgVertexBuffer& vertexBuffer) { assert(vertexBuffer.vcount >= 3); - meshes.push(gMeshDataPool->allocate(context)); + meshes.push(WgMeshDataPool::gMeshDataPool->allocate(context)); meshes.last()->update(context, vertexBuffer); } @@ -182,14 +183,14 @@ void WgMeshDataGroup::append(WgContext& context, const WgVertexBuffer& vertexBuf void WgMeshDataGroup::append(WgContext& context, const WgVertexBufferInd& vertexBufferInd) { assert(vertexBufferInd.vcount >= 3); - meshes.push(gMeshDataPool->allocate(context)); + meshes.push(WgMeshDataPool::gMeshDataPool->allocate(context)); meshes.last()->update(context, vertexBufferInd); } void WgMeshDataGroup::append(WgContext& context, const Point pmin, const Point pmax) { - meshes.push(gMeshDataPool->allocate(context)); + meshes.push(WgMeshDataPool::gMeshDataPool->allocate(context)); meshes.last()->bbox(context, pmin, pmax); } @@ -197,7 +198,7 @@ void WgMeshDataGroup::append(WgContext& context, const Point pmin, const Point p void WgMeshDataGroup::release(WgContext& context) { for (uint32_t i = 0; i < meshes.count; i++) - gMeshDataPool->free(context, meshes[i]); + WgMeshDataPool::gMeshDataPool->free(context, meshes[i]); meshes.clear(); }; @@ -298,8 +299,6 @@ void WgRenderSettings::release(WgContext& context) // WgRenderDataPaint //*********************************************************************** -WgVertexBufferInd* WgRenderDataPaint::gStrokesGenerator = nullptr; - void WgRenderDataPaint::release(WgContext& context) { context.pipelines->layouts.releaseBindGroup(bindGroupPaint); @@ -455,7 +454,8 @@ void WgRenderDataShape::updateMeshes(WgContext &context, const RenderShape &rsha void WgRenderDataShape::proceedStrokes(WgContext context, const RenderStroke* rstroke, float tbeg, float tend, const WgVertexBuffer& buff) { assert(rstroke); - gStrokesGenerator->reset(buff.tscale); + static WgVertexBufferInd strokesGenerator; + strokesGenerator.reset(buff.tscale); // trim -> dash -> stroke if ((tbeg != 0.0f) || (tend != 1.0f)) { if (tbeg == tend) return; @@ -464,17 +464,17 @@ void WgRenderDataShape::proceedStrokes(WgContext context, const RenderStroke* rs trimed_buff.trim(buff, tbeg, tend); trimed_buff.updateDistances(); // trim ->dash -> stroke - if (rstroke->dashPattern) gStrokesGenerator->appendStrokesDashed(trimed_buff, rstroke); + if (rstroke->dashPattern) strokesGenerator.appendStrokesDashed(trimed_buff, rstroke); // trim -> stroke - else gStrokesGenerator->appendStrokes(trimed_buff, rstroke); + else strokesGenerator.appendStrokes(trimed_buff, rstroke); } else // dash -> stroke if (rstroke->dashPattern) { - gStrokesGenerator->appendStrokesDashed(buff, rstroke); + strokesGenerator.appendStrokesDashed(buff, rstroke); // stroke } else - gStrokesGenerator->appendStrokes(buff, rstroke); - appendStroke(context, *gStrokesGenerator); + strokesGenerator.appendStrokes(buff, rstroke); + appendStroke(context, strokesGenerator); } diff --git a/src/renderer/wg_engine/tvgWgRenderData.h b/src/renderer/wg_engine/tvgWgRenderData.h index 79ee1ece..1b091688 100755 --- a/src/renderer/wg_engine/tvgWgRenderData.h +++ b/src/renderer/wg_engine/tvgWgRenderData.h @@ -50,14 +50,13 @@ private: Array mPool; Array mList; public: + static WgMeshDataPool* gMeshDataPool; WgMeshData* allocate(WgContext& context); void free(WgContext& context, WgMeshData* meshData); void release(WgContext& context); }; struct WgMeshDataGroup { - static WgMeshDataPool* gMeshDataPool; - Array meshes{}; void append(WgContext& context, const WgVertexBuffer& vertexBuffer); @@ -96,9 +95,6 @@ struct WgRenderSettings struct WgRenderDataPaint { - // global strokes generator. single instance - static WgVertexBufferInd* gStrokesGenerator; - WGPUBuffer bufferModelMat{}; WGPUBuffer bufferBlendSettings{}; WGPUBindGroup bindGroupPaint{}; diff --git a/src/renderer/wg_engine/tvgWgRenderer.cpp b/src/renderer/wg_engine/tvgWgRenderer.cpp index cb4d02fd..c8e6342d 100755 --- a/src/renderer/wg_engine/tvgWgRenderer.cpp +++ b/src/renderer/wg_engine/tvgWgRenderer.cpp @@ -30,47 +30,45 @@ WgRenderer::WgRenderer() WgRenderer::~WgRenderer() { release(); - mContext.release(); } void WgRenderer::initialize() { - mPipelines.initialize(mContext); - WgMeshDataGroup::gMeshDataPool = new WgMeshDataPool(); - WgRenderDataShape::gStrokesGenerator = new WgVertexBufferInd(); } void WgRenderer::release() { + // check for general context availability + if (!mContext.queue) return; + + // dispose stored objects disposeObjects(); - mStorageRoot.release(mContext); - mRenderStoragePool.release(mContext); - mRenderDataShapePool.release(mContext); - delete WgRenderDataShape::gStrokesGenerator; - WgMeshDataGroup::gMeshDataPool->release(mContext); - delete WgMeshDataGroup::gMeshDataPool; + + // clear rendering tree stacks mCompositorStack.clear(); mRenderStorageStack.clear(); + mRenderStoragePool.release(mContext); + mRenderDataShapePool.release(mContext); + WgMeshDataPool::gMeshDataPool->release(mContext); + mStorageRoot.release(mContext); + + // release context handles + mCompositor.release(mContext); mPipelines.release(mContext); - if (gpuOwner) { - if (device) wgpuDeviceRelease(device); - device = nullptr; - if (adapter) wgpuAdapterRelease(adapter); - adapter = nullptr; - gpuOwner = false; - } - releaseSurfaceTexture(); + mContext.release(); + + // release gpu handles + clearTargets(); + releaseDevice(); } void WgRenderer::disposeObjects() { - if (mDisposeRenderDatas.count == 0) return; - - for (auto p = mDisposeRenderDatas.begin(); p < mDisposeRenderDatas.end(); p++) { - auto renderData = (WgRenderDataPaint*)(*p); + for (uint32_t i = 0; i < mDisposeRenderDatas.count; i++) { + WgRenderDataPaint* renderData = (WgRenderDataPaint*)mDisposeRenderDatas[i]; if (renderData->type() == Type::Shape) { mRenderDataShapePool.free(mContext, (WgRenderDataShape*)renderData); } else { @@ -260,20 +258,26 @@ void WgRenderer::releaseSurfaceTexture() bool WgRenderer::sync() { disposeObjects(); - if (!surface) return false; - releaseSurfaceTexture(); + // if texture buffer used + WGPUTexture dstTexture = targetTexture; + if (surface) { + releaseSurfaceTexture(); + wgpuSurfaceGetCurrentTexture(surface, &surfaceTexture); + dstTexture = surfaceTexture.texture; + } + // there is no external dest buffer + if (!dstTexture) return false; - wgpuSurfaceGetCurrentTexture(surface, &surfaceTexture); - - WGPUTextureView dstView = mContext.createTextureView(surfaceTexture.texture); + // get external dest buffer + WGPUTextureView dstTextureView = mContext.createTextureView(dstTexture); // create command encoder const WGPUCommandEncoderDescriptor commandEncoderDesc{}; WGPUCommandEncoder commandEncoder = wgpuDeviceCreateCommandEncoder(mContext.device, &commandEncoderDesc); // show root offscreen buffer - mCompositor.blit(mContext, commandEncoder, &mStorageRoot, dstView); + mCompositor.blit(mContext, commandEncoder, &mStorageRoot, dstTextureView); // release command encoder const WGPUCommandBufferDescriptor commandBufferDesc{}; @@ -281,68 +285,109 @@ bool WgRenderer::sync() wgpuQueueSubmit(mContext.queue, 1, &commandsBuffer); wgpuCommandBufferRelease(commandsBuffer); wgpuCommandEncoderRelease(commandEncoder); - mContext.releaseTextureView(dstView); + // release dest buffer view + mContext.releaseTextureView(dstTextureView); return true; } -// target for native window handle -bool WgRenderer::target(WGPUInstance instance, WGPUSurface surface, uint32_t w, uint32_t h, WGPUDevice device) +// render target handle +bool WgRenderer::target(WGPUDevice device, WGPUInstance instance, void* target, uint32_t width, uint32_t height, int type) { - gpuOwner = false; + // release existing handles + release(); + + // can not initialize renderer, give up + if (!instance || !target || !width || !height) return false; + + // store or regest gpu device this->device = device; - if (!this->device) { - // request adapter - const WGPURequestAdapterOptions requestAdapterOptions { .nextInChain = nullptr, .compatibleSurface = surface, .powerPreference = WGPUPowerPreference_HighPerformance, .forceFallbackAdapter = false }; - auto onAdapterRequestEnded = [](WGPURequestAdapterStatus status, WGPUAdapter adapter, char const * message, void * pUserData) { *((WGPUAdapter*)pUserData) = adapter; }; - wgpuInstanceRequestAdapter(instance, &requestAdapterOptions, onAdapterRequestEnded, &this->adapter); + if (!this->device) + reguestDevice(instance, (WGPUSurface)target); - // get adapter and surface properties - WGPUFeatureName featureNames[32]{}; - size_t featuresCount = wgpuAdapterEnumerateFeatures(this->adapter, featureNames); - - // request device - const WGPUDeviceDescriptor deviceDesc { .nextInChain = nullptr, .label = "The device", .requiredFeatureCount = featuresCount, .requiredFeatures = featureNames }; - auto onDeviceRequestEnded = [](WGPURequestDeviceStatus status, WGPUDevice device, char const * message, void * pUserData) { *((WGPUDevice*)pUserData) = device; }; - wgpuAdapterRequestDevice(this->adapter, &deviceDesc, onDeviceRequestEnded, &this->device); - gpuOwner = true; - } + // store target properties + mTargetSurface.stride = width; + mTargetSurface.w = width; + mTargetSurface.h = height; + // initialize rendering context mContext.initialize(instance, this->device); - initialize(); - target(surface, w, h); - mRenderStoragePool.initialize(mContext, w, h); - mStorageRoot.initialize(mContext, w, h); - mCompositor.initialize(mContext, w, h); + mPipelines.initialize(mContext); + + // initialize render tree instances + mRenderStoragePool.initialize(mContext, width, height); + mStorageRoot.initialize(mContext, width, height); + mCompositor.initialize(mContext, width, height); + + // configure surface (must be called after context creation) + if (type == 0) { + surface = (WGPUSurface)target; + surfaceConfigure(surface, mContext, width, height); + } else targetTexture = (WGPUTexture)target; return true; } -bool WgRenderer::target(WGPUSurface surface, uint32_t w, uint32_t h) { + +void WgRenderer::reguestDevice(WGPUInstance instance, WGPUSurface surface) +{ + // request adapter + const WGPURequestAdapterOptions requestAdapterOptions { .compatibleSurface = surface, .powerPreference = WGPUPowerPreference_HighPerformance }; + auto onAdapterRequestEnded = [](WGPURequestAdapterStatus status, WGPUAdapter adapter, char const * message, void * pUserData) { *((WGPUAdapter*)pUserData) = adapter; }; + wgpuInstanceRequestAdapter(instance, &requestAdapterOptions, onAdapterRequestEnded, &this->adapter); + + // get adapter and surface properties + WGPUFeatureName featureNames[32]{}; + size_t featuresCount = wgpuAdapterEnumerateFeatures(this->adapter, featureNames); + + // request device + const WGPUDeviceDescriptor deviceDesc { .label = "The owned device", .requiredFeatureCount = featuresCount, .requiredFeatures = featureNames }; + auto onDeviceRequestEnded = [](WGPURequestDeviceStatus status, WGPUDevice device, char const * message, void * pUserData) { *((WGPUDevice*)pUserData) = device; }; + wgpuAdapterRequestDevice(this->adapter, &deviceDesc, onDeviceRequestEnded, &this->device); + gpuOwner = true; +} + + +void WgRenderer::releaseDevice() +{ + if (!gpuOwner) return; + wgpuDeviceRelease(device); + wgpuDeviceDestroy(device); + wgpuAdapterRelease(adapter); + device = nullptr; + adapter = nullptr; + gpuOwner = false; +} + + +void WgRenderer::clearTargets() { + releaseSurfaceTexture(); + targetTexture = nullptr; + surface = nullptr; +} + + +bool WgRenderer::surfaceConfigure(WGPUSurface surface, WgContext& context, uint32_t width, uint32_t height) +{ // store target surface properties this->surface = surface; - mTargetSurface.stride = w; - mTargetSurface.w = w; - mTargetSurface.h = h; - if (w == 0 || h == 0) return false; - if (!surface) return true; + if (width == 0 || height == 0 || !surface) return false; + // setup surface configuration WGPUSurfaceConfiguration surfaceConfiguration { - .device = mContext.device, - .format = mContext.preferredFormat, + .device = context.device, + .format = context.preferredFormat, .usage = WGPUTextureUsage_RenderAttachment, #ifdef __EMSCRIPTEN__ .alphaMode = WGPUCompositeAlphaMode_Premultiplied, #endif - .width = w, .height = h, - #ifdef __EMSCRIPTEN__ + .width = width, + .height = height, + #ifndef __EMSCRIPTEN__ .presentMode = WGPUPresentMode_Fifo, - #else - .presentMode = WGPUPresentMode_Immediate #endif }; wgpuSurfaceConfigure(surface, &surfaceConfiguration); - return true; } @@ -369,7 +414,7 @@ bool WgRenderer::beginComposite(RenderCompositor* cmp, MaskMethod method, uint8_ mRenderStorageStack.push(storage); // begin newly added render pass WGPUColor color{}; - if ((method == MaskMethod::None) && (opacity != 255)) color = {1.0f, 1.0f, 1.0f, 0.0f}; + if ((method == MaskMethod::None) && (opacity != 255)) color = { 1.0, 1.0, 1.0, 0.0 }; mCompositor.beginRenderPass(mCommandEncoder, mRenderStorageStack.last(), true, color); return true; } diff --git a/src/renderer/wg_engine/tvgWgRenderer.h b/src/renderer/wg_engine/tvgWgRenderer.h index 9faa7317..6bb37819 100755 --- a/src/renderer/wg_engine/tvgWgRenderer.h +++ b/src/renderer/wg_engine/tvgWgRenderer.h @@ -45,8 +45,7 @@ public: bool clear() override; bool sync() override; - bool target(WGPUInstance instance, WGPUSurface surface, uint32_t w, uint32_t h, WGPUDevice device); - bool target(WGPUSurface surface, uint32_t w, uint32_t h); + bool target(WGPUDevice device, WGPUInstance instance, void* target, uint32_t width, uint32_t height, int type = 0); RenderCompositor* target(const RenderRegion& region, ColorSpace cs) override; bool beginComposite(RenderCompositor* cmp, MaskMethod method, uint8_t opacity) override; @@ -59,8 +58,6 @@ public: static bool init(uint32_t threads); static bool term(); - WGPUSurface surface{}; // external handle - private: WgRenderer(); ~WgRenderer(); @@ -69,28 +66,37 @@ private: void disposeObjects(); void releaseSurfaceTexture(); - WGPUSurfaceTexture surfaceTexture{}; + void reguestDevice(WGPUInstance instance, WGPUSurface surface); + void releaseDevice(); + void clearTargets(); + bool surfaceConfigure(WGPUSurface surface, WgContext& context, uint32_t width, uint32_t height); - WGPUCommandEncoder mCommandEncoder{}; - WgRenderDataShapePool mRenderDataShapePool; - - // render tree stacks + // render tree stacks and pools WgRenderStorage mStorageRoot; Array mCompositorStack; Array mRenderStorageStack; WgRenderStoragePool mRenderStoragePool; + WgRenderDataShapePool mRenderDataShapePool; + // rendering context WgContext mContext; WgPipelines mPipelines; WgCompositor mCompositor; + // rendering states RenderSurface mTargetSurface; BlendMethod mBlendMethod{}; RenderRegion mViewport{}; + // disposable data list Array mDisposeRenderDatas{}; Key mDisposeKey{}; + // gpu handles + WGPUCommandEncoder mCommandEncoder{}; + WGPUTexture targetTexture{}; // external handle + WGPUSurfaceTexture surfaceTexture{}; + WGPUSurface surface{}; // external handle WGPUAdapter adapter{}; WGPUDevice device{}; bool gpuOwner{};