sw/gl/wg: ++threads safety

Considered global engine initialization and termination.
Engines could be used among multiple worker threads.
This commit is contained in:
Hermet Park 2025-02-11 16:14:59 +09:00 committed by Hermet Park
parent f64fb088b4
commit 3c25623ee9
7 changed files with 105 additions and 63 deletions

View file

@ -20,6 +20,7 @@
* SOFTWARE. * SOFTWARE.
*/ */
#include <atomic>
#include "tvgGlCommon.h" #include "tvgGlCommon.h"
#include "tvgGlRenderer.h" #include "tvgGlRenderer.h"
#include "tvgGlGpuBuffer.h" #include "tvgGlGpuBuffer.h"
@ -33,8 +34,8 @@
#define NOISE_LEVEL 0.5f #define NOISE_LEVEL 0.5f
static int32_t initEngineCnt = false; static atomic<int32_t> initEngineCnt{};
static int32_t rendererCnt = 0; static atomic<int32_t> rendererCnt{};
static void _termEngine() static void _termEngine()
@ -1285,7 +1286,7 @@ bool GlRenderer::postUpdate()
} }
int GlRenderer::init(uint32_t threads) bool GlRenderer::init(uint32_t threads)
{ {
if ((initEngineCnt++) > 0) return true; if ((initEngineCnt++) > 0) return true;
@ -1301,7 +1302,7 @@ int32_t GlRenderer::init()
} }
int GlRenderer::term() bool GlRenderer::term()
{ {
if ((--initEngineCnt) > 0) return true; if ((--initEngineCnt) > 0) return true;

View file

@ -93,9 +93,9 @@ public:
void dispose(TVG_UNUSED RenderEffect* effect) override; void dispose(TVG_UNUSED RenderEffect* effect) override;
static GlRenderer* gen(); static GlRenderer* gen();
static int init(TVG_UNUSED uint32_t threads); static bool init(TVG_UNUSED uint32_t threads);
static int32_t init(); static int32_t init();
static int term(); static bool term();
private: private:
GlRenderer(); GlRenderer();

View file

@ -24,6 +24,7 @@
#include <omp.h> #include <omp.h>
#endif #endif
#include <algorithm> #include <algorithm>
#include <atomic>
#include "tvgMath.h" #include "tvgMath.h"
#include "tvgSwCommon.h" #include "tvgSwCommon.h"
#include "tvgTaskScheduler.h" #include "tvgTaskScheduler.h"
@ -32,8 +33,8 @@
/************************************************************************/ /************************************************************************/
/* Internal Class Implementation */ /* Internal Class Implementation */
/************************************************************************/ /************************************************************************/
static int32_t initEngineCnt = false; static atomic<int32_t> initEngineCnt{};
static int32_t rendererCnt = 0; static atomic<int32_t> rendererCnt{};
static SwMpool* globalMpool = nullptr; static SwMpool* globalMpool = nullptr;
static uint32_t threadsCnt = 0; static uint32_t threadsCnt = 0;

View file

@ -76,7 +76,7 @@ Result SwCanvas::target(uint32_t* buffer, uint32_t stride, uint32_t w, uint32_t
auto renderer = static_cast<SwRenderer*>(pImpl->renderer); auto renderer = static_cast<SwRenderer*>(pImpl->renderer);
if (!renderer) return Result::MemoryCorruption; if (!renderer) return Result::MemoryCorruption;
if (!renderer->target(buffer, stride, w, h, static_cast<ColorSpace>(cs))) return Result::InvalidArguments; if (!renderer->target(buffer, stride, w, h, cs)) return Result::InvalidArguments;
pImpl->vport = {0, 0, (int32_t)w, (int32_t)h}; pImpl->vport = {0, 0, (int32_t)w, (int32_t)h};
renderer->viewport(pImpl->vport); renderer->viewport(pImpl->vport);

View file

@ -74,6 +74,7 @@ Result WgCanvas::target(void* device, void* instance, void* target, uint32_t w,
WgCanvas* WgCanvas::gen() noexcept WgCanvas* WgCanvas::gen() noexcept
{ {
#ifdef THORVG_WG_RASTER_SUPPORT #ifdef THORVG_WG_RASTER_SUPPORT
if (WgRenderer::init() <= 0) return nullptr;
return new WgCanvas; return new WgCanvas;
#endif #endif
return nullptr; return nullptr;

View file

@ -20,21 +20,23 @@
* SOFTWARE. * SOFTWARE.
*/ */
#include <atomic>
#include "tvgWgRenderer.h" #include "tvgWgRenderer.h"
WgRenderer::WgRenderer()
/************************************************************************/
/* Internal Class Implementation */
/************************************************************************/
static atomic<int32_t> initEngineCnt{};
static atomic<int32_t> rendererCnt{};
static void _termEngine()
{ {
} if (rendererCnt > 0) return;
//TODO:
WgRenderer::~WgRenderer()
{
release();
}
void WgRenderer::initialize()
{
} }
@ -84,6 +86,58 @@ void WgRenderer::disposeObjects()
} }
void WgRenderer::releaseSurfaceTexture()
{
if (surfaceTexture.texture) {
wgpuTextureRelease(surfaceTexture.texture);
surfaceTexture.texture = nullptr;
}
}
void WgRenderer::clearTargets()
{
releaseSurfaceTexture();
if (surface) wgpuSurfaceUnconfigure(surface);
targetTexture = nullptr;
surface = nullptr;
mTargetSurface.stride = 0;
mTargetSurface.w = 0;
mTargetSurface.h = 0;
}
bool WgRenderer::surfaceConfigure(WGPUSurface surface, WgContext& context, uint32_t width, uint32_t height)
{
// store target surface properties
this->surface = surface;
if (width == 0 || height == 0 || !surface) return false;
// setup surface configuration
WGPUSurfaceConfiguration surfaceConfiguration {
.device = context.device,
.format = context.preferredFormat,
.usage = WGPUTextureUsage_RenderAttachment,
#ifdef __EMSCRIPTEN__
.alphaMode = WGPUCompositeAlphaMode_Premultiplied,
#endif
.width = width,
.height = height,
#ifndef __EMSCRIPTEN__
.presentMode = WGPUPresentMode_Fifo,
#endif
};
wgpuSurfaceConfigure(surface, &surfaceConfiguration);
return true;
}
/************************************************************************/
/* External Class Implementation */
/************************************************************************/
RenderData WgRenderer::prepare(const RenderShape& rshape, RenderData data, const Matrix& transform, Array<RenderData>& clips, uint8_t opacity, RenderUpdateFlag flags, bool clipper) RenderData WgRenderer::prepare(const RenderShape& rshape, RenderData data, const Matrix& transform, Array<RenderData>& clips, uint8_t opacity, RenderUpdateFlag flags, bool clipper)
{ {
// get or create render data shape // get or create render data shape
@ -254,15 +308,6 @@ bool WgRenderer::clear()
} }
void WgRenderer::releaseSurfaceTexture()
{
if (surfaceTexture.texture) {
wgpuTextureRelease(surfaceTexture.texture);
surfaceTexture.texture = nullptr;
}
}
bool WgRenderer::sync() bool WgRenderer::sync()
{ {
disposeObjects(); disposeObjects();
@ -368,41 +413,18 @@ bool WgRenderer::target(WGPUDevice device, WGPUInstance instance, void* target,
} }
void WgRenderer::clearTargets() WgRenderer::WgRenderer()
{ {
releaseSurfaceTexture();
if (surface) wgpuSurfaceUnconfigure(surface);
targetTexture = nullptr;
surface = nullptr;
mTargetSurface.stride = 0;
mTargetSurface.w = 0;
mTargetSurface.h = 0;
} }
bool WgRenderer::surfaceConfigure(WGPUSurface surface, WgContext& context, uint32_t width, uint32_t height) WgRenderer::~WgRenderer()
{ {
// store target surface properties release();
this->surface = surface;
if (width == 0 || height == 0 || !surface) return false;
// setup surface configuration --rendererCnt;
WGPUSurfaceConfiguration surfaceConfiguration {
.device = context.device, if (rendererCnt == 0 && initEngineCnt == 0) _termEngine();
.format = context.preferredFormat,
.usage = WGPUTextureUsage_RenderAttachment,
#ifdef __EMSCRIPTEN__
.alphaMode = WGPUCompositeAlphaMode_Premultiplied,
#endif
.width = width,
.height = height,
#ifndef __EMSCRIPTEN__
.presentMode = WGPUPresentMode_Fifo,
#endif
};
wgpuSurfaceConfigure(surface, &surfaceConfiguration);
return true;
} }
@ -559,19 +581,36 @@ bool WgRenderer::postUpdate()
} }
WgRenderer* WgRenderer::gen() bool WgRenderer::init(TVG_UNUSED uint32_t threads)
{ {
return new WgRenderer(); if ((initEngineCnt++) > 0) return true;
//TODO: global engine init
return true;
} }
bool WgRenderer::init(TVG_UNUSED uint32_t threads) int32_t WgRenderer::init()
{ {
return true; return initEngineCnt;
} }
bool WgRenderer::term() bool WgRenderer::term()
{ {
if ((--initEngineCnt) > 0) return true;
initEngineCnt = 0;
_termEngine();
return true; return true;
} }
WgRenderer* WgRenderer::gen()
{
++rendererCnt;
return new WgRenderer();
}

View file

@ -60,12 +60,12 @@ public:
static WgRenderer* gen(); static WgRenderer* gen();
static bool init(uint32_t threads); static bool init(uint32_t threads);
static int32_t init();
static bool term(); static bool term();
private: private:
WgRenderer(); WgRenderer();
~WgRenderer(); ~WgRenderer();
void initialize();
void release(); void release();
void disposeObjects(); void disposeObjects();
void releaseSurfaceTexture(); void releaseSurfaceTexture();