mirror of
https://github.com/thorvg/thorvg.git
synced 2025-06-07 21:23:32 +00:00
wg_engine: multicanvas support
Added multicanas support Issue https://github.com/thorvg/thorvg/issues/2745
This commit is contained in:
parent
57fcada8cc
commit
3805f26aff
14 changed files with 181 additions and 126 deletions
|
@ -425,14 +425,14 @@ struct WgWindow : Window
|
||||||
|
|
||||||
virtual ~WgWindow()
|
virtual ~WgWindow()
|
||||||
{
|
{
|
||||||
wgpuSurfaceRelease(surface);
|
//wgpuSurfaceRelease(surface);
|
||||||
wgpuInstanceRelease(instance);
|
wgpuInstanceRelease(instance);
|
||||||
}
|
}
|
||||||
|
|
||||||
void resize() override
|
void resize() override
|
||||||
{
|
{
|
||||||
//Set the canvas target and draw on it.
|
//Set the canvas target and draw on it.
|
||||||
verify(static_cast<tvg::WgCanvas*>(canvas)->target(instance, surface, width, height));
|
verify(static_cast<tvg::WgCanvas*>(canvas)->target(nullptr, instance, surface, width, height));
|
||||||
}
|
}
|
||||||
|
|
||||||
void refresh() override
|
void refresh() override
|
||||||
|
|
13
inc/thorvg.h
13
inc/thorvg.h
|
@ -1774,11 +1774,12 @@ public:
|
||||||
/**
|
/**
|
||||||
* @brief Sets the drawing target for the rasterization.
|
* @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
|
||||||
*
|
*
|
||||||
* @retval Result::InsufficientCondition if the canvas is performing rendering. Please ensure the canvas is synced.
|
* @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.
|
* @retval Result::NonSupport In case the wg engine is not supported.
|
||||||
|
@ -1788,7 +1789,7 @@ public:
|
||||||
* @see Canvas::viewport()
|
* @see Canvas::viewport()
|
||||||
* @see Canvas::sync()
|
* @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.
|
* @brief Creates a new WgCanvas object.
|
||||||
|
@ -2148,4 +2149,4 @@ public:
|
||||||
|
|
||||||
} //namespace
|
} //namespace
|
||||||
|
|
||||||
#endif //_THORVG_H_
|
#endif //_THORVG_H_
|
|
@ -560,11 +560,12 @@ TVG_API Tvg_Canvas* tvg_wgcanvas_create(void);
|
||||||
/*!
|
/*!
|
||||||
* \brief Sets the drawing target for the rasterization.
|
* \brief Sets the drawing target for the rasterization.
|
||||||
*
|
*
|
||||||
* \param[in] instance WGPUInstance, context for all other wgpu objects.
|
* @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] surface WGPUSurface, handle to a presentable surface.
|
* @param[in] instance WGPUInstance, context for all other wgpu objects.
|
||||||
* \param[in] w The width of the surface.
|
* @param[in] target Either WGPUSurface or WGPUTexture, serving as handles to a presentable surface or texture
|
||||||
* \param[in] h The height of the surface.
|
* @param[in] w The width of the target.
|
||||||
* \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] h The height of the target.
|
||||||
|
* @param[in] type 0: surface, 1: texture are used as pesentable target
|
||||||
*
|
*
|
||||||
* \return Tvg_Result enumeration.
|
* \return Tvg_Result enumeration.
|
||||||
* \retval TVG_RESULT_INSUFFICIENT_CONDITION if the canvas is performing rendering. Please ensure the canvas is synced.
|
* \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
|
* \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
|
/** \} */ // end defgroup ThorVGCapi_WgCanvas
|
||||||
|
|
||||||
|
|
|
@ -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;
|
if (!canvas) return TVG_RESULT_INVALID_ARGUMENT;
|
||||||
return (Tvg_Result) reinterpret_cast<WgCanvas*>(canvas)->target(instance, surface, w, h, device);
|
return (Tvg_Result) reinterpret_cast<WgCanvas*>(canvas)->target(device, instance, target, w, h, type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -150,7 +150,7 @@ struct TvgWgEngine : TvgEngineMethod
|
||||||
void resize(Canvas* canvas, int w, int h) override
|
void resize(Canvas* canvas, int w, int h) override
|
||||||
{
|
{
|
||||||
#ifdef THORVG_WG_RASTER_SUPPORT
|
#ifdef THORVG_WG_RASTER_SUPPORT
|
||||||
static_cast<WgCanvas*>(canvas)->target(instance, surface, w, h, device);
|
static_cast<WgCanvas*>(canvas)->target(device, instance, surface, w, h);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -52,25 +52,23 @@ WgCanvas::~WgCanvas()
|
||||||
{
|
{
|
||||||
#ifdef THORVG_WG_RASTER_SUPPORT
|
#ifdef THORVG_WG_RASTER_SUPPORT
|
||||||
auto renderer = static_cast<WgRenderer*>(Canvas::pImpl->renderer);
|
auto renderer = static_cast<WgRenderer*>(Canvas::pImpl->renderer);
|
||||||
renderer->target(nullptr, 0, 0);
|
renderer->target(nullptr, nullptr, nullptr, 0, 0);
|
||||||
#endif
|
#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
|
#ifdef THORVG_WG_RASTER_SUPPORT
|
||||||
if (Canvas::pImpl->status != Status::Damaged && Canvas::pImpl->status != Status::Synced) {
|
if (Canvas::pImpl->status != Status::Damaged && Canvas::pImpl->status != Status::Synced) {
|
||||||
return Result::InsufficientCondition;
|
return Result::InsufficientCondition;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!instance || !surface || (w == 0) || (h == 0)) return Result::InvalidArguments;
|
|
||||||
|
|
||||||
//We know renderer type, avoid dynamic_cast for performance.
|
//We know renderer type, avoid dynamic_cast for performance.
|
||||||
auto renderer = static_cast<WgRenderer*>(Canvas::pImpl->renderer);
|
auto renderer = static_cast<WgRenderer*>(Canvas::pImpl->renderer);
|
||||||
if (!renderer) return Result::MemoryCorruption;
|
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};
|
Canvas::pImpl->vport = {0, 0, (int32_t)w, (int32_t)h};
|
||||||
renderer->viewport(Canvas::pImpl->vport);
|
renderer->viewport(Canvas::pImpl->vport);
|
||||||
|
|
||||||
|
|
|
@ -140,6 +140,12 @@ void WgBindGroupLayouts::releaseBindGroup(WGPUBindGroup& bindGroup)
|
||||||
bindGroup = nullptr;
|
bindGroup = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void WgBindGroupLayouts::releaseBindGroupLayout(WGPUBindGroupLayout& bindGroupLayout)
|
||||||
|
{
|
||||||
|
if (bindGroupLayout) wgpuBindGroupLayoutRelease(bindGroupLayout);
|
||||||
|
bindGroupLayout = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void WgBindGroupLayouts::initialize(WgContext& context)
|
void WgBindGroupLayouts::initialize(WgContext& context)
|
||||||
{
|
{
|
||||||
|
@ -262,14 +268,15 @@ void WgBindGroupLayouts::initialize(WgContext& context)
|
||||||
|
|
||||||
void WgBindGroupLayouts::release(WgContext& context)
|
void WgBindGroupLayouts::release(WgContext& context)
|
||||||
{
|
{
|
||||||
wgpuBindGroupLayoutRelease(layoutBuffer3Un);
|
releaseBindGroupLayout(layoutBuffer3Un);
|
||||||
wgpuBindGroupLayoutRelease(layoutBuffer2Un);
|
releaseBindGroupLayout(layoutBuffer2Un);
|
||||||
wgpuBindGroupLayoutRelease(layoutBuffer1Un);
|
releaseBindGroupLayout(layoutBuffer1Un);
|
||||||
wgpuBindGroupLayoutRelease(layoutTexStrorage3RO);
|
releaseBindGroupLayout(layoutTexStrorage3RO);
|
||||||
wgpuBindGroupLayoutRelease(layoutTexStrorage2RO);
|
releaseBindGroupLayout(layoutTexStrorage2RO);
|
||||||
wgpuBindGroupLayoutRelease(layoutTexStrorage1RO);
|
releaseBindGroupLayout(layoutTexStrorage1RO);
|
||||||
wgpuBindGroupLayoutRelease(layoutTexStrorage1WO);
|
releaseBindGroupLayout(layoutTexStrorage1WO);
|
||||||
wgpuBindGroupLayoutRelease(layoutTexSampledBuff1Un);
|
releaseBindGroupLayout(layoutTexSampledBuff1Un);
|
||||||
wgpuBindGroupLayoutRelease(layoutTexSampled);
|
releaseBindGroupLayout(layoutTexSampledBuff2Un);
|
||||||
|
releaseBindGroupLayout(layoutTexSampled);
|
||||||
device = nullptr;
|
device = nullptr;
|
||||||
}
|
}
|
||||||
|
|
|
@ -51,6 +51,7 @@ public:
|
||||||
WGPUBindGroup createBindGroupBuffer2Un(WGPUBuffer buff0, WGPUBuffer buff1);
|
WGPUBindGroup createBindGroupBuffer2Un(WGPUBuffer buff0, WGPUBuffer buff1);
|
||||||
WGPUBindGroup createBindGroupBuffer3Un(WGPUBuffer buff0, WGPUBuffer buff1, WGPUBuffer buff2);
|
WGPUBindGroup createBindGroupBuffer3Un(WGPUBuffer buff0, WGPUBuffer buff1, WGPUBuffer buff2);
|
||||||
void releaseBindGroup(WGPUBindGroup& bindGroup);
|
void releaseBindGroup(WGPUBindGroup& bindGroup);
|
||||||
|
void releaseBindGroupLayout(WGPUBindGroupLayout& bindGroupLayout);
|
||||||
public:
|
public:
|
||||||
void initialize(WgContext& context);
|
void initialize(WgContext& context);
|
||||||
void release(WgContext& context);
|
void release(WgContext& context);
|
||||||
|
|
|
@ -260,7 +260,7 @@ void WgContext::releaseBuffer(WGPUBuffer& buffer)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void WgContext::releaseQueue(WGPUQueue queue)
|
void WgContext::releaseQueue(WGPUQueue& queue)
|
||||||
{
|
{
|
||||||
if (queue) {
|
if (queue) {
|
||||||
wgpuQueueRelease(queue);
|
wgpuQueueRelease(queue);
|
||||||
|
|
|
@ -63,7 +63,7 @@ struct WgContext {
|
||||||
void releaseTextureView(WGPUTextureView& textureView);
|
void releaseTextureView(WGPUTextureView& textureView);
|
||||||
void releaseTexture(WGPUTexture& texture);
|
void releaseTexture(WGPUTexture& texture);
|
||||||
void releaseSampler(WGPUSampler& sampler);
|
void releaseSampler(WGPUSampler& sampler);
|
||||||
void releaseQueue(WGPUQueue queue);
|
void releaseQueue(WGPUQueue& queue);
|
||||||
|
|
||||||
// create buffer objects (return true, if buffer handle was changed)
|
// create buffer objects (return true, if buffer handle was changed)
|
||||||
bool allocateBufferUniform(WGPUBuffer& buffer, const void* data, uint64_t size);
|
bool allocateBufferUniform(WGPUBuffer& buffer, const void* data, uint64_t size);
|
||||||
|
|
|
@ -165,7 +165,8 @@ void WgMeshDataPool::release(WgContext& context)
|
||||||
mList.clear();
|
mList.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
WgMeshDataPool* WgMeshDataGroup::gMeshDataPool = nullptr;
|
WgMeshDataPool gMeshDataPoolInstance;
|
||||||
|
WgMeshDataPool* WgMeshDataPool::gMeshDataPool = &gMeshDataPoolInstance;
|
||||||
|
|
||||||
//***********************************************************************
|
//***********************************************************************
|
||||||
// WgMeshDataGroup
|
// WgMeshDataGroup
|
||||||
|
@ -174,7 +175,7 @@ WgMeshDataPool* WgMeshDataGroup::gMeshDataPool = nullptr;
|
||||||
void WgMeshDataGroup::append(WgContext& context, const WgVertexBuffer& vertexBuffer)
|
void WgMeshDataGroup::append(WgContext& context, const WgVertexBuffer& vertexBuffer)
|
||||||
{
|
{
|
||||||
assert(vertexBuffer.vcount >= 3);
|
assert(vertexBuffer.vcount >= 3);
|
||||||
meshes.push(gMeshDataPool->allocate(context));
|
meshes.push(WgMeshDataPool::gMeshDataPool->allocate(context));
|
||||||
meshes.last()->update(context, vertexBuffer);
|
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)
|
void WgMeshDataGroup::append(WgContext& context, const WgVertexBufferInd& vertexBufferInd)
|
||||||
{
|
{
|
||||||
assert(vertexBufferInd.vcount >= 3);
|
assert(vertexBufferInd.vcount >= 3);
|
||||||
meshes.push(gMeshDataPool->allocate(context));
|
meshes.push(WgMeshDataPool::gMeshDataPool->allocate(context));
|
||||||
meshes.last()->update(context, vertexBufferInd);
|
meshes.last()->update(context, vertexBufferInd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void WgMeshDataGroup::append(WgContext& context, const Point pmin, const Point pmax)
|
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);
|
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)
|
void WgMeshDataGroup::release(WgContext& context)
|
||||||
{
|
{
|
||||||
for (uint32_t i = 0; i < meshes.count; i++)
|
for (uint32_t i = 0; i < meshes.count; i++)
|
||||||
gMeshDataPool->free(context, meshes[i]);
|
WgMeshDataPool::gMeshDataPool->free(context, meshes[i]);
|
||||||
meshes.clear();
|
meshes.clear();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -298,8 +299,6 @@ void WgRenderSettings::release(WgContext& context)
|
||||||
// WgRenderDataPaint
|
// WgRenderDataPaint
|
||||||
//***********************************************************************
|
//***********************************************************************
|
||||||
|
|
||||||
WgVertexBufferInd* WgRenderDataPaint::gStrokesGenerator = nullptr;
|
|
||||||
|
|
||||||
void WgRenderDataPaint::release(WgContext& context)
|
void WgRenderDataPaint::release(WgContext& context)
|
||||||
{
|
{
|
||||||
context.pipelines->layouts.releaseBindGroup(bindGroupPaint);
|
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)
|
void WgRenderDataShape::proceedStrokes(WgContext context, const RenderStroke* rstroke, float tbeg, float tend, const WgVertexBuffer& buff)
|
||||||
{
|
{
|
||||||
assert(rstroke);
|
assert(rstroke);
|
||||||
gStrokesGenerator->reset(buff.tscale);
|
static WgVertexBufferInd strokesGenerator;
|
||||||
|
strokesGenerator.reset(buff.tscale);
|
||||||
// trim -> dash -> stroke
|
// trim -> dash -> stroke
|
||||||
if ((tbeg != 0.0f) || (tend != 1.0f)) {
|
if ((tbeg != 0.0f) || (tend != 1.0f)) {
|
||||||
if (tbeg == tend) return;
|
if (tbeg == tend) return;
|
||||||
|
@ -464,17 +464,17 @@ void WgRenderDataShape::proceedStrokes(WgContext context, const RenderStroke* rs
|
||||||
trimed_buff.trim(buff, tbeg, tend);
|
trimed_buff.trim(buff, tbeg, tend);
|
||||||
trimed_buff.updateDistances();
|
trimed_buff.updateDistances();
|
||||||
// trim ->dash -> stroke
|
// trim ->dash -> stroke
|
||||||
if (rstroke->dashPattern) gStrokesGenerator->appendStrokesDashed(trimed_buff, rstroke);
|
if (rstroke->dashPattern) strokesGenerator.appendStrokesDashed(trimed_buff, rstroke);
|
||||||
// trim -> stroke
|
// trim -> stroke
|
||||||
else gStrokesGenerator->appendStrokes(trimed_buff, rstroke);
|
else strokesGenerator.appendStrokes(trimed_buff, rstroke);
|
||||||
} else
|
} else
|
||||||
// dash -> stroke
|
// dash -> stroke
|
||||||
if (rstroke->dashPattern) {
|
if (rstroke->dashPattern) {
|
||||||
gStrokesGenerator->appendStrokesDashed(buff, rstroke);
|
strokesGenerator.appendStrokesDashed(buff, rstroke);
|
||||||
// stroke
|
// stroke
|
||||||
} else
|
} else
|
||||||
gStrokesGenerator->appendStrokes(buff, rstroke);
|
strokesGenerator.appendStrokes(buff, rstroke);
|
||||||
appendStroke(context, *gStrokesGenerator);
|
appendStroke(context, strokesGenerator);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -50,14 +50,13 @@ private:
|
||||||
Array<WgMeshData*> mPool;
|
Array<WgMeshData*> mPool;
|
||||||
Array<WgMeshData*> mList;
|
Array<WgMeshData*> mList;
|
||||||
public:
|
public:
|
||||||
|
static WgMeshDataPool* gMeshDataPool;
|
||||||
WgMeshData* allocate(WgContext& context);
|
WgMeshData* allocate(WgContext& context);
|
||||||
void free(WgContext& context, WgMeshData* meshData);
|
void free(WgContext& context, WgMeshData* meshData);
|
||||||
void release(WgContext& context);
|
void release(WgContext& context);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct WgMeshDataGroup {
|
struct WgMeshDataGroup {
|
||||||
static WgMeshDataPool* gMeshDataPool;
|
|
||||||
|
|
||||||
Array<WgMeshData*> meshes{};
|
Array<WgMeshData*> meshes{};
|
||||||
|
|
||||||
void append(WgContext& context, const WgVertexBuffer& vertexBuffer);
|
void append(WgContext& context, const WgVertexBuffer& vertexBuffer);
|
||||||
|
@ -96,9 +95,6 @@ struct WgRenderSettings
|
||||||
|
|
||||||
struct WgRenderDataPaint
|
struct WgRenderDataPaint
|
||||||
{
|
{
|
||||||
// global strokes generator. single instance
|
|
||||||
static WgVertexBufferInd* gStrokesGenerator;
|
|
||||||
|
|
||||||
WGPUBuffer bufferModelMat{};
|
WGPUBuffer bufferModelMat{};
|
||||||
WGPUBuffer bufferBlendSettings{};
|
WGPUBuffer bufferBlendSettings{};
|
||||||
WGPUBindGroup bindGroupPaint{};
|
WGPUBindGroup bindGroupPaint{};
|
||||||
|
|
|
@ -30,47 +30,45 @@ WgRenderer::WgRenderer()
|
||||||
WgRenderer::~WgRenderer()
|
WgRenderer::~WgRenderer()
|
||||||
{
|
{
|
||||||
release();
|
release();
|
||||||
mContext.release();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void WgRenderer::initialize()
|
void WgRenderer::initialize()
|
||||||
{
|
{
|
||||||
mPipelines.initialize(mContext);
|
|
||||||
WgMeshDataGroup::gMeshDataPool = new WgMeshDataPool();
|
|
||||||
WgRenderDataShape::gStrokesGenerator = new WgVertexBufferInd();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void WgRenderer::release()
|
void WgRenderer::release()
|
||||||
{
|
{
|
||||||
|
// check for general context availability
|
||||||
|
if (!mContext.queue) return;
|
||||||
|
|
||||||
|
// dispose stored objects
|
||||||
disposeObjects();
|
disposeObjects();
|
||||||
mStorageRoot.release(mContext);
|
|
||||||
mRenderStoragePool.release(mContext);
|
// clear rendering tree stacks
|
||||||
mRenderDataShapePool.release(mContext);
|
|
||||||
delete WgRenderDataShape::gStrokesGenerator;
|
|
||||||
WgMeshDataGroup::gMeshDataPool->release(mContext);
|
|
||||||
delete WgMeshDataGroup::gMeshDataPool;
|
|
||||||
mCompositorStack.clear();
|
mCompositorStack.clear();
|
||||||
mRenderStorageStack.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);
|
mPipelines.release(mContext);
|
||||||
if (gpuOwner) {
|
mContext.release();
|
||||||
if (device) wgpuDeviceRelease(device);
|
|
||||||
device = nullptr;
|
// release gpu handles
|
||||||
if (adapter) wgpuAdapterRelease(adapter);
|
clearTargets();
|
||||||
adapter = nullptr;
|
releaseDevice();
|
||||||
gpuOwner = false;
|
|
||||||
}
|
|
||||||
releaseSurfaceTexture();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void WgRenderer::disposeObjects()
|
void WgRenderer::disposeObjects()
|
||||||
{
|
{
|
||||||
if (mDisposeRenderDatas.count == 0) return;
|
for (uint32_t i = 0; i < mDisposeRenderDatas.count; i++) {
|
||||||
|
WgRenderDataPaint* renderData = (WgRenderDataPaint*)mDisposeRenderDatas[i];
|
||||||
for (auto p = mDisposeRenderDatas.begin(); p < mDisposeRenderDatas.end(); p++) {
|
|
||||||
auto renderData = (WgRenderDataPaint*)(*p);
|
|
||||||
if (renderData->type() == Type::Shape) {
|
if (renderData->type() == Type::Shape) {
|
||||||
mRenderDataShapePool.free(mContext, (WgRenderDataShape*)renderData);
|
mRenderDataShapePool.free(mContext, (WgRenderDataShape*)renderData);
|
||||||
} else {
|
} else {
|
||||||
|
@ -260,20 +258,26 @@ void WgRenderer::releaseSurfaceTexture()
|
||||||
bool WgRenderer::sync()
|
bool WgRenderer::sync()
|
||||||
{
|
{
|
||||||
disposeObjects();
|
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);
|
// get external dest buffer
|
||||||
|
WGPUTextureView dstTextureView = mContext.createTextureView(dstTexture);
|
||||||
WGPUTextureView dstView = mContext.createTextureView(surfaceTexture.texture);
|
|
||||||
|
|
||||||
// create command encoder
|
// create command encoder
|
||||||
const WGPUCommandEncoderDescriptor commandEncoderDesc{};
|
const WGPUCommandEncoderDescriptor commandEncoderDesc{};
|
||||||
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, dstView);
|
mCompositor.blit(mContext, commandEncoder, &mStorageRoot, dstTextureView);
|
||||||
|
|
||||||
// release command encoder
|
// release command encoder
|
||||||
const WGPUCommandBufferDescriptor commandBufferDesc{};
|
const WGPUCommandBufferDescriptor commandBufferDesc{};
|
||||||
|
@ -281,68 +285,109 @@ bool WgRenderer::sync()
|
||||||
wgpuQueueSubmit(mContext.queue, 1, &commandsBuffer);
|
wgpuQueueSubmit(mContext.queue, 1, &commandsBuffer);
|
||||||
wgpuCommandBufferRelease(commandsBuffer);
|
wgpuCommandBufferRelease(commandsBuffer);
|
||||||
wgpuCommandEncoderRelease(commandEncoder);
|
wgpuCommandEncoderRelease(commandEncoder);
|
||||||
mContext.releaseTextureView(dstView);
|
|
||||||
|
|
||||||
|
// release dest buffer view
|
||||||
|
mContext.releaseTextureView(dstTextureView);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// target for native window handle
|
// render target handle
|
||||||
bool WgRenderer::target(WGPUInstance instance, WGPUSurface surface, uint32_t w, uint32_t h, WGPUDevice device)
|
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;
|
this->device = device;
|
||||||
if (!this->device) {
|
if (!this->device)
|
||||||
// request adapter
|
reguestDevice(instance, (WGPUSurface)target);
|
||||||
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);
|
|
||||||
|
|
||||||
// get adapter and surface properties
|
// store target properties
|
||||||
WGPUFeatureName featureNames[32]{};
|
mTargetSurface.stride = width;
|
||||||
size_t featuresCount = wgpuAdapterEnumerateFeatures(this->adapter, featureNames);
|
mTargetSurface.w = width;
|
||||||
|
mTargetSurface.h = height;
|
||||||
// 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
// initialize rendering context
|
||||||
mContext.initialize(instance, this->device);
|
mContext.initialize(instance, this->device);
|
||||||
initialize();
|
mPipelines.initialize(mContext);
|
||||||
target(surface, w, h);
|
|
||||||
mRenderStoragePool.initialize(mContext, w, h);
|
// initialize render tree instances
|
||||||
mStorageRoot.initialize(mContext, w, h);
|
mRenderStoragePool.initialize(mContext, width, height);
|
||||||
mCompositor.initialize(mContext, w, h);
|
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;
|
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
|
// store target surface properties
|
||||||
this->surface = surface;
|
this->surface = surface;
|
||||||
mTargetSurface.stride = w;
|
if (width == 0 || height == 0 || !surface) return false;
|
||||||
mTargetSurface.w = w;
|
|
||||||
mTargetSurface.h = h;
|
|
||||||
if (w == 0 || h == 0) return false;
|
|
||||||
if (!surface) return true;
|
|
||||||
|
|
||||||
|
// setup surface configuration
|
||||||
WGPUSurfaceConfiguration surfaceConfiguration {
|
WGPUSurfaceConfiguration surfaceConfiguration {
|
||||||
.device = mContext.device,
|
.device = context.device,
|
||||||
.format = mContext.preferredFormat,
|
.format = context.preferredFormat,
|
||||||
.usage = WGPUTextureUsage_RenderAttachment,
|
.usage = WGPUTextureUsage_RenderAttachment,
|
||||||
#ifdef __EMSCRIPTEN__
|
#ifdef __EMSCRIPTEN__
|
||||||
.alphaMode = WGPUCompositeAlphaMode_Premultiplied,
|
.alphaMode = WGPUCompositeAlphaMode_Premultiplied,
|
||||||
#endif
|
#endif
|
||||||
.width = w, .height = h,
|
.width = width,
|
||||||
#ifdef __EMSCRIPTEN__
|
.height = height,
|
||||||
|
#ifndef __EMSCRIPTEN__
|
||||||
.presentMode = WGPUPresentMode_Fifo,
|
.presentMode = WGPUPresentMode_Fifo,
|
||||||
#else
|
|
||||||
.presentMode = WGPUPresentMode_Immediate
|
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
wgpuSurfaceConfigure(surface, &surfaceConfiguration);
|
wgpuSurfaceConfigure(surface, &surfaceConfiguration);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -369,7 +414,7 @@ bool WgRenderer::beginComposite(RenderCompositor* cmp, MaskMethod method, uint8_
|
||||||
mRenderStorageStack.push(storage);
|
mRenderStorageStack.push(storage);
|
||||||
// begin newly added render pass
|
// begin newly added render pass
|
||||||
WGPUColor color{};
|
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);
|
mCompositor.beginRenderPass(mCommandEncoder, mRenderStorageStack.last(), true, color);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -45,8 +45,7 @@ public:
|
||||||
bool clear() override;
|
bool clear() override;
|
||||||
bool sync() override;
|
bool sync() override;
|
||||||
|
|
||||||
bool target(WGPUInstance instance, WGPUSurface surface, uint32_t w, uint32_t h, WGPUDevice device);
|
bool target(WGPUDevice device, WGPUInstance instance, void* target, uint32_t width, uint32_t height, int type = 0);
|
||||||
bool target(WGPUSurface surface, uint32_t w, uint32_t h);
|
|
||||||
|
|
||||||
RenderCompositor* target(const RenderRegion& region, ColorSpace cs) override;
|
RenderCompositor* target(const RenderRegion& region, ColorSpace cs) override;
|
||||||
bool beginComposite(RenderCompositor* cmp, MaskMethod method, uint8_t opacity) override;
|
bool beginComposite(RenderCompositor* cmp, MaskMethod method, uint8_t opacity) override;
|
||||||
|
@ -59,8 +58,6 @@ public:
|
||||||
static bool init(uint32_t threads);
|
static bool init(uint32_t threads);
|
||||||
static bool term();
|
static bool term();
|
||||||
|
|
||||||
WGPUSurface surface{}; // external handle
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
WgRenderer();
|
WgRenderer();
|
||||||
~WgRenderer();
|
~WgRenderer();
|
||||||
|
@ -69,28 +66,37 @@ private:
|
||||||
void disposeObjects();
|
void disposeObjects();
|
||||||
void releaseSurfaceTexture();
|
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{};
|
// render tree stacks and pools
|
||||||
WgRenderDataShapePool mRenderDataShapePool;
|
|
||||||
|
|
||||||
// render tree stacks
|
|
||||||
WgRenderStorage mStorageRoot;
|
WgRenderStorage mStorageRoot;
|
||||||
Array<WgCompose*> mCompositorStack;
|
Array<WgCompose*> mCompositorStack;
|
||||||
Array<WgRenderStorage*> mRenderStorageStack;
|
Array<WgRenderStorage*> mRenderStorageStack;
|
||||||
WgRenderStoragePool mRenderStoragePool;
|
WgRenderStoragePool mRenderStoragePool;
|
||||||
|
WgRenderDataShapePool mRenderDataShapePool;
|
||||||
|
|
||||||
|
// rendering context
|
||||||
WgContext mContext;
|
WgContext mContext;
|
||||||
WgPipelines mPipelines;
|
WgPipelines mPipelines;
|
||||||
WgCompositor mCompositor;
|
WgCompositor mCompositor;
|
||||||
|
|
||||||
|
// rendering states
|
||||||
RenderSurface mTargetSurface;
|
RenderSurface mTargetSurface;
|
||||||
BlendMethod mBlendMethod{};
|
BlendMethod mBlendMethod{};
|
||||||
RenderRegion mViewport{};
|
RenderRegion mViewport{};
|
||||||
|
|
||||||
|
// disposable data list
|
||||||
Array<RenderData> mDisposeRenderDatas{};
|
Array<RenderData> mDisposeRenderDatas{};
|
||||||
Key mDisposeKey{};
|
Key mDisposeKey{};
|
||||||
|
|
||||||
|
// gpu handles
|
||||||
|
WGPUCommandEncoder mCommandEncoder{};
|
||||||
|
WGPUTexture targetTexture{}; // external handle
|
||||||
|
WGPUSurfaceTexture surfaceTexture{};
|
||||||
|
WGPUSurface surface{}; // external handle
|
||||||
WGPUAdapter adapter{};
|
WGPUAdapter adapter{};
|
||||||
WGPUDevice device{};
|
WGPUDevice device{};
|
||||||
bool gpuOwner{};
|
bool gpuOwner{};
|
||||||
|
|
Loading…
Add table
Reference in a new issue