From 8d5c728119692047c13e4be28091e78bd9e83542 Mon Sep 17 00:00:00 2001 From: SergeyLebedkin Date: Fri, 13 Oct 2023 16:59:32 +0300 Subject: [PATCH] wg_engine: introduce a webgpu canvas(engine) WebGPU is a Render Hardware Interface built on top of the various APIs provided by the driver/OS depending on your platform. WebGPU exposes an API for performing operations, such as rendering and computation, on a Graphics Processing Unit. WebGPU official documentation: https://www.w3.org/TR/webgpu/ The new engine type introduced: tvg::CanvasEngine::Wg The new canvas type introduced: tvg::WgCanvas Example: $meson setup build -Dengines=wg_beta ` // init engine webgpu tvg::Initializer::init(tvg::CanvasEngine::Wg, 0); // create wg canvas auto canvasWg = tvg::WgCanvas::gen(); canvas_wg->target(glfwGetWin32Window(window), width, height); // ... // terminate engine and window tvg::Initializer::term(tvg::CanvasEngine::Wg); ` Still this feature is under the beta Issue: https://github.com/thorvg/thorvg/issues/1479 --- inc/thorvg.h | 39 ++++++- meson.build | 34 +++--- meson_options.txt | 2 +- src/renderer/meson.build | 4 + src/renderer/tvgInitializer.cpp | 14 +++ src/renderer/tvgWgCanvas.cpp | 78 ++++++++++++++ src/renderer/wg_engine/meson.build | 8 ++ src/renderer/wg_engine/tvgWgRenderer.cpp | 127 +++++++++++++++++++++++ src/renderer/wg_engine/tvgWgRenderer.h | 64 ++++++++++++ 9 files changed, 354 insertions(+), 16 deletions(-) create mode 100644 src/renderer/tvgWgCanvas.cpp create mode 100644 src/renderer/wg_engine/meson.build create mode 100644 src/renderer/wg_engine/tvgWgRenderer.cpp create mode 100644 src/renderer/wg_engine/tvgWgRenderer.h diff --git a/inc/thorvg.h b/inc/thorvg.h index 1b9c2d70..576f94a4 100644 --- a/inc/thorvg.h +++ b/inc/thorvg.h @@ -213,7 +213,8 @@ enum class BlendMethod : uint8_t enum class CanvasEngine { Sw = (1 << 1), ///< CPU rasterizer. - Gl = (1 << 2) ///< OpenGL rasterizer. + Gl = (1 << 2), ///< OpenGL rasterizer. + Wg = (1 << 3), ///< WebGPU rasterizer. @BETA_API }; @@ -1593,6 +1594,42 @@ public: }; +/** + * @class WgCanvas + * + * @brief A class for the rendering graphic elements with a WebGPU raster engine. + * + * @warning Please do not use it. This class is not fully supported yet. + * + * @BETA_API + */ +class TVG_API WgCanvas final : public Canvas +{ +public: + ~WgCanvas(); + + /** + * @brief Sets the target window for the rasterization. + * + * @warning Please do not use it, this API is not official one. It could be modified in the next version. + * + * @BETA_API + */ + Result target(void* window, uint32_t w, uint32_t h) noexcept; + + /** + * @brief Creates a new WgCanvas object. + * + * @return A new WgCanvas object. + * + * @BETA_API + */ + static std::unique_ptr gen() noexcept; + + _TVG_DECLARE_PRIVATE(WgCanvas); +}; + + /** * @class Initializer * diff --git a/meson.build b/meson.build index 884da3ae..cd3d3e89 100644 --- a/meson.build +++ b/meson.build @@ -22,6 +22,10 @@ if get_option('engines').contains('gl_beta') == true config_h.set10('THORVG_GL_RASTER_SUPPORT', true) endif +if get_option('engines').contains('wg_beta') == true + config_h.set10('THORVG_WG_RASTER_SUPPORT', true) +endif + #Loaders all_loaders = false @@ -124,20 +128,21 @@ Summary: SIMD Instruction: @3@ Raster Engine (SW): @4@ Raster Engine (GL): @5@ - Loader (TVG): @6@ - Loader (SVG): @7@ - Loader (PNG): @8@ - Loader (JPG): @9@ - Loader (WEBP_BETA): @10@ - Loader (LOTTIE): @11@ - Saver (TVG): @12@ - Binding (CAPI): @13@ - Binding (WASM_BETA): @14@ - Log Message: @15@ - Tests: @16@ - Examples: @17@ - Tool (Svg2Tvg): @18@ - Tool (Svg2Png): @19@ + Raster Engine (WG): @6@ + Loader (TVG): @7@ + Loader (SVG): @8@ + Loader (PNG): @9@ + Loader (JPG): @10@ + Loader (WEBP_BETA): @11@ + Loader (LOTTIE): @12@ + Saver (TVG): @13@ + Binding (CAPI): @14@ + Binding (WASM_BETA): @15@ + Log Message: @16@ + Tests: @17@ + Examples: @18@ + Tool (Svg2Tvg): @19@ + Tool (Svg2Png): @20@ '''.format( meson.project_version(), @@ -146,6 +151,7 @@ Summary: simd_type, get_option('engines').contains('sw'), get_option('engines').contains('gl_beta'), + get_option('engines').contains('wg_beta'), all_loaders or get_option('loaders').contains('tvg'), all_loaders or get_option('loaders').contains('svg'), all_loaders or get_option('loaders').contains('png'), diff --git a/meson_options.txt b/meson_options.txt index 1059e95d..331e9b63 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -1,6 +1,6 @@ option('engines', type: 'array', - choices: ['sw', 'gl_beta'], + choices: ['sw', 'gl_beta', 'wg_beta'], value: ['sw'], description: 'Enable Rasterizer Engine in thorvg') diff --git a/src/renderer/meson.build b/src/renderer/meson.build index c00a513c..759a9d99 100644 --- a/src/renderer/meson.build +++ b/src/renderer/meson.build @@ -8,6 +8,10 @@ if get_option('engines').contains('gl_beta') == true subdir('gl_engine') endif +if get_option('engines').contains('wg_beta') == true + subdir('wg_engine') +endif + source_file = [ 'tvgCanvas.h', 'tvgCommon.h', diff --git a/src/renderer/tvgInitializer.cpp b/src/renderer/tvgInitializer.cpp index b7326a9f..97827390 100644 --- a/src/renderer/tvgInitializer.cpp +++ b/src/renderer/tvgInitializer.cpp @@ -36,6 +36,10 @@ #include "tvgGlRenderer.h" #endif +#ifdef THORVG_WG_RASTER_SUPPORT + #include "tvgWgRenderer.h" +#endif + /************************************************************************/ /* Internal Class Implementation */ @@ -102,6 +106,11 @@ Result Initializer::init(CanvasEngine engine, uint32_t threads) noexcept if (!GlRenderer::init(threads)) return Result::FailedAllocation; nonSupport = false; #endif + } else if (engine & CanvasEngine::Wg) { + #ifdef THORVG_WG_RASTER_SUPPORT + if (!WgRenderer::init(threads)) return Result::FailedAllocation; + nonSupport = false; + #endif } else { return Result::InvalidArguments; } @@ -136,6 +145,11 @@ Result Initializer::term(CanvasEngine engine) noexcept if (!GlRenderer::term()) return Result::InsufficientCondition; nonSupport = false; #endif + } else if (engine & CanvasEngine::Wg) { + #ifdef THORVG_WG_RASTER_SUPPORT + if (!WgRenderer::term()) return Result::InsufficientCondition; + nonSupport = false; + #endif } else { return Result::InvalidArguments; } diff --git a/src/renderer/tvgWgCanvas.cpp b/src/renderer/tvgWgCanvas.cpp new file mode 100644 index 00000000..8d28ae45 --- /dev/null +++ b/src/renderer/tvgWgCanvas.cpp @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2023 the ThorVG project. All rights reserved. + + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include "tvgCanvas.h" + +#ifdef THORVG_WG_RASTER_SUPPORT + #include "tvgWgRenderer.h" +#endif + +/************************************************************************/ +/* Internal Class Implementation */ +/************************************************************************/ + +struct WgCanvas::Impl +{ +}; + + +/************************************************************************/ +/* External Class Implementation */ +/************************************************************************/ + +#ifdef THORVG_WG_RASTER_SUPPORT +WgCanvas::WgCanvas() : Canvas(WgRenderer::gen()), pImpl(new Impl) +#else +WgCanvas::WgCanvas() : Canvas(nullptr), pImpl(nullptr) +#endif +{ +} + +WgCanvas::~WgCanvas() +{ + delete pImpl; +} + +Result WgCanvas::target(void* window, uint32_t w, uint32_t h) noexcept +{ +#ifdef THORVG_WG_RASTER_SUPPORT + //We know renderer type, avoid dynamic_cast for performance. + auto renderer = static_cast(Canvas::pImpl->renderer); + if (!renderer) return Result::MemoryCorruption; + + if (!renderer->target(window, w, h)) return Result::Unknown; + + //Paints must be updated again with this new target. + Canvas::pImpl->needRefresh(); + + return Result::Success; +#endif + return Result::NonSupport; +} + +unique_ptr WgCanvas::gen() noexcept +{ +#ifdef THORVG_WG_RASTER_SUPPORT + return unique_ptr(new WgCanvas); +#endif + return nullptr; +} diff --git a/src/renderer/wg_engine/meson.build b/src/renderer/wg_engine/meson.build new file mode 100644 index 00000000..424c59fa --- /dev/null +++ b/src/renderer/wg_engine/meson.build @@ -0,0 +1,8 @@ +source_file = [ + 'tvgWgRenderer.cpp', +] + +engine_dep += [declare_dependency( + include_directories : include_directories('.'), + sources : source_file +)] diff --git a/src/renderer/wg_engine/tvgWgRenderer.cpp b/src/renderer/wg_engine/tvgWgRenderer.cpp new file mode 100644 index 00000000..3865db6d --- /dev/null +++ b/src/renderer/wg_engine/tvgWgRenderer.cpp @@ -0,0 +1,127 @@ +/* + * Copyright (c) 2023 the ThorVG project. All rights reserved. + + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include "tvgWgRenderer.h" + +WgRenderer::WgRenderer() { + initialize(); +} + +WgRenderer::~WgRenderer() { + release(); +} + +void WgRenderer::initialize() { + TVGERR("WG_ENGINE", "TODO: WgRenderer::initialize()"); +} + +void WgRenderer::release() { + TVGERR("WG_ENGINE", "TODO: WgRenderer::release()"); +} + +RenderData WgRenderer::prepare(const RenderShape& rshape, RenderData data, const RenderTransform* transform, Array& clips, uint8_t opacity, RenderUpdateFlag flags, bool clipper) { + return nullptr; +} + +RenderData WgRenderer::prepare(const Array& scene, RenderData data, const RenderTransform* transform, Array& clips, uint8_t opacity, RenderUpdateFlag flags) { + return nullptr; +} + +RenderData WgRenderer::prepare(Surface* surface, const RenderMesh* mesh, RenderData data, const RenderTransform* transform, Array& clips, uint8_t opacity, RenderUpdateFlag flags) { + return nullptr; +} + +bool WgRenderer::preRender() { + return true; +} + +bool WgRenderer::renderShape(RenderData data) { + return true; +} + +bool WgRenderer::renderImage(RenderData data) { + return true; +} + +bool WgRenderer::postRender() { + return true; +} + +bool WgRenderer::dispose(RenderData data) { + return true; +} + +RenderRegion WgRenderer::region(RenderData data) { + return { 0, 0, INT32_MAX, INT32_MAX }; +} + +RenderRegion WgRenderer::viewport() { + return { 0, 0, INT32_MAX, INT32_MAX }; +} + +bool WgRenderer::viewport(const RenderRegion& vp) { + return true; +} + +bool WgRenderer::blend(BlendMethod method) { + return false; +} + +ColorSpace WgRenderer::colorSpace() { + return ColorSpace::Unsupported; +} + +bool WgRenderer::clear() { + return true; +} + +bool WgRenderer::sync() { + return true; +} + +bool WgRenderer::target(void* window, uint32_t w, uint32_t h) { + return true; +} + +Compositor* WgRenderer::target(const RenderRegion& region, ColorSpace cs) { + return nullptr; +} + +bool WgRenderer::beginComposite(Compositor* cmp, CompositeMethod method, uint8_t opacity) { + return false; +} + +bool WgRenderer::endComposite(Compositor* cmp) { + return false; +} + +WgRenderer* WgRenderer::gen() { + return new WgRenderer(); +} + +bool WgRenderer::init(uint32_t threads) { + return true; +} + +bool WgRenderer::term() { + return true; +} diff --git a/src/renderer/wg_engine/tvgWgRenderer.h b/src/renderer/wg_engine/tvgWgRenderer.h new file mode 100644 index 00000000..4003d66c --- /dev/null +++ b/src/renderer/wg_engine/tvgWgRenderer.h @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2023 the ThorVG project. All rights reserved. + + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef _TVG_WG_RENDERER_H_ +#define _TVG_WG_RENDERER_H_ + +#include "tvgRender.h" + +class WgRenderer : public RenderMethod +{ +private: + WgRenderer(); + ~WgRenderer(); +private: + void initialize(); + void release(); +public: + RenderData prepare(const RenderShape& rshape, RenderData data, const RenderTransform* transform, Array& clips, uint8_t opacity, RenderUpdateFlag flags, bool clipper); + RenderData prepare(const Array& scene, RenderData data, const RenderTransform* transform, Array& clips, uint8_t opacity, RenderUpdateFlag flags); + RenderData prepare(Surface* surface, const RenderMesh* mesh, RenderData data, const RenderTransform* transform, Array& clips, uint8_t opacity, RenderUpdateFlag flags); + bool preRender(); + bool renderShape(RenderData data); + bool renderImage(RenderData data); + bool postRender(); + bool dispose(RenderData data); + RenderRegion region(RenderData data); + RenderRegion viewport(); + bool viewport(const RenderRegion& vp); + bool blend(BlendMethod method); + ColorSpace colorSpace(); + + bool clear(); + bool sync(); + + bool target(void* window, uint32_t w, uint32_t h); // temporary solution + Compositor* target(const RenderRegion& region, ColorSpace cs); + bool beginComposite(Compositor* cmp, CompositeMethod method, uint8_t opacity); + bool endComposite(Compositor* cmp); +public: + static WgRenderer* gen(); + static bool init(uint32_t threads); + static bool term(); +}; + +#endif /* _TVG_WG_RENDERER_H_ */