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.
*/
#include <atomic>
#include "tvgGlCommon.h"
#include "tvgGlRenderer.h"
#include "tvgGlGpuBuffer.h"
@ -33,8 +34,8 @@
#define NOISE_LEVEL 0.5f
static int32_t initEngineCnt = false;
static int32_t rendererCnt = 0;
static atomic<int32_t> initEngineCnt{};
static atomic<int32_t> rendererCnt{};
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;
@ -1301,7 +1302,7 @@ int32_t GlRenderer::init()
}
int GlRenderer::term()
bool GlRenderer::term()
{
if ((--initEngineCnt) > 0) return true;

View file

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

View file

@ -24,6 +24,7 @@
#include <omp.h>
#endif
#include <algorithm>
#include <atomic>
#include "tvgMath.h"
#include "tvgSwCommon.h"
#include "tvgTaskScheduler.h"
@ -32,8 +33,8 @@
/************************************************************************/
/* Internal Class Implementation */
/************************************************************************/
static int32_t initEngineCnt = false;
static int32_t rendererCnt = 0;
static atomic<int32_t> initEngineCnt{};
static atomic<int32_t> rendererCnt{};
static SwMpool* globalMpool = nullptr;
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);
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};
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
{
#ifdef THORVG_WG_RASTER_SUPPORT
if (WgRenderer::init() <= 0) return nullptr;
return new WgCanvas;
#endif
return nullptr;

View file

@ -20,21 +20,23 @@
* SOFTWARE.
*/
#include <atomic>
#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;
WgRenderer::~WgRenderer()
{
release();
}
void WgRenderer::initialize()
{
//TODO:
}
@ -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)
{
// 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()
{
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
this->surface = surface;
if (width == 0 || height == 0 || !surface) return false;
release();
// 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;
--rendererCnt;
if (rendererCnt == 0 && initEngineCnt == 0) _termEngine();
}
@ -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()
{
if ((--initEngineCnt) > 0) return true;
initEngineCnt = 0;
_termEngine();
return true;
}
WgRenderer* WgRenderer::gen()
{
++rendererCnt;
return new WgRenderer();
}

View file

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